Код: Выделить всё
# resources
def get_default_service_instance_id():
try:
hostname = socket.gethostname() or "unknown-host"
except Exception as e:
hostname = "unknown-host"
try:
process_id = os.getpid()
except Exception as e:
process_id = "unknown-pid"
return f"{hostname}-{process_id}"
service_name = "my-service"
otlp_endpoint = "http://otel-collector:4318"
service_instance_id = get_default_service_instance_id()
resource = Resource.create(
{
SERVICE_NAME: service_name,
SERVICE_INSTANCE_ID: service_instance_id,
}
)
# traces
otlp_endpoint_traces = urljoin(otlp_endpoint, "/v1/traces")
trace_exporter = OTLPSpanExporter(endpoint=otlp_endpoint_traces)
span_processor = BatchSpanProcessor(trace_exporter)
tracer_provider = TracerProvider(resource=resource)
trace.set_tracer_provider(tracer_provider)
trace.get_tracer_provider().add_span_processor(span_processor)
# metrics
otlp_endpoint_metrics = urljoin(otlp_endpoint, "/v1/metrics")
metric_exporter = OTLPMetricExporter(endpoint=otlp_endpoint_metrics)
metric_reader = PeriodicExportingMetricReader(metric_exporter)
meter_provider = MeterProvider(resource=resource, metric_readers=[metric_reader])
metrics.set_meter_provider(meter_provider)
# instrument
DjangoInstrumentor().instrument()
Psycopg2Instrumentor().instrument()
CeleryInstrumentor().instrument()
Код: Выделить всё
import otel_config
< /code>
Хотя мои следы и метрики работают нормально в большинстве случаев, мои показатели Openelemetry нарушаются в случае работников сельдерея с режимом Prefork. Следовательно, разные дочерние процессы манипулируют одним и тем же метрическим значением, что у каждого есть своя исключительная память. Таким образом, значение в моем коллекционере меняется очень часто и неверно, поскольку это не значение агрегации всех дочерних процессов.--pool=threads< /code>) Поскольку все разные потоки одного и того же работника используют один и тот же метрический экземпляр в памяти, а конечное значение в коллекторе всегда является правильным значением агрегации. < /p>
Я пробовал несколько решений, но я получаю другие недостатки, которые я объясню в дальнейшем. Worker_process_init
Здесь я удалил импорт otel_config из настройки. PrettyPrint-Override ">
Код: Выделить всё
from celery.signals import worker_init, worker_process_init
@worker_init
def worker_init_handler(sender, **kwargs):
pool_cls = str(sender.pool_cls) if hasattr(sender, 'pool_cls') else None
if "threads" in pool_cls: # only if --pool=threads
import otel_config
@worker_process_init.connect
def worker_process_init_handler(**kwargs):
import otel_config
Мне также пришлось добавить импорт OTEL_CONFIG < /code> в мой файл wsgi.py < /code> для моего файла Django API и метриков. У меня есть обработчик сигнала task_received < /code>, который экспортирует некоторые метрики, и этот сигнал обрабатывается только в родительском процессе.
Я также не уверен, является ли это хорошей практикой для инструмента Opentelemetry в нескольких местах вместо одного места (т.е. Процессы < /li>
< /ol>
В этом подходе я попытался повторно импортировать все в случае инициализации дочернего процесса: < /p>
Код: Выделить всё
@worker_process_init.connect
def worker_process_init_handler(**kwargs):
import import otel_config
< /code>
Тем не менее, Python Otel работает на одной основе. Значение Установка MeterProvider
# trace.set_tracer_provider(tracer_provider) # this one is singleton so commented
trace._TRACER_PROVIDER = tracer_provider
...
# metrics.set_meter_provider(meter_provider) # this one is singleton so commented
metrics._internal._METER_PROVIDER = meter_provider
< /code>
Но этот подход слишком хакерский и требует других хаков на инструментах и использовании get_meter < /code> в кодовой базе.>
Подробнее здесь: https://stackoverflow.com/questions/797 ... ry-metrics