mirror of
https://github.com/makeplane/plane.git
synced 2026-09-02 12:09:14 +02:00
Review fixes for #9419: - Pin headers on the license telemetry exporter so it can no longer inherit OTEL_EXPORTER_OTLP_HEADERS and ship an operator's APM credential to telemetry.plane.so. An empty dict is falsy and does not suppress the exporters' env fallback, so the value has to be non-empty. - manage.py: apply --settings before the first plane.* import, which otherwise materializes LazySettings from the default module and silently ignored the flag (breaking the local runserver entrypoint). - Defer OTLP exporter creation to worker_process_init on the Celery prefork pool; the gRPC channel is created eagerly and is not fork-safe. - Bound interpreter-exit flushing: shutdown_on_exit=False on both providers plus an atexit hook on the existing bounded flush_otel(). With an unreachable collector a manage.py command now exits in ~3.5s instead of ~63s. - Stamp a per-process service.instance.id so gunicorn workers and prefork children stop exporting colliding cumulative http.server.* streams. - Resolve instrumentors lazily and isolate each import, and take opentelemetry-instrumentation-httpx[instruments] so a missing httpx cannot crash every entrypoint with OTEL_ENABLED=0. - Add a shared is_otel_active() (enabled AND any endpoint var, signal-specific included) used by setup, both settings modules and celery, so the log schema never changes in a process that exports nothing. - Emit the boot banner through an explicit stderr handler and name the observability loggers in LOGGING so disable_existing_loggers stops silencing export errors. - Strip whitespace in _protocol(); treat blank env values as unset so compose's ${VAR:-} interpolation no longer defeats the sampler defaults. - Deployments: give migrator the OTel env, spell out the sampler defaults, and ship OTEL_ENABLED commented out on AIO, where plane.env is exported after container env and clobbered it. - Docs: correct the emitted-metrics list, the log-schema gate, and the filelog pipeline (Docker envelope needs a second json_parser; trace context needs trace_parser, not move). - Tests: fix the conftest env leak (monkeypatch.delenv, delete-only teardown) and cover the new gating, defaults, deferred providers and logging config. Claude-Session: https://claude.ai/code/session_01BpGkdpVLNQ3Ziqcd6zK2qV
49 lines
1.9 KiB
Python
49 lines
1.9 KiB
Python
#!/usr/bin/env python
|
|
# Copyright (c) 2023-present Plane Software, Inc. and contributors
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
# See the LICENSE file for details.
|
|
|
|
import os
|
|
import sys
|
|
|
|
|
|
def _apply_settings_argument(argv: list[str]) -> None:
|
|
"""Honor `--settings=...` before anything imports the `plane` package.
|
|
|
|
Importing `plane.observability.setup` below runs `plane/__init__.py`, which
|
|
imports `plane.celery`, which touches `django.conf.settings` at module
|
|
scope. That materializes Django's LazySettings from DJANGO_SETTINGS_MODULE
|
|
long before `execute_from_command_line` gets a chance to apply `--settings`,
|
|
so the flag would be silently ignored (e.g. bin/docker-entrypoint-api-local.sh
|
|
runs `runserver --settings=plane.settings.local`). Django itself does the
|
|
same assignment, just later, so applying it here is equivalent.
|
|
"""
|
|
for index, arg in enumerate(argv):
|
|
if arg.startswith("--settings="):
|
|
os.environ["DJANGO_SETTINGS_MODULE"] = arg.split("=", 1)[1]
|
|
return
|
|
if arg == "--settings" and index + 1 < len(argv):
|
|
os.environ["DJANGO_SETTINGS_MODULE"] = argv[index + 1]
|
|
return
|
|
|
|
|
|
if __name__ == "__main__":
|
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "plane.settings.production")
|
|
_apply_settings_argument(sys.argv[1:])
|
|
|
|
# Bootstrap OpenTelemetry before Django imports so runserver and
|
|
# management commands are instrumented too. No-op unless OTel is active.
|
|
from plane.observability.setup import configure_otel
|
|
|
|
configure_otel()
|
|
|
|
try:
|
|
from django.core.management import execute_from_command_line
|
|
except ImportError as exc:
|
|
raise ImportError(
|
|
"Couldn't import Django. Are you sure it's installed and "
|
|
"available on your PYTHONPATH environment variable? Did you "
|
|
"forget to activate a virtual environment?"
|
|
) from exc
|
|
execute_from_command_line(sys.argv)
|