在Python FastAPI应用程序中导入自定义APM处理器



我在Python中使用Elasticsearch APM来记录FastAPI应用程序的请求。

有一种机制可以通过简单地指定自定义处理器函数的模块路径来加载自定义处理器。

我的应用程序布局如下:

app
├── __init__.py
├── apm_processors.py
├── main.py
└── version.py

我的apm_processors.py文件定义了以下功能:

def ip_processor(client, event):
# process the event
pass

所以,在我的应用程序中,我做到了:

# other imports
from elasticapm.contrib.starlette import make_apm_client, ElasticAPM
from . import apm_processors

为了建立APM,我称之为:

apm_config = {
"SERVICE_NAME": config('ELASTIC_APM_SERVICE_NAME', cast=str, default="Server"),
"SECRET_TOKEN": str(config('ELASTIC_APM_SECRET_TOKEN', cast=Secret, default="")),
"SERVER_URL": config('ELASTIC_APM_SERVER_URL', cast=str, default="http://localhost:8200"),
"PROCESSORS": (
"elasticapm.processors.sanitize_http_request_cookies",
"elasticapm.processors.sanitize_http_headers",
"apm_processors.ip_processor"
)
}
apm = make_apm_client(apm_config)
app = FastAPI()
# other app setup
app.add_middleware(ElasticAPM, client=apm)

这引发了一个错误:

ModuleNotFoundError: No module named 'apm_processors'

具有以下堆栈:

Traceback (most recent call last):
File "/usr/local/lib/python3.9/multiprocessing/process.py", line 315, in _bootstrap
self.run()
File "/usr/local/lib/python3.9/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "/usr/local/lib/python3.9/site-packages/uvicorn/subprocess.py", line 76, in subprocess_started
target(sockets=sockets)
File "/usr/local/lib/python3.9/site-packages/uvicorn/server.py", line 60, in run
return asyncio.run(self.serve(sockets=sockets))
File "/usr/local/lib/python3.9/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/usr/local/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete
return future.result()
File "/usr/local/lib/python3.9/site-packages/uvicorn/server.py", line 67, in serve
config.load()
File "/usr/local/lib/python3.9/site-packages/uvicorn/config.py", line 458, in load
self.loaded_app = import_from_string(self.app)
File "/usr/local/lib/python3.9/site-packages/uvicorn/importer.py", line 24, in import_from_string
raise exc from None
File "/usr/local/lib/python3.9/site-packages/uvicorn/importer.py", line 21, in import_from_string
module = importlib.import_module(module_str)
File "/usr/local/lib/python3.9/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 "/home/statisticsserver/./app/main.py", line 75, in <module>
apm = make_apm_client(apm_config)
File "/usr/local/lib/python3.9/site-packages/elasticapm/contrib/starlette/__init__.py", line 70, in make_apm_client
return client_cls(config, **defaults)
File "/usr/local/lib/python3.9/site-packages/elasticapm/base.py", line 153, in __init__
"processors": self.load_processors(),
File "/usr/local/lib/python3.9/site-packages/elasticapm/base.py", line 640, in load_processors
return [seen.setdefault(path, import_string(path)) for path in processors if path not in seen]
File "/usr/local/lib/python3.9/site-packages/elasticapm/base.py", line 640, in <listcomp>
return [seen.setdefault(path, import_string(path)) for path in processors if path not in seen]
File "/usr/local/lib/python3.9/site-packages/elasticapm/utils/module_import.py", line 47, in import_string
module = import_module(module_path)
File "/usr/local/lib/python3.9/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 984, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'apm_processors'

据我所知,它使用import_module导入指定的函数,但出于某种原因,它声称没有这样的模块——尽管我实际上可以导入它

如何指定处理器?

由于应用程序的上下文/主模块是app,因此导入应按如下方式进行:

"PROCESSORS": (
"elasticapm.processors.sanitize_http_request_cookies",
"elasticapm.processors.sanitize_http_headers",
"app.apm_processors.ip_processor"
)

这样,导入成功,并且将为每个事件调用函数。

最新更新