datasette/datasette
Alex Garcia 52614f6f44
Document what the database-layer spans emit, and how to turn them on
The span reference itself is generated from the registry, so this adds the
prose the generated list cannot supply: how to actually see a span, what is
deliberately never recorded, and where the instrumentation stops short.

The "how to turn it on" part is the part people get wrong. Core installs no
provider, so OTEL_TRACES_EXPORTER=console against a plain `datasette` process
emits nothing at all - that variable is read by the SDK auto-configuration
which only runs under `opentelemetry-instrument`. Documented as a warning
because it reads like a bug when you hit it. Two more measured facts get the
same treatment: the SDK's BatchSpanProcessor default schedule delay is 5000ms
(checked, not assumed - `BatchSpanProcessor._default_schedule_delay_millis()`
on opentelemetry-sdk 1.44), so nothing appears for five seconds; and without
OTEL_SERVICE_NAME the default resource reports service.name=unknown_service.

Privacy properties are stated positively rather than left implicit: SQL
truncated at 2048 characters, parameter values never recorded, no actor
identifiers, table names only from an explicit `table=` argument. The last of
those is now documented on db.execute() itself, since it is public API.

The limitations section claims only what was measured. An earlier draft said
two traces per process are orphaned by the register_output_renderer and
asgi_wrapper hooks; measuring it showed a default install emits zero spans
from either, because Datasette queries no database there - it is a plugin
that would produce the orphan. Corrected to say that.

It also deliberately does NOT say an embedder must install its provider
before Datasette's first span or get nothing. That claim is false:
ProxyTracer._tracer returns the no-op tracer without caching it when no
provider is set, so early spans are dropped and nothing is poisoned.

The telemetry.py docstring said no-op spans "cost approximately nothing".
The benchmark for this diff does not support a claim that strong - a table
page emits ~58 spans - so it now states the measurement instead: median
9.80ms to 9.98ms across 15 runs, inside a 1.4ms run-to-run spread.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 08:42:01 -07:00
..
default_permissions Deny SQLite statistics table access through a default hook 2026-09-10 16:52:25 -07:00
publish Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
static Rename modal trigger option to returnFocusTo, refs #2790 2026-09-17 15:46:34 -07:00
templates Move shared modal styles into app.css, refs #2790 2026-09-17 14:17:35 -07:00
utils Fix for GHSA-h547-rmjf-5m2m 2026-09-16 16:43:34 -07:00
views Make db.query spans match OpenTelemetry semantic conventions 2026-09-23 08:42:01 -07:00
__init__.py Add datasette.add_background_task() with supervised launch after startup (#2889) 2026-09-15 10:55:54 -07:00
__main__.py Add support for running datasette as a module (#556) 2019-07-11 09:07:44 -07:00
_pytest_plugin.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
actor_auth_cookie.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
app.py Name every span and attribute once, in a registry the docs are built from 2026-09-23 08:42:01 -07:00
background_tasks.py Add /-/tasks introspection endpoint for supervised background tasks (#2892) 2026-09-15 11:56:53 -07:00
blob_renderer.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
cli.py Use $DATASETTE_INTERNAL in absence of --internal (#2174) 2026-09-15 15:39:39 -07:00
column_types.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
csrf.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
database.py Stop marking a deliberately-short query budget as a span error 2026-09-23 08:42:01 -07:00
default_actions.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
default_column_types.py Normalize URL column schemes consistently 2026-09-08 21:16:35 -07:00
default_database_actions.py No execute-write on immutable databases 2026-05-25 12:46:21 -07:00
default_debug_menu.py Autocomplete widget and /-/debug/autocomplete test page 2026-06-13 22:59:37 -07:00
default_jump_items.py Remove source and source_key columns from JumpSQL 2026-05-23 20:41:32 -07:00
default_magic_parameters.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
default_query_actions.py Web UI to edit and delete stored queries (#2764) 2026-06-08 20:19:47 -07:00
default_table_actions.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
events.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
extras.py Return 400 for unknown _extra names on data formats 2026-07-04 16:16:02 +00:00
facets.py Fix facet selection for explicit exact filters 2026-09-16 14:56:09 -07:00
filters.py Fix float coercion for numeric filter parameters (#2876) 2026-09-15 13:14:29 -07:00
fixtures.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
forbidden.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
handle_exception.py Return CSV errors as plain text, closes #2129 2026-09-15 15:53:10 -07:00
hookspecs.py Allow extra_template_vars to resolve to None 2026-09-16 10:30:11 -07:00
inspect.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
jump.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
permissions.py Match table permission identities using SQLite case semantics 2026-09-09 08:39:03 -07:00
plugins.py Deny SQLite statistics table access through a default hook 2026-09-10 16:52:25 -07:00
renderer.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
resources.py Match table permission identities using SQLite case semantics 2026-09-09 08:39:03 -07:00
sql_functions.py _search= queries now correctly escaped, fixes #651 2019-12-29 18:48:30 +00:00
stored_queries.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
telemetry.py Document what the database-layer spans emit, and how to turn them on 2026-09-23 08:42:01 -07:00
telemetry_registry.py Stop marking a deliberately-short query budget as a span error 2026-09-23 08:42:01 -07:00
template_contexts.py Clarify template context metadata names 2026-06-23 11:30:30 -07:00
tokens.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
tracer.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
url_builder.py Upgrade to ruff>=0.16.0 (#2857) 2026-07-25 15:47:08 -07:00
version.py Release 1.0a40 2026-09-16 16:46:51 -07:00
write_sql.py Reject untrusted table-valued PRAGMA reads 2026-09-08 21:16:35 -07:00