logfire icon indicating copy to clipboard operation
logfire copied to clipboard

Incompatible with newrelic-admin CLI: "Couldn't build proto file into descriptor pool: duplicate file name opentelemetry/proto/common/v1/common.proto"

Open Giuzzilla opened this issue 1 year ago • 12 comments

Description

Hey all, thanks for your work and the fantastic product.

I was trying to try out logfire and it works fine locally, but sadly it breaks as soon as I put it on a GKE / Kubernetes pod (on the same docker container). I have a quite standard FastAPI application on Python 3.12.

EDIT: See first comment for the probable cause

The error is the following:

Traceback (most recent call last):
  File "/usr/local/bin/uvicorn", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/usr/local/lib/python3.12/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/uvicorn/main.py", line 409, in main
    run(
  File "/usr/local/lib/python3.12/site-packages/uvicorn/main.py", line 575, in run
    server.run()
  File "/usr/local/lib/python3.12/site-packages/uvicorn/server.py", line 65, in run
    return asyncio.run(self.serve(sockets=sockets))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/asyncio/runners.py", line 194, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "uvloop/loop.pyx", line 1517, in uvloop.loop.Loop.run_until_complete
  File "/usr/local/lib/python3.12/site-packages/uvicorn/server.py", line 69, in serve
    await self._serve(sockets)
  File "/usr/local/lib/python3.12/site-packages/uvicorn/server.py", line 76, in _serve
    config.load()
  File "/usr/local/lib/python3.12/site-packages/uvicorn/config.py", line 433, in load
    self.loaded_app = import_from_string(self.app)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/uvicorn/importer.py", line 19, in import_from_string
    module = importlib.import_module(module_str)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/importlib/__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "/home/xxx/xxx/xxx/app.py", line 3, in <module>
    from fastapi import Depends, FastAPI, Request
  File "/usr/local/lib/python3.12/site-packages/fastapi/__init__.py", line 7, in <module>
    from .applications import FastAPI as FastAPI
  File "/usr/local/lib/python3.12/site-packages/fastapi/applications.py", line 16, in <module>
    from fastapi import routing
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "/usr/local/lib/python3.12/site-packages/newrelic/api/import_hook.py", line 174, in exec_module
    self.loader.exec_module(module)
  File "/usr/local/lib/python3.12/site-packages/fastapi/routing.py", line 22, in <module>
    from fastapi import params
  File "/usr/local/lib/python3.12/site-packages/fastapi/params.py", line 5, in <module>
    from fastapi.openapi.models import Example
  File "/usr/local/lib/python3.12/site-packages/fastapi/openapi/models.py", line 4, in <module>
    from fastapi._compat import (
  File "/usr/local/lib/python3.12/site-packages/fastapi/_compat.py", line 20, in <module>
    from fastapi.exceptions import RequestErrorModel
  File "/usr/local/lib/python3.12/site-packages/fastapi/exceptions.py", line 139, in <module>
    RequestErrorModel: Type[BaseModel] = create_model("Request")
                                         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/pydantic/main.py", line 1531, in create_model
    return meta(
           ^^^^^
  File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_model_construction.py", line 202, in __new__
    complete_model_class(
  File "/usr/local/lib/python3.12/site-packages/pydantic/_internal/_model_construction.py", line 557, in complete_model_class
    cls.__pydantic_validator__ = create_schema_validator(
                                 ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/pydantic/plugin/_schema_validator.py", line 37, in create_schema_validator
    plugins = get_plugins()
              ^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/pydantic/plugin/_loader.py", line 47, in get_plugins
    _plugins[entry_point.value] = entry_point.load()
                                  ^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/importlib/metadata/__init__.py", line 205, in load
    module = import_module(match.group('module'))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/importlib/__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/logfire/__init__.py", line 9, in <module>
    from ._internal.config import (
  File "/usr/local/lib/python3.12/site-packages/logfire/_internal/config.py", line 22, in <module>
    from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
  File "/usr/local/lib/python3.12/site-packages/opentelemetry/exporter/otlp/proto/http/metric_exporter/__init__.py", line 25, in <module>
    from opentelemetry.exporter.otlp.proto.common._internal import (
  File "/usr/local/lib/python3.12/site-packages/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 31, in <module>
    from opentelemetry.proto.common.v1.common_pb2 import (
  File "/usr/local/lib/python3.12/site-packages/opentelemetry/proto/common/v1/common_pb2.py", line 17, in <module>
    DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n*opentelemetry/proto/common/v1/common.proto\x12\x1dopentelemetry.proto.common.v1\"\x8c\x02\n\x08\x41nyValue\x12\x16\n\x0cstring_value\x18\x01 \x01(\tH\x00\x12\x14\n\nbool_value\x18\x02 \x01(\x08H\x00\x12\x13\n\tint_value\x18\x03 \x01(\x03H\x00\x12\x16\n\x0c\x64ouble_value\x18\x04 \x01(\x01H\x00\x12@\n\x0b\x61rray_value\x18\x05 \x01(\x0b\x32).opentelemetry.proto.common.v1.ArrayValueH\x00\x12\x43\n\x0ckvlist_value\x18\x06 \x01(\x0b\x32+.opentelemetry.proto.common.v1.KeyValueListH\x00\x12\x15\n\x0b\x62ytes_value\x18\x07 \x01(\x0cH\x00\x42\x07\n\x05value\"E\n\nArrayValue\x12\x37\n\x06values\x18\x01 \x03(\x0b\x32\'.opentelemetry.proto.common.v1.AnyValue\"G\n\x0cKeyValueList\x12\x37\n\x06values\x18\x01 \x03(\x0b\x32\'.opentelemetry.proto.common.v1.KeyValue\"O\n\x08KeyValue\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x36\n\x05value\x18\x02 \x01(\x0b\x32\'.opentelemetry.proto.common.v1.AnyValue\"\x94\x01\n\x14InstrumentationScope\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07version\x18\x02 \x01(\t\x12;\n\nattributes\x18\x03 \x03(\x0b\x32\'.opentelemetry.proto.common.v1.KeyValue\x12 \n\x18\x64ropped_attributes_count\x18\x04 \x01(\rB{\n io.opentelemetry.proto.common.v1B\x0b\x43ommonProtoP\x01Z(go.opentelemetry.io/proto/otlp/common/v1\xaa\x02\x1dOpenTelemetry.Proto.Common.V1b\x06proto3')
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: Couldn't build proto file into descriptor pool: duplicate file name opentelemetry/proto/common/v1/common.proto

I don't have opentelemetry among my standard dependencies, the opentelemetry version is automatically resolved by poetry when installing logfire with poetry add logfire[fastapi, psycopg]. (I use poetry as a package manager & export versions to requirements. The container only sees the exported requirements.txt). ~~A possible issue may be a conflicting protobuf version installed automatically from google cloud dependencies (protobuf==4.25.3)?~~

As an additional info: the same error happens on a similar configuration where I have installed logfire on a Flask app (as opposed to fastapi): as soon as I import any pydantic model it crashes. (In this case, I'm not even importing logfire)

Python, Logfire & OS Versions, related packages (not required)

logfire="0.35.0"
platform="Linux-5.14.0-1054-oem-x86_64-with-glibc2.31"
python="3.12.3 (main, May 14 2024, 07:54:30) [GCC 10.2.1 20210110]"
[related_packages]
requests="2.32.2"
pydantic="2.7.0"
protobuf="4.25.3"
rich="13.7.1"
executing="2.0.1"
opentelemetry-api="1.24.0"
opentelemetry-exporter-otlp-proto-common="1.24.0"
opentelemetry-exporter-otlp-proto-http="1.24.0"
opentelemetry-instrumentation="0.45b0"
opentelemetry-instrumentation-asgi="0.45b0"
opentelemetry-instrumentation-dbapi="0.45b0"
opentelemetry-instrumentation-fastapi="0.45b0"
opentelemetry-instrumentation-psycopg="0.45b0"
opentelemetry-proto="1.24.0"
opentelemetry-sdk="1.24.0"
opentelemetry-semantic-conventions="0.45b0"
opentelemetry-util-http="0.45b0"

Giuzzilla avatar May 24 '24 14:05 Giuzzilla

I didn't think about it initially and it's quite funny, but the issue seems related to newrelic-admin CLI to automatically instrument the application :) (I don't run it locally, that's practically the only difference between the setups)

Giuzzilla avatar May 24 '24 15:05 Giuzzilla

I get the same error when newrelic is imported first on a simple script:

import newrelic.agent

"""
"""
import logfire

ddorian avatar Sep 12 '24 12:09 ddorian

Thanks @ddorian. Asked newrelic about it here: https://github.com/newrelic/newrelic-python-agent/issues/1154#issuecomment-2346252804

alexmojaki avatar Sep 12 '24 13:09 alexmojaki

This workaround works:

from newrelic.core.config import global_settings

settings = global_settings()
settings.debug.otlp_content_encoding = "json"

# Now you can import these in either order
import newrelic.agent
import logfire

logfire.configure()

logfire.info("hi")

Based on the lack of response from newrelic, we will probably have to do something about this ourselves in the SDK, not sure what.

alexmojaki avatar Nov 15 '24 20:11 alexmojaki

It seems to be an issue with NewRelic, not Logfire. 🤔

Do we need to do something here?

Kludex avatar Dec 24 '24 10:12 Kludex

Setting the env var PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python seems to prevent the error, although I don't know what the implications of this are.

alexmojaki avatar Feb 06 '25 12:02 alexmojaki

I don't know how to get the error using the newrelic-admin command to test, e.g.newrelic-admin run-python -c 'import logfire; logfire.configure()' works fine without the env var.

alexmojaki avatar Feb 06 '25 12:02 alexmojaki

This is still happening in conjunction with ChromaDB & unfortunately, the workaround of settings.debug.oltp_content_encoding doesn't work since the wrong protobuf gets registered before you can even run that line, so the damage is done. The only solution for now was to disable Newrelic completely. See https://github.com/newrelic/newrelic-python-agent/issues/1154 for details

tspecht avatar Mar 19 '25 14:03 tspecht

@tspecht does PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python work?

alexmojaki avatar Mar 19 '25 14:03 alexmojaki

It does but then throwing a bunch of other errors, so not a fix. Only option for now was to not use newrelic-admin, do the setting mentioned above first and then initialize the agent manually. Not sure why NewRelic closed that issue while it's still clearly not fixed.

tspecht avatar Mar 19 '25 14:03 tspecht

Can you share a simple reproduction where PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python newrelic-admin ... raises an error?

alexmojaki avatar Mar 19 '25 14:03 alexmojaki

Please check the version of newrelic in your image/system. The newrelic team has provided a fix in its latest version 10.12.0 - https://docs.newrelic.com/docs/release-notes/agent-release-notes/python-release-notes/python-agent-101200/

shetty-personal avatar May 20 '25 18:05 shetty-personal