apm-agent-python
apm-agent-python copied to clipboard
Accessing APM with FastAPI
I'm running an API using FastAPI and trying to connect do elastic APM and give the following error:
No custom SERVICE_NAME was set -- using non-descript default 'unknown-python-service'
Could not register elasticapm.metrics.sets.cpu.CPUMetricSet metricset: psutil not found. Install it to get system and process metrics
No custom SERVICE_NAME was set -- using non-descript default 'unknown-python-service'
Could not register elasticapm.metrics.sets.cpu.CPUMetricSet metricset: psutil not found. Install it to get system and process metrics
Client object is being set more than once
Stack (most recent call last):
File "C:\Users\DOMINGRC\Factories\API_IRN\app\main.py", line 68, in <module>
uvicorn.run(app='main:app', host="0.0.0.0", port=8000, root_path="/")
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\site-packages\uvicorn\main.py", line 447, in run
server.run()
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\site-packages\uvicorn\server.py", line 68, in run
return asyncio.run(self.serve(sockets=sockets))
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\asyncio\runners.py", line 44, in run
return loop.run_until_complete(main)
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 629, in run_until_complete
self.run_forever()
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 596, in run_forever
self._run_once()
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 1890, in _run_once
handle._run()
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\asyncio\events.py", line 80, in _run
self._context.run(self._callback, *self._args)
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\site-packages\uvicorn\server.py", line 76, in serve
config.load()
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\site-packages\uvicorn\config.py", line 448, in load
self.loaded_app = import_from_string(self.app)
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\site-packages\uvicorn\importer.py", line 21, in import_from_string
module = importlib.import_module(module_str)
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 850, in exec_module
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "C:\Users\DOMINGRC\Factories\API_IRN\app\main.py", line 13, in <module>
apm = make_apm_client()
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\site-packages\elasticapm\contrib\starlette\__init__.py", line 71, in make_apm_client
return client_cls(config, **defaults)
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\site-packages\elasticapm\base.py", line 224, in __init__
set_client(self)
File "C:\Users\DOMINGRC\AppData\Local\Programs\Python\Python39\lib\site-packages\elasticapm\base.py", line 703, in set_client
logger.warning("Client object is being set more than once", stack_info=True)
My code is:
import uvicorn
from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi
from elasticapm.contrib.starlette import make_apm_client, ElasticAPM
app = FastAPI()
apm = make_apm_client({"SERVICE_NAME": 'API_IRN',
"SECRET_TOKEN": "secret",
"SERVER_URL": "127.0.0.1:8200",
"ELASTIC_APM_ENVIRONMENT": "DEV",
"VERIFY_SERVER_CERT": False})
app.add_middleware(ElasticAPM, client=apm)
@app.get("/health")
async def health():
return {"message": "IRN API is up and running..."}
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="API_IRN",
version="1.0.0",
description="API extrair dados do IRN",
routes=app.routes,
)
openapi_schema["paths"]["/api/auth"] = {
"post": {
"requestBody": {"content": {"application/json": {}}, "required": True}, "tags": ["Auth"]
}
}
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi()
if __name__ == '__main__':
try:
uvicorn.run(app='main:app', host="0.0.0.0", port=8000, root_path="/")
except Exception as ex:
print("ERROR-main" + ex.message)
The stacktrace you're seeing is just a warning, not an error. It should not be affecting the execution of your app.
However, you do want to avoid multiple Client objects because they spin up background threads. My best guess is that uvicorn is spinning up multiple workers, each of which creates a Client object. You could probably fix that by doing this:
app = FastAPI()
apm = elasticapm.get_client()
if apm is None:
apm = make_apm_client({"SERVICE_NAME": 'API_IRN',
"SECRET_TOKEN": "secret",
"SERVER_URL": "127.0.0.1:8200",
"ELASTIC_APM_ENVIRONMENT": "DEV",
"VERIFY_SERVER_CERT": False})
app.add_middleware(ElasticAPM, client=apm)
This ensures that you only create the client if it hasn't already been created.