datasette/datasette
Alex Garcia f7bf49a495
Add opentelemetry-api dependency and datasette/telemetry.py scaffolding
Datasette core is gaining OpenTelemetry spans alongside the existing
hand-rolled tracer. This commit only lays the groundwork - no span is
emitted yet.

Core takes a runtime dependency on opentelemetry-api and nothing more.
It deliberately never creates a TracerProvider, configures an exporter,
or touches sampling: that belongs to whoever runs Datasette, normally
via an opentelemetry-instrument agent. Owning a provider in core was
tried in an earlier design and produced a cross-request span leak, a
process-global provider that tests could not tear down, and a sampling
env var that silently blanked output. With no provider installed every
span is a NonRecordingSpan and costs approximately nothing.

datasette/telemetry.py exposes the module-level tracer plus
sql_attribute(), which truncates SQL to 2048 characters. On a public
instance the SQL is attacker-controlled and unbounded - someone can
paste a 10MB query into ?sql= - so it must never reach a telemetry
pipeline verbatim.

opentelemetry-sdk goes in the dev dependency group only, because the
test suite needs it to assert on spans while the package itself must
not import it. tests/test_telemetry.py enforces that by importing
datasette in a fresh interpreter and inspecting sys.modules, which
catches a lazy import inside a function body that a grep would miss.

conftest.py gains a session-scoped autouse fixture installing an SDK
provider with an InMemorySpanExporter. It has to be session-scoped
because set_tracer_provider() is effectively once-per-process - a
second call logs a warning and is ignored. SimpleSpanProcessor rather
than BatchSpanProcessor, so assertions made right after a request never
race a background export thread. The otel_spans fixture that later
tickets assert against is added here too.

test_datasette_package_never_imports_the_sdk is moved to the front of
the run. Late in a serial run the pytest process holds enough threads
that the fork half of subprocess' fork+exec segfaults the interpreter
on macOS/CPython 3.13. That reproduces with any subprocess call in that
position on an unmodified tree, so it is a pre-existing hazard rather
than something this commit introduces; the repo already moves its other
subprocess-spawning tests to the front for related reasons.

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 Show correct query timings, closes #2446 2026-09-16 21:23:54 -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 Allow extra_template_vars to resolve to None 2026-09-16 10:30:11 -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 Fix remaining pytest warnings (#2928) 2026-09-16 14:50:06 -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 Add opentelemetry-api dependency and datasette/telemetry.py scaffolding 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