logfire
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"
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"
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)
I get the same error when newrelic is imported first on a simple script:
import newrelic.agent
"""
"""
import logfire
Thanks @ddorian. Asked newrelic about it here: https://github.com/newrelic/newrelic-python-agent/issues/1154#issuecomment-2346252804
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.
It seems to be an issue with NewRelic, not Logfire. 🤔
Do we need to do something here?
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.
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.
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 does PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python work?
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.
Can you share a simple reproduction where PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python newrelic-admin ... raises an error?
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/