mirror of
https://github.com/simonw/datasette.git
synced 2026-09-02 22:54:08 +02:00
Both histograms declared unit="s" but inherited OpenTelemetry's default boundaries, which are tuned for milliseconds - so every SQLite query landed in the single (0, 5] second bucket and every quantile query returned noise. The boundaries are the semantic conventions' recommended set for db.client.operation.duration plus 0.0001 and 0.0005 at the bottom, since SQLite is in-process and many real queries take tens of microseconds. (Adapted from 024f2029: that commit assumed the metrics were already in telemetry_registry.py, which on this lineage held spans only - so this commit also brings the MetricName registry machinery, the registry entries for all eight phase-3 metrics, the cog-generated Metric reference in internals.rst, and the datasette.operation attribute. The template and facet histograms it also touched belong to phase 5 and are not included.) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F2h9ANGZ7paWSpqs5DUAcG
56 lines
2 KiB
Python
56 lines
2 KiB
Python
"""
|
|
Render the span reference in ``internals.rst`` from
|
|
``datasette/telemetry_registry.py``.
|
|
|
|
Driven by cog, and ``cog --check docs/*.rst`` runs in CI - so adding a span
|
|
without documenting it, or documenting one that no longer exists, is a build
|
|
failure rather than something a reader discovers later.
|
|
"""
|
|
|
|
|
|
def _attribute_lines(cog, attributes):
|
|
if not attributes:
|
|
cog.out(" No attributes.\n\n")
|
|
return
|
|
cog.out(" Attributes:\n\n")
|
|
for attribute in attributes:
|
|
suffix = " *(optional)*" if attribute.optional else ""
|
|
cog.out(f" - ``{attribute}``{suffix} - {attribute.description}\n")
|
|
cog.out("\n")
|
|
|
|
|
|
def spans(cog):
|
|
from opentelemetry.trace import SpanKind
|
|
|
|
from datasette.telemetry_registry import SPANS
|
|
|
|
cog.out("\n")
|
|
for span in SPANS:
|
|
title = f"{span}*" if span.prefix else str(span)
|
|
cog.out(f"``{title}``\n")
|
|
cog.out(f" {span.description}\n\n")
|
|
# INTERNAL is the default and the overwhelming majority of spans -
|
|
# printing it on every one would be noise. Only the exceptional case,
|
|
# a real database call, is worth calling out.
|
|
if span.kind != SpanKind.INTERNAL:
|
|
cog.out(f" Kind: ``{span.kind.name}``.\n\n")
|
|
_attribute_lines(cog, span.attributes)
|
|
|
|
|
|
def metrics(cog):
|
|
from datasette.telemetry_registry import METRICS
|
|
|
|
cog.out("\n")
|
|
for metric in METRICS:
|
|
cog.out(f"``{metric}``\n")
|
|
cog.out(f" {metric.kind}, unit ``{metric.unit}``. {metric.description}\n\n")
|
|
if metric.buckets:
|
|
boundaries = ", ".join(f"``{boundary}``" for boundary in metric.buckets)
|
|
cog.out(f" Bucket boundaries: {boundaries}.\n\n")
|
|
if metric.attributes:
|
|
cog.out(" Attributes:\n\n")
|
|
for attribute in metric.attributes:
|
|
cog.out(f" - ``{attribute}`` - {attribute.description}\n")
|
|
cog.out("\n")
|
|
else:
|
|
cog.out(" No attributes.\n\n")
|