traceable-agent 1.3.0__tar.gz → 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {traceable-agent-1.3.0/src/traceable_agent.egg-info → traceable-agent-2.0.0}/PKG-INFO +6 -6
- traceable-agent-2.0.0/setup.py +67 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0/src/traceable_agent.egg-info}/PKG-INFO +6 -6
- traceable-agent-2.0.0/src/traceable_agent.egg-info/SOURCES.txt +45 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/src/traceable_agent.egg-info/entry_points.txt +1 -0
- traceable-agent-2.0.0/src/traceable_agent.egg-info/requires.txt +28 -0
- traceable-agent-2.0.0/src/traceableai/agent.py +186 -0
- traceable-agent-2.0.0/src/traceableai/agent_init.py +177 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/src/traceableai/autoinstrumentation/sitecustomize.py +1 -9
- traceable-agent-2.0.0/src/traceableai/config/__init__.py +0 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/src/traceableai/config/config.py +11 -10
- traceable-agent-2.0.0/src/traceableai/config/config_pb2.py +91 -0
- traceable-agent-2.0.0/src/traceableai/config/default.py +54 -0
- traceable-agent-2.0.0/src/traceableai/config/environment.py +150 -0
- traceable-agent-2.0.0/src/traceableai/constants.py +9 -0
- traceable-agent-2.0.0/src/traceableai/custom_logger.py +41 -0
- traceable-agent-2.0.0/src/traceableai/env.py +7 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/src/traceableai/filter/__init__.py +6 -2
- traceable-agent-2.0.0/src/traceableai/filter/filter.py +18 -0
- traceable-agent-2.0.0/src/traceableai/filter/registry.py +42 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/src/traceableai/filter/traceable.py +19 -8
- traceable-agent-2.0.0/src/traceableai/instrumentation/__init__.py +263 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/aiohttp/__init__.py +182 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/aws_lambda/__init__.py +199 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/boto/__init__.py +11 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/botocore/__init__.py +11 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/django/__init__.py +64 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/django/django_auto_instrumentation_compat.py +70 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/fast_api/__init__.py +189 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/fast_api/fast_api_auto_instrumentation_compat.py +65 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/flask/__init__.py +183 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/grpc/__init__.py +265 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/instrumentation_definitions.py +99 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/mysql/__init__.py +11 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/postgresql/__init__.py +13 -0
- traceable-agent-2.0.0/src/traceableai/instrumentation/requests/__init__.py +34 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/src/traceableai/version.py +1 -1
- traceable-agent-1.3.0/setup.py +0 -42
- traceable-agent-1.3.0/src/traceable_agent.egg-info/SOURCES.txt +0 -26
- traceable-agent-1.3.0/src/traceable_agent.egg-info/requires.txt +0 -4
- traceable-agent-1.3.0/src/traceableai/agent.py +0 -77
- traceable-agent-1.3.0/src/traceableai/config/__init__.py +0 -5
- traceable-agent-1.3.0/src/traceableai/config/default.py +0 -25
- traceable-agent-1.3.0/src/traceableai/config/environment.py +0 -54
- traceable-agent-1.3.0/src/traceableai/config/traceable_config_pb2.py +0 -539
- traceable-agent-1.3.0/src/traceableai/config_wrapper.py +0 -128
- traceable-agent-1.3.0/src/traceableai/hypertrace_env_override.py +0 -20
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/MANIFEST.in +0 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/README.md +0 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/pyproject.toml +0 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/setup.cfg +0 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/src/traceable_agent.egg-info/dependency_links.txt +0 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/src/traceable_agent.egg-info/top_level.txt +0 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/src/traceableai/__init__.py +0 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/src/traceableai/autoinstrumentation/__init__.py +0 -0
- {traceable-agent-1.3.0 → traceable-agent-2.0.0}/src/traceableai/autoinstrumentation/wrapper.py +0 -0
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: traceable-agent
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Traceable.ai Python Agent
|
|
5
5
|
Home-page: https://traceable.ai
|
|
6
6
|
Author: Traceable.ai
|
|
7
|
+
License: UNKNOWN
|
|
8
|
+
Platform: UNKNOWN
|
|
7
9
|
Classifier: Programming Language :: Python :: 3
|
|
8
10
|
Classifier: Operating System :: OS Independent
|
|
9
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.8
|
|
10
12
|
Description-Content-Type: text/markdown
|
|
11
|
-
Requires-Dist: hypertrace-agent==0.15.0
|
|
12
|
-
Requires-Dist: psutil
|
|
13
|
-
Requires-Dist: distro==1.6.0
|
|
14
|
-
Requires-Dist: cffi
|
|
15
13
|
|
|
16
14
|
# Python Agent
|
|
17
15
|
|
|
@@ -95,3 +93,5 @@ git submodule update --init --recursive
|
|
|
95
93
|
```
|
|
96
94
|
- Test applications
|
|
97
95
|
1. Refer to `docker/test_apps/`.
|
|
96
|
+
|
|
97
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# pylint: skip-file
|
|
2
|
+
import os
|
|
3
|
+
from setuptools import setup, find_packages, Extension
|
|
4
|
+
|
|
5
|
+
exec(open('src/traceableai/version.py').read())
|
|
6
|
+
|
|
7
|
+
with open("README.md", "r", encoding="utf-8") as fh:
|
|
8
|
+
long_description = fh.read()
|
|
9
|
+
|
|
10
|
+
setup(
|
|
11
|
+
name="traceable-agent",
|
|
12
|
+
version=__version__,
|
|
13
|
+
author="Traceable.ai",
|
|
14
|
+
description="Traceable.ai Python Agent",
|
|
15
|
+
url="https://traceable.ai",
|
|
16
|
+
classifiers=[
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Operating System :: OS Independent"
|
|
19
|
+
],
|
|
20
|
+
package_dir={"": "src"},
|
|
21
|
+
packages=find_packages(where="src"),
|
|
22
|
+
include_package_data=True,
|
|
23
|
+
python_requires=">=3.8",
|
|
24
|
+
ext_modules=[
|
|
25
|
+
# this option will let wheel builder know to package c extensions when ran from CI. No effect for source tar installs
|
|
26
|
+
Extension(
|
|
27
|
+
name='traceableai.filter._libtraceable',
|
|
28
|
+
sources=[],
|
|
29
|
+
optional=os.environ.get('CIBUILDWHEEL', '0') != '1'
|
|
30
|
+
)
|
|
31
|
+
],
|
|
32
|
+
install_requires=[
|
|
33
|
+
"opentelemetry-api==1.26.0",
|
|
34
|
+
"opentelemetry-exporter-otlp==1.26.0",
|
|
35
|
+
"opentelemetry-instrumentation==0.47b0",
|
|
36
|
+
"opentelemetry-instrumentation-aiohttp-client==0.47b0",
|
|
37
|
+
"opentelemetry-instrumentation-boto==0.47b0",
|
|
38
|
+
"opentelemetry-instrumentation-botocore==0.47b0",
|
|
39
|
+
"opentelemetry-instrumentation-wsgi==0.47b0",
|
|
40
|
+
"opentelemetry-instrumentation-fastapi==0.47b0",
|
|
41
|
+
"opentelemetry-instrumentation-flask==0.47b0",
|
|
42
|
+
"opentelemetry-instrumentation-mysql==0.47b0",
|
|
43
|
+
"opentelemetry-instrumentation-psycopg2==0.47b0",
|
|
44
|
+
"opentelemetry-instrumentation-requests==0.47b0",
|
|
45
|
+
"opentelemetry-instrumentation-grpc==0.47b0",
|
|
46
|
+
"opentelemetry-instrumentation-django==0.47b0",
|
|
47
|
+
"opentelemetry-instrumentation-aws-lambda==0.47b0",
|
|
48
|
+
"opentelemetry-propagator-b3==1.26.0",
|
|
49
|
+
"opentelemetry-proto==1.26.0",
|
|
50
|
+
"opentelemetry-sdk==1.26.0",
|
|
51
|
+
"opentelemetry-util-http==0.47b0",
|
|
52
|
+
"google>=3.0.0",
|
|
53
|
+
"pyyaml",
|
|
54
|
+
"protobuf<5",
|
|
55
|
+
"psutil",
|
|
56
|
+
"distro==1.6.0",
|
|
57
|
+
"cffi",
|
|
58
|
+
"setuptools",
|
|
59
|
+
"jaraco.text",
|
|
60
|
+
"platformdirs"
|
|
61
|
+
],
|
|
62
|
+
entry_points={
|
|
63
|
+
'console_scripts': [
|
|
64
|
+
'traceableai-instrument = traceableai.autoinstrumentation.wrapper:run',
|
|
65
|
+
],
|
|
66
|
+
}
|
|
67
|
+
)
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: traceable-agent
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Traceable.ai Python Agent
|
|
5
5
|
Home-page: https://traceable.ai
|
|
6
6
|
Author: Traceable.ai
|
|
7
|
+
License: UNKNOWN
|
|
8
|
+
Platform: UNKNOWN
|
|
7
9
|
Classifier: Programming Language :: Python :: 3
|
|
8
10
|
Classifier: Operating System :: OS Independent
|
|
9
|
-
Requires-Python: >=3.
|
|
11
|
+
Requires-Python: >=3.8
|
|
10
12
|
Description-Content-Type: text/markdown
|
|
11
|
-
Requires-Dist: hypertrace-agent==0.15.0
|
|
12
|
-
Requires-Dist: psutil
|
|
13
|
-
Requires-Dist: distro==1.6.0
|
|
14
|
-
Requires-Dist: cffi
|
|
15
13
|
|
|
16
14
|
# Python Agent
|
|
17
15
|
|
|
@@ -95,3 +93,5 @@ git submodule update --init --recursive
|
|
|
95
93
|
```
|
|
96
94
|
- Test applications
|
|
97
95
|
1. Refer to `docker/test_apps/`.
|
|
96
|
+
|
|
97
|
+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
MANIFEST.in
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
setup.cfg
|
|
5
|
+
setup.py
|
|
6
|
+
src/traceable_agent.egg-info/PKG-INFO
|
|
7
|
+
src/traceable_agent.egg-info/SOURCES.txt
|
|
8
|
+
src/traceable_agent.egg-info/dependency_links.txt
|
|
9
|
+
src/traceable_agent.egg-info/entry_points.txt
|
|
10
|
+
src/traceable_agent.egg-info/requires.txt
|
|
11
|
+
src/traceable_agent.egg-info/top_level.txt
|
|
12
|
+
src/traceableai/__init__.py
|
|
13
|
+
src/traceableai/agent.py
|
|
14
|
+
src/traceableai/agent_init.py
|
|
15
|
+
src/traceableai/constants.py
|
|
16
|
+
src/traceableai/custom_logger.py
|
|
17
|
+
src/traceableai/env.py
|
|
18
|
+
src/traceableai/version.py
|
|
19
|
+
src/traceableai/autoinstrumentation/__init__.py
|
|
20
|
+
src/traceableai/autoinstrumentation/sitecustomize.py
|
|
21
|
+
src/traceableai/autoinstrumentation/wrapper.py
|
|
22
|
+
src/traceableai/config/__init__.py
|
|
23
|
+
src/traceableai/config/config.py
|
|
24
|
+
src/traceableai/config/config_pb2.py
|
|
25
|
+
src/traceableai/config/default.py
|
|
26
|
+
src/traceableai/config/environment.py
|
|
27
|
+
src/traceableai/filter/__init__.py
|
|
28
|
+
src/traceableai/filter/filter.py
|
|
29
|
+
src/traceableai/filter/registry.py
|
|
30
|
+
src/traceableai/filter/traceable.py
|
|
31
|
+
src/traceableai/instrumentation/__init__.py
|
|
32
|
+
src/traceableai/instrumentation/instrumentation_definitions.py
|
|
33
|
+
src/traceableai/instrumentation/aiohttp/__init__.py
|
|
34
|
+
src/traceableai/instrumentation/aws_lambda/__init__.py
|
|
35
|
+
src/traceableai/instrumentation/boto/__init__.py
|
|
36
|
+
src/traceableai/instrumentation/botocore/__init__.py
|
|
37
|
+
src/traceableai/instrumentation/django/__init__.py
|
|
38
|
+
src/traceableai/instrumentation/django/django_auto_instrumentation_compat.py
|
|
39
|
+
src/traceableai/instrumentation/fast_api/__init__.py
|
|
40
|
+
src/traceableai/instrumentation/fast_api/fast_api_auto_instrumentation_compat.py
|
|
41
|
+
src/traceableai/instrumentation/flask/__init__.py
|
|
42
|
+
src/traceableai/instrumentation/grpc/__init__.py
|
|
43
|
+
src/traceableai/instrumentation/mysql/__init__.py
|
|
44
|
+
src/traceableai/instrumentation/postgresql/__init__.py
|
|
45
|
+
src/traceableai/instrumentation/requests/__init__.py
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
opentelemetry-api==1.26.0
|
|
2
|
+
opentelemetry-exporter-otlp==1.26.0
|
|
3
|
+
opentelemetry-instrumentation==0.47b0
|
|
4
|
+
opentelemetry-instrumentation-aiohttp-client==0.47b0
|
|
5
|
+
opentelemetry-instrumentation-boto==0.47b0
|
|
6
|
+
opentelemetry-instrumentation-botocore==0.47b0
|
|
7
|
+
opentelemetry-instrumentation-wsgi==0.47b0
|
|
8
|
+
opentelemetry-instrumentation-fastapi==0.47b0
|
|
9
|
+
opentelemetry-instrumentation-flask==0.47b0
|
|
10
|
+
opentelemetry-instrumentation-mysql==0.47b0
|
|
11
|
+
opentelemetry-instrumentation-psycopg2==0.47b0
|
|
12
|
+
opentelemetry-instrumentation-requests==0.47b0
|
|
13
|
+
opentelemetry-instrumentation-grpc==0.47b0
|
|
14
|
+
opentelemetry-instrumentation-django==0.47b0
|
|
15
|
+
opentelemetry-instrumentation-aws-lambda==0.47b0
|
|
16
|
+
opentelemetry-propagator-b3==1.26.0
|
|
17
|
+
opentelemetry-proto==1.26.0
|
|
18
|
+
opentelemetry-sdk==1.26.0
|
|
19
|
+
opentelemetry-util-http==0.47b0
|
|
20
|
+
google>=3.0.0
|
|
21
|
+
pyyaml
|
|
22
|
+
protobuf<5
|
|
23
|
+
psutil
|
|
24
|
+
distro==1.6.0
|
|
25
|
+
cffi
|
|
26
|
+
setuptools
|
|
27
|
+
jaraco.text
|
|
28
|
+
platformdirs
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import threading
|
|
4
|
+
import traceback
|
|
5
|
+
|
|
6
|
+
import distro
|
|
7
|
+
|
|
8
|
+
from traceableai import constants
|
|
9
|
+
from traceableai.agent_init import AgentInit
|
|
10
|
+
from traceableai.config.config import Config
|
|
11
|
+
from traceableai.custom_logger import get_custom_logger
|
|
12
|
+
from traceableai.env import get_env_value
|
|
13
|
+
from traceableai.filter.registry import Registry
|
|
14
|
+
from traceableai.instrumentation.instrumentation_definitions import SUPPORTED_LIBRARIES, get_instrumentation_wrapper, \
|
|
15
|
+
FLASK_KEY, DJANGO_KEY, FAST_API_KEY, LAMBDA
|
|
16
|
+
from traceableai.version import __version__ # pylint:disable=C0413
|
|
17
|
+
logger = get_custom_logger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Agent():
|
|
21
|
+
_instance = None
|
|
22
|
+
_singleton_lock = threading.Lock()
|
|
23
|
+
|
|
24
|
+
def __new__(cls):
|
|
25
|
+
'''constructor'''
|
|
26
|
+
if cls._instance is None:
|
|
27
|
+
with cls._singleton_lock:
|
|
28
|
+
logger.debug('Creating Agent')
|
|
29
|
+
logger.debug('Python version: %s', sys.version)
|
|
30
|
+
logger.debug('Traceable Agent version: %s', __version__)
|
|
31
|
+
cls._instance = super(Agent, cls).__new__(cls)
|
|
32
|
+
else:
|
|
33
|
+
logger.debug('Using existing Agent.')
|
|
34
|
+
return cls._instance
|
|
35
|
+
|
|
36
|
+
def __init__(self):
|
|
37
|
+
self._initialized = False
|
|
38
|
+
if not self._initialized: # pylint: disable=E0203:
|
|
39
|
+
logger.debug('Initializing Agent.')
|
|
40
|
+
if not self.is_enabled():
|
|
41
|
+
return
|
|
42
|
+
try:
|
|
43
|
+
self._config = Config()
|
|
44
|
+
self._init = AgentInit(self._config)
|
|
45
|
+
self._initialized = True
|
|
46
|
+
except Exception as err: # pylint: disable=W0703
|
|
47
|
+
logger.error('Failed to initialize Agent: exception=%s, stacktrace=%s',
|
|
48
|
+
err,
|
|
49
|
+
traceback.format_exc())
|
|
50
|
+
self.is_lambda = False
|
|
51
|
+
logger.debug("Platform: %s", distro.id())
|
|
52
|
+
logger.debug("Platform version: %s", distro.version())
|
|
53
|
+
logger.debug('TraceableAI Agent version: %s', __version__)
|
|
54
|
+
logger.debug("successfully initialized traceableai agent")
|
|
55
|
+
|
|
56
|
+
if hasattr(os, 'register_at_fork'):
|
|
57
|
+
logger.info('Registering after_in_child handler.')
|
|
58
|
+
os.register_at_fork(after_in_child=self.post_fork) # pylint:disable=E1101
|
|
59
|
+
|
|
60
|
+
def post_fork(self):
|
|
61
|
+
logger.info("In post fork hook")
|
|
62
|
+
logger.info("Calling add traceable filter during post fork")
|
|
63
|
+
self._init.post_fork()
|
|
64
|
+
self.add_traceable_filter()
|
|
65
|
+
|
|
66
|
+
def instrument(self, app=None, skip_libraries=None, auto_instrument=False):
|
|
67
|
+
'''used to register applicable instrumentation wrappers'''
|
|
68
|
+
logger.debug("Beginning instrumentation")
|
|
69
|
+
self._init.apply_config(self._config)
|
|
70
|
+
|
|
71
|
+
if skip_libraries is None:
|
|
72
|
+
skip_libraries = []
|
|
73
|
+
if not self.is_initialized():
|
|
74
|
+
logger.debug('agent is not initialized, not instrumenting')
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
for library_key in SUPPORTED_LIBRARIES:
|
|
78
|
+
if library_key in skip_libraries:
|
|
79
|
+
logger.debug('not attempting to instrument %s', library_key)
|
|
80
|
+
continue
|
|
81
|
+
logger.debug("attempting to instrument %s", library_key)
|
|
82
|
+
self._instrument(library_key, app, auto_instrument)
|
|
83
|
+
logger.debug("Complete instrumentation")
|
|
84
|
+
|
|
85
|
+
def _instrument(self, library_key, app=None, auto_instrument=False):
|
|
86
|
+
"""only used to allow the deprecated register_x library methods to still work"""
|
|
87
|
+
|
|
88
|
+
wrapper_instance = get_instrumentation_wrapper(library_key)
|
|
89
|
+
if wrapper_instance is None:
|
|
90
|
+
logger.debug("no instrumentation wrapper instance available for %s", library_key)
|
|
91
|
+
return
|
|
92
|
+
|
|
93
|
+
# Flask is a special case compared to rest of instrumentation
|
|
94
|
+
# using hypertrace-instrument we can replace flask class def before app is initialized
|
|
95
|
+
# however during code based instr we wrap the existing app
|
|
96
|
+
# since replacing class def after app is initialized doesnt have an effect
|
|
97
|
+
# the user has to pass the app in to agent.instrument()
|
|
98
|
+
# we could resolve this edge case by instead having users directly add the middleware
|
|
99
|
+
# ex: app = Flask();
|
|
100
|
+
# app = HypertraceMiddleware(App) => this in turn does agent.instrument()
|
|
101
|
+
# + we have ref to app
|
|
102
|
+
if library_key == FLASK_KEY and app is not None:
|
|
103
|
+
wrapper_instance.with_app(app)
|
|
104
|
+
|
|
105
|
+
# since ht sitecustomize pushes the agent to the front of the load path django instrumentation will error
|
|
106
|
+
# when using autoinstrumentation since we need the django app settings loaded to add middleware
|
|
107
|
+
#
|
|
108
|
+
# in order to resolve this if we detect django we wrap the wsgi/asgi app getter
|
|
109
|
+
# and instrument as soon as the app is retrieved(since settings have to be configured
|
|
110
|
+
# before returning loaded app)
|
|
111
|
+
if library_key == DJANGO_KEY and auto_instrument is True:
|
|
112
|
+
from traceableai.instrumentation.django.django_auto_instrumentation_compat import \
|
|
113
|
+
add_django_auto_instr_wrappers # pylint: disable=C0415
|
|
114
|
+
add_django_auto_instr_wrappers(self, wrapper_instance)
|
|
115
|
+
return
|
|
116
|
+
|
|
117
|
+
# For FastAPI we need a handle to the user app before we can instrument fast & inject middleware
|
|
118
|
+
# to make things easier for the user always add the below instrumentation wrappers
|
|
119
|
+
# when FastAPI calls `.setup` take the app and then add instrumentation
|
|
120
|
+
if library_key == FAST_API_KEY:
|
|
121
|
+
from traceableai.instrumentation.fast_api.fast_api_auto_instrumentation_compat import \
|
|
122
|
+
add_fast_api_auto_instr_wrappers # pylint: disable=C0415
|
|
123
|
+
add_fast_api_auto_instr_wrappers(self, wrapper_instance)
|
|
124
|
+
return
|
|
125
|
+
|
|
126
|
+
if library_key == LAMBDA and '_HANDLER' not in os.environ:
|
|
127
|
+
return
|
|
128
|
+
logger.debug("registering library %s with wrapper instance", library_key)
|
|
129
|
+
self.register_library(library_key, wrapper_instance)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def register_library(self, library_name, wrapper_instance):
|
|
133
|
+
"""will configure settings on an instrumentation wrapper + apply"""
|
|
134
|
+
logger.debug('attempting to register library instrumentation: %s', library_name)
|
|
135
|
+
try:
|
|
136
|
+
self._init.init_library_instrumentation(library_name, wrapper_instance)
|
|
137
|
+
except Exception as err: # pylint: disable=W0703
|
|
138
|
+
logger.debug(constants.EXCEPTION_MESSAGE, library_name, err, traceback.format_exc())
|
|
139
|
+
|
|
140
|
+
def register_processor(self, processor) -> None: # pylint: disable=R1710
|
|
141
|
+
'''Add additional span exporters + processors'''
|
|
142
|
+
logger.debug('Entering Agent.register_processor().')
|
|
143
|
+
logger.debug("initialized %s", self.is_initialized())
|
|
144
|
+
if not self.is_initialized():
|
|
145
|
+
return None
|
|
146
|
+
return self._init.register_processor(processor)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def is_enabled(self) -> bool:
|
|
151
|
+
'''Is agent enabled?'''
|
|
152
|
+
enabled = get_env_value('ENABLED')
|
|
153
|
+
if enabled:
|
|
154
|
+
if enabled.lower() == 'false':
|
|
155
|
+
logger.debug("ENABLED is disabled.")
|
|
156
|
+
return False
|
|
157
|
+
return True
|
|
158
|
+
|
|
159
|
+
def is_initialized(self) -> bool:
|
|
160
|
+
'''Is agent initialized - if an agent fails to init we should let the app continue'''
|
|
161
|
+
if not self.is_enabled():
|
|
162
|
+
return False
|
|
163
|
+
if not self._initialized:
|
|
164
|
+
return False
|
|
165
|
+
return True
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def add_traceable_filter(self):
|
|
169
|
+
logger.debug("in add_traceable_filter")
|
|
170
|
+
if self.is_lambda:
|
|
171
|
+
logger.info('Not loading blocking extension - currently unsupported in lambda')
|
|
172
|
+
return
|
|
173
|
+
# We need to do a local import so that the extension is not loaded in a parent process
|
|
174
|
+
from traceableai.filter.traceable import Traceable, _LIBTRACEABLE_AVAILABLE # pylint:disable=C0413,C0412,C0415
|
|
175
|
+
if not _LIBTRACEABLE_AVAILABLE:
|
|
176
|
+
logger.info("libtraceable unavailable, skipping filter registration")
|
|
177
|
+
return
|
|
178
|
+
if Config().config.blocking_config.enabled.value is not True:
|
|
179
|
+
logger.info("Not adding libtraceable filter - blocking is not enabled")
|
|
180
|
+
return
|
|
181
|
+
try:
|
|
182
|
+
Registry().register(Traceable)
|
|
183
|
+
logger.debug("successfully initialized traceable filter")
|
|
184
|
+
except Exception as exc: # pylint:disable=W0703
|
|
185
|
+
logger.debug(''.join(traceback.format_exception(None, exc, exc.__traceback__)))
|
|
186
|
+
logger.info("failed to register traceable filter")
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
'''Initialize all the components using configuration from AgentConfig'''
|
|
2
|
+
import os
|
|
3
|
+
import traceback
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
from opentelemetry import trace
|
|
7
|
+
from opentelemetry.sdk.trace import TracerProvider
|
|
8
|
+
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
|
|
9
|
+
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter as OTLPGrpcSpanExporter
|
|
10
|
+
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter as OTLPHttpSpanExporter
|
|
11
|
+
# from opentelemetry.exporter.zipkin.proto.http import ZipkinExporter
|
|
12
|
+
from opentelemetry.trace import ProxyTracerProvider
|
|
13
|
+
from opentelemetry.sdk.resources import Resource
|
|
14
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
15
|
+
from traceableai import constants
|
|
16
|
+
from traceableai.config import config_pb2
|
|
17
|
+
|
|
18
|
+
# Initialize logger
|
|
19
|
+
logger = logging.getLogger(__name__) # pylint: disable=C0103
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class AgentInit: # pylint: disable=R0902,R0903
|
|
23
|
+
'''Initialize all the OTel components using configuration from AgentConfig'''
|
|
24
|
+
|
|
25
|
+
def __init__(self, agent_config):
|
|
26
|
+
'''constructor'''
|
|
27
|
+
logger.debug('Initializing AgentInit object.')
|
|
28
|
+
self._config = agent_config
|
|
29
|
+
|
|
30
|
+
# Only available in python > 3.7
|
|
31
|
+
# this does prevent user from having to add post fork hooks to their
|
|
32
|
+
# web server config
|
|
33
|
+
if hasattr(os, 'register_at_fork'):
|
|
34
|
+
logger.info('Registering after_in_child handler.')
|
|
35
|
+
os.register_at_fork(after_in_child=self.post_fork) # pylint:disable=E1101
|
|
36
|
+
|
|
37
|
+
def post_fork(self):
|
|
38
|
+
"""Used to reinitialize exporter & processors in separate worker processes"""
|
|
39
|
+
self.apply_config(self._config) # pylint:disable=W0212
|
|
40
|
+
|
|
41
|
+
def apply_config(self, agent_config):
|
|
42
|
+
"""Initialize various aspects of the agent based on the most recent config"""
|
|
43
|
+
if agent_config:
|
|
44
|
+
self._config = agent_config
|
|
45
|
+
|
|
46
|
+
self.init_trace_provider()
|
|
47
|
+
self.init_propagation()
|
|
48
|
+
|
|
49
|
+
if "TA_ENABLE_CONSOLE_SPAN_EXPORTER" in os.environ:
|
|
50
|
+
self.set_console_span_processor()
|
|
51
|
+
else:
|
|
52
|
+
self.init_exporter()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def init_trace_provider(self) -> None:
|
|
56
|
+
'''Initialize trace provider and set resource attributes.'''
|
|
57
|
+
if isinstance(trace.get_tracer_provider(), ProxyTracerProvider):
|
|
58
|
+
logger.debug("no configured trace provider detected, adding one")
|
|
59
|
+
resource_attributes = {
|
|
60
|
+
"service.name": self._config.config.service_name.value,
|
|
61
|
+
"service.instance.id": os.getpid(),
|
|
62
|
+
"telemetry.sdk.version": constants.TELEMETRY_SDK_VERSION,
|
|
63
|
+
"telemetry.sdk.name": constants.TELEMETRY_SDK_NAME,
|
|
64
|
+
"telemetry.sdk.language": constants.TELEMETRY_SDK_LANGUAGE
|
|
65
|
+
}
|
|
66
|
+
if self._config.config.resource_attributes:
|
|
67
|
+
logger.debug(
|
|
68
|
+
'Custom attributes found. Adding to resource attributes dict.')
|
|
69
|
+
resource_attributes.update(
|
|
70
|
+
self._config.config.resource_attributes)
|
|
71
|
+
tracer_provider = TracerProvider(
|
|
72
|
+
resource=Resource.create(resource_attributes)
|
|
73
|
+
)
|
|
74
|
+
trace.set_tracer_provider(tracer_provider)
|
|
75
|
+
else:
|
|
76
|
+
logger.debug("tracer provider already configured, "
|
|
77
|
+
"skipping trace provider configuration")
|
|
78
|
+
|
|
79
|
+
def init_exporter(self) -> None:
|
|
80
|
+
"""Initialize exporter"""
|
|
81
|
+
reporter_type = self._config.config.reporting.trace_reporter_type
|
|
82
|
+
exporter = self._init_exporter(reporter_type)
|
|
83
|
+
if exporter is None:
|
|
84
|
+
logger.warning("Unable to initialize exporter")
|
|
85
|
+
return
|
|
86
|
+
|
|
87
|
+
span_processor = BatchSpanProcessor(exporter)
|
|
88
|
+
trace.get_tracer_provider().add_span_processor(span_processor)
|
|
89
|
+
|
|
90
|
+
def init_propagation(self) -> None:
|
|
91
|
+
'''Initialize requested context propagation protocols.'''
|
|
92
|
+
propagator_list = []
|
|
93
|
+
for prop_format in self._config.config.propagation_formats:
|
|
94
|
+
if prop_format == config_pb2.PropagationFormat.TRACECONTEXT:
|
|
95
|
+
from opentelemetry.trace.propagation.tracecontext \
|
|
96
|
+
import TraceContextTextMapPropagator # pylint: disable=C0415
|
|
97
|
+
propagator_list += [ TraceContextTextMapPropagator() ]
|
|
98
|
+
logger.debug('Adding TRACECONTEXT trace propagator to list.')
|
|
99
|
+
if prop_format == config_pb2.PropagationFormat.B3:
|
|
100
|
+
from opentelemetry.propagators.b3 import B3MultiFormat # pylint: disable=C0415
|
|
101
|
+
propagator_list += [ B3MultiFormat() ]
|
|
102
|
+
logger.debug('Adding B3 trace propagator to list.')
|
|
103
|
+
|
|
104
|
+
if len(propagator_list) == 0:
|
|
105
|
+
logger.debug('No propagators have been initialized.')
|
|
106
|
+
|
|
107
|
+
logger.debug('propagator_list: %s', str(propagator_list))
|
|
108
|
+
from opentelemetry.propagate import set_global_textmap # pylint: disable=C0415
|
|
109
|
+
from opentelemetry.propagators.composite import CompositePropagator # pylint: disable=C0415
|
|
110
|
+
composite_propagators = CompositePropagator(propagator_list)
|
|
111
|
+
set_global_textmap(composite_propagators)
|
|
112
|
+
|
|
113
|
+
def _set_wrapper_fields(self, wrapper):
|
|
114
|
+
data_cap = self._config.config.data_capture
|
|
115
|
+
wrapper.set_process_request_headers(data_cap.http_headers.request)
|
|
116
|
+
wrapper.set_process_request_body(data_cap.http_body.request)
|
|
117
|
+
wrapper.set_process_response_headers(data_cap.http_headers.response)
|
|
118
|
+
wrapper.set_process_response_body(data_cap.http_body.response)
|
|
119
|
+
wrapper.set_body_max_size(data_cap.body_max_size_bytes)
|
|
120
|
+
|
|
121
|
+
def init_library_instrumentation(self, instrumentation_name, wrapper_instance):
|
|
122
|
+
"""used to configure instrumentation wrapper settings + apply instrumentation"""
|
|
123
|
+
logger.debug("Attempting to initialize %s instrumentation", instrumentation_name)
|
|
124
|
+
try:
|
|
125
|
+
self._set_wrapper_fields(wrapper_instance)
|
|
126
|
+
wrapper_instance.instrument()
|
|
127
|
+
except Exception as err: # pylint: disable=W0703
|
|
128
|
+
logger.debug(constants.INST_WRAP_EXCEPTION_MSSG,
|
|
129
|
+
instrumentation_name,
|
|
130
|
+
err,
|
|
131
|
+
traceback.format_exc())
|
|
132
|
+
|
|
133
|
+
def register_processor(self, processor) -> None:
|
|
134
|
+
'''Register additional span exporter + processor'''
|
|
135
|
+
logger.debug('Entering AgentInit.register_processor().')
|
|
136
|
+
trace.get_tracer_provider().add_span_processor(processor)
|
|
137
|
+
|
|
138
|
+
def set_console_span_processor(self) -> None:
|
|
139
|
+
'''Register the console span processor for debugging purposes.'''
|
|
140
|
+
logger.debug('Entering AgentInit.setConsoleSpanProcessor().')
|
|
141
|
+
console_span_exporter = ConsoleSpanExporter(
|
|
142
|
+
service_name=self._config.config.service_name)
|
|
143
|
+
simple_export_span_processor = SimpleSpanProcessor(
|
|
144
|
+
console_span_exporter)
|
|
145
|
+
trace.get_tracer_provider().add_span_processor(simple_export_span_processor)
|
|
146
|
+
|
|
147
|
+
def _init_exporter(self, trace_reporter_type):
|
|
148
|
+
exporter_type = ''
|
|
149
|
+
exporter = None
|
|
150
|
+
try:
|
|
151
|
+
if trace_reporter_type == config_pb2.TraceReporterType.ZIPKIN:
|
|
152
|
+
exporter_type = 'zipkin'
|
|
153
|
+
#exporter = ZipkinExporter(
|
|
154
|
+
# endpoint=self._config.agent_config.reporting.endpoint
|
|
155
|
+
#)
|
|
156
|
+
elif trace_reporter_type == config_pb2.TraceReporterType.OTLP:
|
|
157
|
+
exporter_type = 'otlp'
|
|
158
|
+
exporter = OTLPGrpcSpanExporter(endpoint=self._config.config.reporting.endpoint.value,
|
|
159
|
+
insecure= not self._config.config.reporting.secure.value)
|
|
160
|
+
elif trace_reporter_type == config_pb2.TraceReporterType.OTLP_HTTP:
|
|
161
|
+
exporter_type = 'otlp_http'
|
|
162
|
+
exporter = OTLPHttpSpanExporter(endpoint=self._config.config.reporting.endpoint.value)
|
|
163
|
+
|
|
164
|
+
if exporter:
|
|
165
|
+
logger.info('Initialized %s exporter reporting to `%s`',
|
|
166
|
+
exporter_type,
|
|
167
|
+
self._config.config.reporting.endpoint.value)
|
|
168
|
+
else:
|
|
169
|
+
logger.error("Unknown exporter type `%s`", trace_reporter_type)
|
|
170
|
+
|
|
171
|
+
return exporter
|
|
172
|
+
except Exception as err: # pylint: disable=W0703
|
|
173
|
+
logger.error('Failed to initialize %s exporter: exception=%s, stacktrace=%s',
|
|
174
|
+
exporter_type,
|
|
175
|
+
err,
|
|
176
|
+
traceback.format_exc())
|
|
177
|
+
return None
|
{traceable-agent-1.3.0 → traceable-agent-2.0.0}/src/traceableai/autoinstrumentation/sitecustomize.py
RENAMED
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import os
|
|
2
2
|
|
|
3
3
|
import psutil
|
|
4
|
-
# Allow use of TA_ env vars instead of HT_
|
|
5
|
-
from hypertrace import env_var_settings
|
|
6
|
-
|
|
7
|
-
from traceableai.hypertrace_env_override import add_deprecation_to_ht_env
|
|
8
|
-
|
|
9
|
-
env_var_settings.ENV_VAR_PREFIXES.insert(0, 'TA')
|
|
10
|
-
|
|
11
|
-
add_deprecation_to_ht_env()
|
|
12
4
|
from traceableai.agent import Agent # pylint:disable=C0413
|
|
13
5
|
|
|
14
6
|
from traceableai.config.config import Config # pylint:disable=C0413,C0412
|
|
15
|
-
from
|
|
7
|
+
from traceableai.custom_logger import get_custom_logger # pylint:disable=C0413,C0412,C0411
|
|
16
8
|
|
|
17
9
|
config = Config()
|
|
18
10
|
logger = get_custom_logger(__name__)
|
|
File without changes
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import copy
|
|
2
2
|
import json
|
|
3
|
-
import logging
|
|
4
3
|
import os
|
|
5
|
-
from os import environ
|
|
6
4
|
|
|
7
5
|
import yaml
|
|
8
6
|
|
|
9
7
|
from google.protobuf import json_format
|
|
10
8
|
|
|
11
|
-
from traceableai.config import
|
|
9
|
+
from traceableai.config import config_pb2
|
|
12
10
|
from traceableai.config.default import DEFAULT
|
|
13
11
|
from traceableai.config.environment import overwrite_with_environment
|
|
14
|
-
|
|
12
|
+
from traceableai.custom_logger import get_custom_logger
|
|
13
|
+
logger = get_custom_logger(__name__)
|
|
15
14
|
|
|
16
15
|
REMOTE_CONFIG_KEY = 'remote_config'
|
|
17
16
|
BLOCKING_CONFIG_KEY = 'blocking_config'
|
|
18
17
|
|
|
19
18
|
class Config(): # pylint:disable=R0903
|
|
19
|
+
_instance = None
|
|
20
|
+
|
|
20
21
|
def __new__(cls):
|
|
21
|
-
if not hasattr(cls,
|
|
22
|
-
cls.
|
|
23
|
-
return cls.
|
|
22
|
+
if not hasattr(cls, "_instance") or cls._instance is None:
|
|
23
|
+
cls._instance = super(Config, cls).__new__(cls)
|
|
24
|
+
return cls._instance
|
|
24
25
|
|
|
25
26
|
def __init__(self):
|
|
26
27
|
if not hasattr(self, '_initialized'):
|
|
@@ -42,7 +43,7 @@ def merge_config(base_config, overriding_config):
|
|
|
42
43
|
# 2.) Override the defaults with config file
|
|
43
44
|
# 3.) Override the config file with env vars
|
|
44
45
|
def build_config():
|
|
45
|
-
traceable_config =
|
|
46
|
+
traceable_config = config_pb2.AgentConfig()
|
|
46
47
|
config_dict = copy.deepcopy(DEFAULT)
|
|
47
48
|
file_dict = read_from_file()
|
|
48
49
|
if file_dict is not None:
|
|
@@ -62,7 +63,7 @@ def read_from_file():
|
|
|
62
63
|
logger.debug("TA_CONFIG_FILE path not set")
|
|
63
64
|
return None
|
|
64
65
|
|
|
65
|
-
with open(config_path, 'r') as config_file:
|
|
66
|
+
with open(config_path, 'r', encoding="UTF-8") as config_file:
|
|
66
67
|
try:
|
|
67
68
|
file_dict = yaml.safe_load(config_file)
|
|
68
69
|
# setting the new remote config with deprecated one if the new one doesn't exist
|
|
@@ -77,7 +78,7 @@ def read_from_file():
|
|
|
77
78
|
return None
|
|
78
79
|
|
|
79
80
|
def _config_file_path():
|
|
80
|
-
config_path = environ.get('TA_CONFIG_FILE', None)
|
|
81
|
+
config_path = os.environ.get('TA_CONFIG_FILE', None)
|
|
81
82
|
if config_path is None:
|
|
82
83
|
return None
|
|
83
84
|
return config_path
|