Add optional OpenTelemetry integration via kaya-otel
CI / Build and push docker image (push) Successful in 1m31s

Adds an OTEL_ENABLED opt-in that assembles kaya-otel's OTelMixin into
the app, exporting HTTP/WebSocket traces and request metrics to an
OTLP/HTTP collector. Configured through OTEL_SERVICE_NAME,
OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS and
OTEL_EXCLUDED_PATHS (defaults to the /api/health probe endpoint).

kaya-otel is an optional 'otel' extra imported lazily, so default
installs and the test suite do not need the OpenTelemetry packages.
The kaya dependencies are bumped to 0.0.4, which kaya-otel requires.
This commit is contained in:
2026-09-19 10:09:31 +08:00
parent 93d041b004
commit af480bb9b7
9 changed files with 216 additions and 8 deletions
+35
View File
@@ -130,5 +130,40 @@ class CorsSettingsTests(unittest.TestCase):
self.assertEqual(3600, settings.cors_max_age)
class OTelSettingsTests(unittest.TestCase):
def test_otel_disabled_by_default(self):
settings = _settings({})
self.assertFalse(settings.otel_enabled)
self.assertEqual("tavolo", settings.otel_service_name)
self.assertIsNone(settings.otel_exporter_endpoint)
self.assertIsNone(settings.otel_exporter_headers)
def test_otel_enabled_parses_boolean(self):
for value in ("1", "true", "TRUE", "yes", "on"):
self.assertTrue(_settings({"OTEL_ENABLED": value}).otel_enabled)
for value in ("0", "false", "no", "off", "anything-else"):
self.assertFalse(_settings({"OTEL_ENABLED": value}).otel_enabled)
def test_otel_settings_are_passed_through(self):
settings = _settings({
"OTEL_SERVICE_NAME": "cards",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://collector:4318",
"OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer t, X-Tenant=one",
})
self.assertEqual("cards", settings.otel_service_name)
self.assertEqual("http://collector:4318", settings.otel_exporter_endpoint)
self.assertEqual(
("Authorization=Bearer t", "X-Tenant=one"),
settings.otel_exporter_headers,
)
def test_otel_excluded_paths_defaults_to_health_endpoint(self):
self.assertEqual(("/api/health",), _settings({}).otel_excluded_paths)
def test_otel_excluded_paths_parses_comma_separated_list(self):
settings = _settings({"OTEL_EXCLUDED_PATHS": "/api/health, /metrics"})
self.assertEqual(("/api/health", "/metrics"), settings.otel_excluded_paths)
if __name__ == "__main__":
unittest.main()