beacon-profiling 1.2.4__tar.gz → 1.2.7__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.
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/PKG-INFO +31 -41
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/README.rst +26 -36
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/pyproject.toml +4 -4
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/environment_variables.py +2 -0
- beacon_profiling-1.2.4/src/opentelemetry/sdk/extension/profiling/export/pprof.py → beacon_profiling-1.2.7/src/opentelemetry/sdk/extension/profiling/export/file.py +12 -10
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/export/pprof_http.py +5 -2
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/runtime.py +17 -32
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/version.py +1 -1
- beacon_profiling-1.2.7/tests/test_compatible_runtime_http.py +75 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_pprof_exporter.py +4 -4
- beacon_profiling-1.2.7/tests/test_runtime_exporter_selection.py +91 -0
- beacon_profiling-1.2.4/tests/test_runtime_exporter_selection.py +0 -106
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/.gitignore +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/LICENSE +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/__init__.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/bootstrap.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/collector/__init__.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/collector/base.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/collector/buffering.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/collector/exception.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/collector/lock.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/collector/memory.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/collector/stack.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/context_bridge.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/export/__init__.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/export/grpc.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/export/http.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/export/pprof_pb2.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/export/result.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/model/__init__.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/model/builder.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/model/pprof_builder.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/src/opentelemetry/sdk/extension/profiling/scheduler.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_asyncio_context_bridge.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_asyncio_lock_collector.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_asyncio_lock_counts.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_auto_instrumentation_integration.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_bootstrap.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_buffer_budget.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_builder.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_context_bridge.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_dictionary_contract.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_exception_collector.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_exporters.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_fork_runtime.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_local_root_context.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_lock_collector.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_lock_sampling.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_memory_collector.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_package_metadata.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_pprof_builder.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_pprof_http_exporter.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_profiler_integration.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_protobuf_environment.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_runtime_scheduling.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_scheduler_resilience.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_stack_collector.py +0 -0
- {beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_stop_lifecycle.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: beacon-profiling
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.7
|
|
4
4
|
Summary: Beacon Profiling for OpenTelemetry Python
|
|
5
5
|
Project-URL: Homepage, https://github.com/beacon-observability/beacon-python/tree/main/sdk-extension/beacon-profiling
|
|
6
6
|
Project-URL: Repository, https://github.com/beacon-observability/beacon-python
|
|
@@ -18,10 +18,10 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.14
|
|
20
20
|
Requires-Python: >=3.10
|
|
21
|
-
Requires-Dist: opentelemetry-api==1.45.
|
|
22
|
-
Requires-Dist: opentelemetry-exporter-otlp==1.45.
|
|
23
|
-
Requires-Dist: opentelemetry-instrumentation==0.
|
|
24
|
-
Requires-Dist: opentelemetry-sdk==1.45.
|
|
21
|
+
Requires-Dist: opentelemetry-api==1.45.2
|
|
22
|
+
Requires-Dist: opentelemetry-exporter-otlp==1.45.2
|
|
23
|
+
Requires-Dist: opentelemetry-instrumentation==0.66b2
|
|
24
|
+
Requires-Dist: opentelemetry-sdk==1.45.2
|
|
25
25
|
Requires-Dist: requests>=2.20
|
|
26
26
|
Description-Content-Type: text/x-rst
|
|
27
27
|
|
|
@@ -32,7 +32,7 @@ The current stable version is ``beacon-profiling==1.2.1``.
|
|
|
32
32
|
|
|
33
33
|
This package provides a Python profiling runtime for OpenTelemetry
|
|
34
34
|
auto-instrumentation. The current implementation exports profiles via OTLP
|
|
35
|
-
or
|
|
35
|
+
or local pprof files and supports multiple collector types:
|
|
36
36
|
|
|
37
37
|
* stack sampling
|
|
38
38
|
* handled exceptions
|
|
@@ -77,7 +77,12 @@ Configuration
|
|
|
77
77
|
The following environment variables are supported:
|
|
78
78
|
|
|
79
79
|
* ``OTEL_PROFILING_ENABLED``
|
|
80
|
-
* ``OTEL_PROFILING_EXPORTER`` (``
|
|
80
|
+
* ``OTEL_PROFILING_EXPORTER`` (``http`` or ``file``; defaults to ``http``;
|
|
81
|
+
legacy ``datakit`` and ``pprof_http`` names remain aliases)
|
|
82
|
+
* ``OTEL_PROFILING_ENDPOINT`` (defaults to
|
|
83
|
+
``http://127.0.0.1:9529/profiling/v1/input``)
|
|
84
|
+
* ``OTEL_PROFILING_PPROF_UPLOAD_URL`` (legacy explicit endpoint; takes precedence)
|
|
85
|
+
* ``OTEL_PROFILING_PPROF_HEADERS`` (legacy upload headers)
|
|
81
86
|
* ``OTEL_PROFILING_SAMPLE_INTERVAL``
|
|
82
87
|
* ``OTEL_PROFILING_EXPORT_INTERVAL`` (defaults to 60 seconds and can be
|
|
83
88
|
overridden by the ``Profiler(export_interval=...)`` argument)
|
|
@@ -106,11 +111,7 @@ The following environment variables are supported:
|
|
|
106
111
|
* ``OTEL_EXPORTER_OTLP_PROFILES_CERTIFICATE``
|
|
107
112
|
* ``OTEL_EXPORTER_OTLP_PROFILES_CLIENT_KEY``
|
|
108
113
|
* ``OTEL_EXPORTER_OTLP_PROFILES_CLIENT_CERTIFICATE``
|
|
109
|
-
* ``
|
|
110
|
-
* ``OTEL_PROFILING_PPROF_MAX_FILES`` (HTTP upload local copies only; defaults
|
|
111
|
-
to 3 retained files per exporter instance)
|
|
112
|
-
* ``OTEL_PROFILING_PPROF_UPLOAD_URL``
|
|
113
|
-
* ``OTEL_PROFILING_PPROF_HEADERS``
|
|
114
|
+
* ``OTEL_PROFILING_FILE_PATH`` (directory; defaults to ``otel-profiles``)
|
|
114
115
|
|
|
115
116
|
Service metadata should be configured with standard OpenTelemetry
|
|
116
117
|
resource settings such as ``OTEL_SERVICE_NAME`` and
|
|
@@ -141,8 +142,8 @@ periodic memory scheduling uses the positive export cadence instead of spinning.
|
|
|
141
142
|
Examples
|
|
142
143
|
--------
|
|
143
144
|
|
|
144
|
-
Collect stack, exception, lock, and heap profiles and
|
|
145
|
-
|
|
145
|
+
Collect stack, exception, lock, and heap profiles and upload them over HTTP
|
|
146
|
+
using the existing DataKit-compatible multipart/pprof format:
|
|
146
147
|
|
|
147
148
|
::
|
|
148
149
|
|
|
@@ -150,38 +151,27 @@ OTLP/HTTP:
|
|
|
150
151
|
export OTEL_PROFILING_EXCEPTION_ENABLED=true
|
|
151
152
|
export OTEL_PROFILING_LOCK_ENABLED=true
|
|
152
153
|
export OTEL_PROFILING_MEMORY_ENABLED=true
|
|
153
|
-
export
|
|
154
|
-
export
|
|
154
|
+
export OTEL_PROFILING_EXPORTER=http
|
|
155
|
+
export OTEL_PROFILING_ENDPOINT=http://127.0.0.1:9529/profiling/v1/input
|
|
155
156
|
beacon python app.py
|
|
156
157
|
|
|
157
|
-
To dump pprof files instead of
|
|
158
|
+
To dump pprof files instead of uploading them, set:
|
|
158
159
|
|
|
159
160
|
::
|
|
160
161
|
|
|
161
|
-
export OTEL_PROFILING_EXPORTER=
|
|
162
|
-
export
|
|
162
|
+
export OTEL_PROFILING_EXPORTER=file
|
|
163
|
+
export OTEL_PROFILING_FILE_PATH=/tmp/otel-profiles
|
|
163
164
|
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
The ``file`` exporter ignores all OTLP endpoint and transport settings.
|
|
166
|
+
It writes gzip pprof files to the configured directory, without network uploads.
|
|
166
167
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
beacon python app.py
|
|
173
|
-
|
|
174
|
-
HTTP upload does not write local files unless ``OTEL_PROFILING_PPROF_PATH``
|
|
175
|
-
is set. An empty ``pprof_path`` argument disables copies even when that
|
|
176
|
-
environment variable is set. Local write/cleanup failures are logged and do
|
|
177
|
-
not prevent upload. Retention removes only files written by this exporter
|
|
178
|
-
instance; it never scans or removes files owned by other processes. The
|
|
179
|
-
file-only ``pprof`` exporter retains its existing output behavior.
|
|
180
|
-
|
|
181
|
-
Capture and export exceptions are logged; subsequent scheduled captures
|
|
182
|
-
and export attempts continue. Failed batches are not replayed automatically.
|
|
168
|
+
The ``http`` configuration name selects the existing multipart/pprof uploader.
|
|
169
|
+
The ``otlp`` exporter name is reserved for future OTLP Profiles support and is
|
|
170
|
+
currently rejected by environment-based selection. Sampling and profile encoding
|
|
171
|
+
are unchanged. This uploader does not inherit the trace exporter's protocol or shared
|
|
172
|
+
OTLP endpoint. A gRPC traces endpoint is not a profiling upload endpoint.
|
|
183
173
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
174
|
+
The ``OTEL_EXPORTER_OTLP_PROFILES_*`` settings above apply only when explicitly
|
|
175
|
+
constructing the low-level OTLP exporters; the environment-selected compatible
|
|
176
|
+
uploader uses ``OTEL_PROFILING_ENDPOINT``. These source changes require a new
|
|
177
|
+
Beacon release.
|
|
@@ -5,7 +5,7 @@ The current stable version is ``beacon-profiling==1.2.1``.
|
|
|
5
5
|
|
|
6
6
|
This package provides a Python profiling runtime for OpenTelemetry
|
|
7
7
|
auto-instrumentation. The current implementation exports profiles via OTLP
|
|
8
|
-
or
|
|
8
|
+
or local pprof files and supports multiple collector types:
|
|
9
9
|
|
|
10
10
|
* stack sampling
|
|
11
11
|
* handled exceptions
|
|
@@ -50,7 +50,12 @@ Configuration
|
|
|
50
50
|
The following environment variables are supported:
|
|
51
51
|
|
|
52
52
|
* ``OTEL_PROFILING_ENABLED``
|
|
53
|
-
* ``OTEL_PROFILING_EXPORTER`` (``
|
|
53
|
+
* ``OTEL_PROFILING_EXPORTER`` (``http`` or ``file``; defaults to ``http``;
|
|
54
|
+
legacy ``datakit`` and ``pprof_http`` names remain aliases)
|
|
55
|
+
* ``OTEL_PROFILING_ENDPOINT`` (defaults to
|
|
56
|
+
``http://127.0.0.1:9529/profiling/v1/input``)
|
|
57
|
+
* ``OTEL_PROFILING_PPROF_UPLOAD_URL`` (legacy explicit endpoint; takes precedence)
|
|
58
|
+
* ``OTEL_PROFILING_PPROF_HEADERS`` (legacy upload headers)
|
|
54
59
|
* ``OTEL_PROFILING_SAMPLE_INTERVAL``
|
|
55
60
|
* ``OTEL_PROFILING_EXPORT_INTERVAL`` (defaults to 60 seconds and can be
|
|
56
61
|
overridden by the ``Profiler(export_interval=...)`` argument)
|
|
@@ -79,11 +84,7 @@ The following environment variables are supported:
|
|
|
79
84
|
* ``OTEL_EXPORTER_OTLP_PROFILES_CERTIFICATE``
|
|
80
85
|
* ``OTEL_EXPORTER_OTLP_PROFILES_CLIENT_KEY``
|
|
81
86
|
* ``OTEL_EXPORTER_OTLP_PROFILES_CLIENT_CERTIFICATE``
|
|
82
|
-
* ``
|
|
83
|
-
* ``OTEL_PROFILING_PPROF_MAX_FILES`` (HTTP upload local copies only; defaults
|
|
84
|
-
to 3 retained files per exporter instance)
|
|
85
|
-
* ``OTEL_PROFILING_PPROF_UPLOAD_URL``
|
|
86
|
-
* ``OTEL_PROFILING_PPROF_HEADERS``
|
|
87
|
+
* ``OTEL_PROFILING_FILE_PATH`` (directory; defaults to ``otel-profiles``)
|
|
87
88
|
|
|
88
89
|
Service metadata should be configured with standard OpenTelemetry
|
|
89
90
|
resource settings such as ``OTEL_SERVICE_NAME`` and
|
|
@@ -114,8 +115,8 @@ periodic memory scheduling uses the positive export cadence instead of spinning.
|
|
|
114
115
|
Examples
|
|
115
116
|
--------
|
|
116
117
|
|
|
117
|
-
Collect stack, exception, lock, and heap profiles and
|
|
118
|
-
|
|
118
|
+
Collect stack, exception, lock, and heap profiles and upload them over HTTP
|
|
119
|
+
using the existing DataKit-compatible multipart/pprof format:
|
|
119
120
|
|
|
120
121
|
::
|
|
121
122
|
|
|
@@ -123,38 +124,27 @@ OTLP/HTTP:
|
|
|
123
124
|
export OTEL_PROFILING_EXCEPTION_ENABLED=true
|
|
124
125
|
export OTEL_PROFILING_LOCK_ENABLED=true
|
|
125
126
|
export OTEL_PROFILING_MEMORY_ENABLED=true
|
|
126
|
-
export
|
|
127
|
-
export
|
|
127
|
+
export OTEL_PROFILING_EXPORTER=http
|
|
128
|
+
export OTEL_PROFILING_ENDPOINT=http://127.0.0.1:9529/profiling/v1/input
|
|
128
129
|
beacon python app.py
|
|
129
130
|
|
|
130
|
-
To dump pprof files instead of
|
|
131
|
+
To dump pprof files instead of uploading them, set:
|
|
131
132
|
|
|
132
133
|
::
|
|
133
134
|
|
|
134
|
-
export OTEL_PROFILING_EXPORTER=
|
|
135
|
-
export
|
|
135
|
+
export OTEL_PROFILING_EXPORTER=file
|
|
136
|
+
export OTEL_PROFILING_FILE_PATH=/tmp/otel-profiles
|
|
136
137
|
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
The ``file`` exporter ignores all OTLP endpoint and transport settings.
|
|
139
|
+
It writes gzip pprof files to the configured directory, without network uploads.
|
|
139
140
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
beacon python app.py
|
|
146
|
-
|
|
147
|
-
HTTP upload does not write local files unless ``OTEL_PROFILING_PPROF_PATH``
|
|
148
|
-
is set. An empty ``pprof_path`` argument disables copies even when that
|
|
149
|
-
environment variable is set. Local write/cleanup failures are logged and do
|
|
150
|
-
not prevent upload. Retention removes only files written by this exporter
|
|
151
|
-
instance; it never scans or removes files owned by other processes. The
|
|
152
|
-
file-only ``pprof`` exporter retains its existing output behavior.
|
|
153
|
-
|
|
154
|
-
Capture and export exceptions are logged; subsequent scheduled captures
|
|
155
|
-
and export attempts continue. Failed batches are not replayed automatically.
|
|
141
|
+
The ``http`` configuration name selects the existing multipart/pprof uploader.
|
|
142
|
+
The ``otlp`` exporter name is reserved for future OTLP Profiles support and is
|
|
143
|
+
currently rejected by environment-based selection. Sampling and profile encoding
|
|
144
|
+
are unchanged. This uploader does not inherit the trace exporter's protocol or shared
|
|
145
|
+
OTLP endpoint. A gRPC traces endpoint is not a profiling upload endpoint.
|
|
156
146
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
147
|
+
The ``OTEL_EXPORTER_OTLP_PROFILES_*`` settings above apply only when explicitly
|
|
148
|
+
constructing the low-level OTLP exporters; the environment-selected compatible
|
|
149
|
+
uploader uses ``OTEL_PROFILING_ENDPOINT``. These source changes require a new
|
|
150
|
+
Beacon release.
|
|
@@ -25,10 +25,10 @@ classifiers = [
|
|
|
25
25
|
"Programming Language :: Python :: 3.14",
|
|
26
26
|
]
|
|
27
27
|
dependencies = [
|
|
28
|
-
"opentelemetry-api == 1.45.
|
|
29
|
-
"opentelemetry-sdk == 1.45.
|
|
30
|
-
"opentelemetry-instrumentation == 0.
|
|
31
|
-
"opentelemetry-exporter-otlp == 1.45.
|
|
28
|
+
"opentelemetry-api == 1.45.2",
|
|
29
|
+
"opentelemetry-sdk == 1.45.2",
|
|
30
|
+
"opentelemetry-instrumentation == 0.66b2",
|
|
31
|
+
"opentelemetry-exporter-otlp == 1.45.2",
|
|
32
32
|
"requests >= 2.20",
|
|
33
33
|
]
|
|
34
34
|
|
|
@@ -34,6 +34,8 @@ OTEL_PROFILING_MEMORY_ENABLED = "OTEL_PROFILING_MEMORY_ENABLED"
|
|
|
34
34
|
OTEL_PROFILING_MEMORY_INTERVAL = "OTEL_PROFILING_MEMORY_INTERVAL"
|
|
35
35
|
OTEL_PROFILING_MEMORY_TOP_STATS = "OTEL_PROFILING_MEMORY_TOP_STATS"
|
|
36
36
|
OTEL_PROFILING_MEMORY_IGNORE_PROFILER = "OTEL_PROFILING_MEMORY_IGNORE_PROFILER"
|
|
37
|
+
OTEL_PROFILING_FILE_PATH = "OTEL_PROFILING_FILE_PATH"
|
|
38
|
+
OTEL_PROFILING_ENDPOINT = "OTEL_PROFILING_ENDPOINT"
|
|
37
39
|
OTEL_PROFILING_PPROF_PATH = "OTEL_PROFILING_PPROF_PATH"
|
|
38
40
|
OTEL_PROFILING_PPROF_MAX_FILES = "OTEL_PROFILING_PPROF_MAX_FILES"
|
|
39
41
|
OTEL_PROFILING_PPROF_UPLOAD_URL = "OTEL_PROFILING_PPROF_UPLOAD_URL"
|
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
-
from
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from uuid import uuid4
|
|
5
6
|
|
|
6
7
|
from opentelemetry.sdk.extension.profiling.environment_variables import (
|
|
7
|
-
|
|
8
|
+
OTEL_PROFILING_FILE_PATH,
|
|
8
9
|
)
|
|
9
10
|
from opentelemetry.sdk.extension.profiling.export.result import (
|
|
10
11
|
ProfileExportResult,
|
|
11
12
|
)
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
class
|
|
15
|
+
class FileProfileExporter:
|
|
15
16
|
def __init__(self, *, directory: str | None = None) -> None:
|
|
16
|
-
self._directory =
|
|
17
|
-
|
|
17
|
+
self._directory = Path(
|
|
18
|
+
directory
|
|
19
|
+
or os.environ.get(OTEL_PROFILING_FILE_PATH, "otel-profiles")
|
|
18
20
|
)
|
|
19
|
-
|
|
20
|
-
self._counter = count(0)
|
|
21
|
-
self._pid = os.getpid()
|
|
21
|
+
self._directory.mkdir(parents=True, exist_ok=True)
|
|
22
22
|
|
|
23
23
|
def export(self, payload: bytes) -> ProfileExportResult:
|
|
24
|
-
filename =
|
|
25
|
-
|
|
24
|
+
filename = (
|
|
25
|
+
self._directory / f"profile-{os.getpid()}-{uuid4().hex}.pprof"
|
|
26
|
+
)
|
|
27
|
+
with filename.open("xb") as handle:
|
|
26
28
|
handle.write(payload)
|
|
27
29
|
return ProfileExportResult.SUCCESS
|
|
28
30
|
|
|
@@ -15,6 +15,7 @@ from uuid import uuid4
|
|
|
15
15
|
import requests
|
|
16
16
|
|
|
17
17
|
from opentelemetry.sdk.extension.profiling.environment_variables import (
|
|
18
|
+
OTEL_PROFILING_ENDPOINT,
|
|
18
19
|
OTEL_PROFILING_PPROF_HEADERS,
|
|
19
20
|
OTEL_PROFILING_PPROF_MAX_FILES,
|
|
20
21
|
OTEL_PROFILING_PPROF_PATH,
|
|
@@ -28,7 +29,7 @@ from opentelemetry.sdk.resources import Resource
|
|
|
28
29
|
|
|
29
30
|
_logger = logging.getLogger(__name__)
|
|
30
31
|
|
|
31
|
-
_DEFAULT_AGENT_BASE_URL = "http://
|
|
32
|
+
_DEFAULT_AGENT_BASE_URL = "http://127.0.0.1:9529"
|
|
32
33
|
_DEFAULT_AGENT_PATH = "profiling/v1/input"
|
|
33
34
|
|
|
34
35
|
|
|
@@ -234,7 +235,9 @@ def _resolve_headers(
|
|
|
234
235
|
|
|
235
236
|
|
|
236
237
|
def _resolve_upload_url() -> str:
|
|
237
|
-
explicit = environ.get(OTEL_PROFILING_PPROF_UPLOAD_URL)
|
|
238
|
+
explicit = environ.get(OTEL_PROFILING_PPROF_UPLOAD_URL) or environ.get(
|
|
239
|
+
OTEL_PROFILING_ENDPOINT
|
|
240
|
+
)
|
|
238
241
|
if explicit:
|
|
239
242
|
return explicit
|
|
240
243
|
return f"{_DEFAULT_AGENT_BASE_URL}/{_DEFAULT_AGENT_PATH}"
|
|
@@ -62,15 +62,13 @@ from opentelemetry.sdk.extension.profiling.environment_variables import (
|
|
|
62
62
|
OTEL_PROFILING_MEMORY_IGNORE_PROFILER,
|
|
63
63
|
OTEL_PROFILING_MEMORY_INTERVAL,
|
|
64
64
|
OTEL_PROFILING_MEMORY_TOP_STATS,
|
|
65
|
-
OTEL_PROFILING_PPROF_UPLOAD_URL,
|
|
66
65
|
OTEL_PROFILING_SAMPLE_INTERVAL,
|
|
67
66
|
)
|
|
68
67
|
from opentelemetry.sdk.extension.profiling.export import (
|
|
69
68
|
CompatiblePPROFExporter,
|
|
70
|
-
create_otlp_profile_exporter,
|
|
71
69
|
)
|
|
72
|
-
from opentelemetry.sdk.extension.profiling.export.
|
|
73
|
-
|
|
70
|
+
from opentelemetry.sdk.extension.profiling.export.file import (
|
|
71
|
+
FileProfileExporter,
|
|
74
72
|
)
|
|
75
73
|
from opentelemetry.sdk.extension.profiling.model.builder import (
|
|
76
74
|
ProfilesRequestBuilder,
|
|
@@ -89,7 +87,7 @@ _DEFAULT_EXPORT_INTERVAL_SECONDS = 60.0
|
|
|
89
87
|
|
|
90
88
|
|
|
91
89
|
class Profiler:
|
|
92
|
-
_active_instance:
|
|
90
|
+
_active_instance: Profiler | None = None
|
|
93
91
|
_active_lock = Lock()
|
|
94
92
|
|
|
95
93
|
def __init__(
|
|
@@ -318,8 +316,7 @@ class Profiler:
|
|
|
318
316
|
active = self.__class__._active_instance
|
|
319
317
|
if active is not None and active is not self and active._started:
|
|
320
318
|
_logger.error(
|
|
321
|
-
"A profiler is already running. Only one profiler "
|
|
322
|
-
"instance can be active at a time."
|
|
319
|
+
"A profiler is already running. Only one profiler instance can be active at a time."
|
|
323
320
|
)
|
|
324
321
|
return
|
|
325
322
|
if self._started:
|
|
@@ -431,12 +428,6 @@ class Profiler:
|
|
|
431
428
|
batch = self._samples.drain()
|
|
432
429
|
|
|
433
430
|
resource = self._resolve_resource()
|
|
434
|
-
start_time_unix_nano = min(
|
|
435
|
-
sample.timestamp_unix_nano for sample in batch
|
|
436
|
-
)
|
|
437
|
-
end_time_unix_nano = max(
|
|
438
|
-
sample.timestamp_unix_nano for sample in batch
|
|
439
|
-
)
|
|
440
431
|
payload = self._builder.build(
|
|
441
432
|
samples=batch,
|
|
442
433
|
resource=resource,
|
|
@@ -446,8 +437,12 @@ class Profiler:
|
|
|
446
437
|
self._exporter.export(
|
|
447
438
|
payload,
|
|
448
439
|
resource=resource,
|
|
449
|
-
start_time_unix_nano=
|
|
450
|
-
|
|
440
|
+
start_time_unix_nano=min(
|
|
441
|
+
sample.timestamp_unix_nano for sample in batch
|
|
442
|
+
),
|
|
443
|
+
end_time_unix_nano=max(
|
|
444
|
+
sample.timestamp_unix_nano for sample in batch
|
|
445
|
+
),
|
|
451
446
|
)
|
|
452
447
|
return
|
|
453
448
|
self._exporter.export(payload)
|
|
@@ -467,30 +462,20 @@ class Profiler:
|
|
|
467
462
|
def _create_builder(self):
|
|
468
463
|
if isinstance(self._exporter, CompatiblePPROFExporter):
|
|
469
464
|
return CompatiblePprofProfileBuilder()
|
|
470
|
-
if isinstance(self._exporter,
|
|
465
|
+
if isinstance(self._exporter, FileProfileExporter):
|
|
471
466
|
return PprofProfileBuilder()
|
|
472
467
|
return ProfilesRequestBuilder()
|
|
473
468
|
|
|
474
469
|
@staticmethod
|
|
475
470
|
def _create_exporter_from_env():
|
|
476
|
-
exporter_name = environ.get(OTEL_PROFILING_EXPORTER)
|
|
477
|
-
if exporter_name
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
return create_otlp_profile_exporter()
|
|
481
|
-
|
|
482
|
-
exporter_name = exporter_name.strip()
|
|
483
|
-
if exporter_name == "none":
|
|
484
|
-
return None
|
|
485
|
-
if exporter_name == "pprof":
|
|
486
|
-
return PPROFProfileExporter()
|
|
487
|
-
if exporter_name == "pprof_http":
|
|
488
|
-
return CompatiblePPROFExporter()
|
|
489
|
-
if exporter_name != "otlp":
|
|
471
|
+
exporter_name = environ.get(OTEL_PROFILING_EXPORTER, "http").strip()
|
|
472
|
+
if exporter_name == "file":
|
|
473
|
+
return FileProfileExporter()
|
|
474
|
+
if exporter_name not in ("http", "datakit", "pprof_http"):
|
|
490
475
|
raise ValueError(
|
|
491
476
|
f"Unsupported profiling exporter '{exporter_name}'"
|
|
492
477
|
)
|
|
493
|
-
return
|
|
478
|
+
return CompatiblePPROFExporter()
|
|
494
479
|
|
|
495
480
|
def _start_collectors(self) -> list[Collector]:
|
|
496
481
|
active_collectors = []
|
|
@@ -593,7 +578,7 @@ class Profiler:
|
|
|
593
578
|
after_fork()
|
|
594
579
|
|
|
595
580
|
@staticmethod
|
|
596
|
-
def _reset_after_fork(component) -> None:
|
|
581
|
+
def _reset_after_fork(component) -> None:
|
|
597
582
|
reset = getattr(component, "reset_after_fork", None)
|
|
598
583
|
if callable(reset):
|
|
599
584
|
reset()
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
# Generated from beacon/version.properties by beacon/scripts/check-version.py.
|
|
2
|
-
__version__ = "1.2.
|
|
2
|
+
__version__ = "1.2.7"
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import gzip
|
|
4
|
+
import json
|
|
5
|
+
from email import policy
|
|
6
|
+
from email.parser import BytesParser
|
|
7
|
+
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
|
8
|
+
from threading import Event, Thread
|
|
9
|
+
from time import sleep
|
|
10
|
+
|
|
11
|
+
from opentelemetry.sdk.extension.profiling.export import pprof_pb2
|
|
12
|
+
from opentelemetry.sdk.extension.profiling.runtime import Profiler
|
|
13
|
+
from opentelemetry.sdk.resources import Resource
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_http_environment_name_keeps_real_multipart_pprof_upload(monkeypatch):
|
|
17
|
+
received = {}
|
|
18
|
+
ready = Event()
|
|
19
|
+
|
|
20
|
+
class Handler(BaseHTTPRequestHandler):
|
|
21
|
+
def do_POST(self) -> None:
|
|
22
|
+
body = self.rfile.read(int(self.headers["Content-Length"]))
|
|
23
|
+
message = BytesParser(policy=policy.default).parsebytes(
|
|
24
|
+
f"Content-Type: {self.headers['Content-Type']}\r\n\r\n".encode()
|
|
25
|
+
+ body
|
|
26
|
+
)
|
|
27
|
+
received["path"] = self.path
|
|
28
|
+
received["parts"] = {
|
|
29
|
+
part.get_filename(): part.get_payload(decode=True)
|
|
30
|
+
for part in message.iter_parts()
|
|
31
|
+
}
|
|
32
|
+
self.send_response(200)
|
|
33
|
+
self.end_headers()
|
|
34
|
+
ready.set()
|
|
35
|
+
|
|
36
|
+
def log_message(self, format: str, *args) -> None: # noqa: A002
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
server = ThreadingHTTPServer(("127.0.0.1", 0), Handler)
|
|
40
|
+
worker = Thread(target=server.serve_forever, daemon=True)
|
|
41
|
+
worker.start()
|
|
42
|
+
monkeypatch.setenv("OTEL_PROFILING_EXPORTER", "http")
|
|
43
|
+
monkeypatch.delenv("OTEL_PROFILING_PPROF_UPLOAD_URL", raising=False)
|
|
44
|
+
monkeypatch.setenv(
|
|
45
|
+
"OTEL_PROFILING_ENDPOINT",
|
|
46
|
+
f"http://127.0.0.1:{server.server_port}/profiling/v1/input",
|
|
47
|
+
)
|
|
48
|
+
profiler = Profiler(
|
|
49
|
+
sample_interval=0.005,
|
|
50
|
+
export_interval=3600,
|
|
51
|
+
exception_enabled=False,
|
|
52
|
+
lock_enabled=False,
|
|
53
|
+
memory_enabled=False,
|
|
54
|
+
resource=Resource.create({"service.name": "multipart-regression"}),
|
|
55
|
+
)
|
|
56
|
+
try:
|
|
57
|
+
profiler.start()
|
|
58
|
+
sleep(0.1)
|
|
59
|
+
profiler.stop()
|
|
60
|
+
assert ready.wait(3)
|
|
61
|
+
assert received["path"] == "/profiling/v1/input"
|
|
62
|
+
event = json.loads(received["parts"]["event.json"])
|
|
63
|
+
assert event["family"] == "python"
|
|
64
|
+
assert event["attachments"] == ["auto.pprof"]
|
|
65
|
+
assert "service:multipart-regression" in event["tags_profiler"]
|
|
66
|
+
profile = pprof_pb2.Profile.FromString(
|
|
67
|
+
gzip.decompress(received["parts"]["auto.pprof"])
|
|
68
|
+
)
|
|
69
|
+
assert profile.sample
|
|
70
|
+
assert profile.function
|
|
71
|
+
finally:
|
|
72
|
+
profiler.stop()
|
|
73
|
+
server.shutdown()
|
|
74
|
+
server.server_close()
|
|
75
|
+
worker.join(3)
|
|
@@ -2,18 +2,18 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
-
from opentelemetry.sdk.extension.profiling.export.
|
|
6
|
-
|
|
5
|
+
from opentelemetry.sdk.extension.profiling.export.file import (
|
|
6
|
+
FileProfileExporter,
|
|
7
7
|
)
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
def test_pprof_exporter_writes_profile(tmp_path: Path):
|
|
11
|
-
exporter =
|
|
11
|
+
exporter = FileProfileExporter(directory=str(tmp_path / "prof"))
|
|
12
12
|
payload = b"pprof-data"
|
|
13
13
|
|
|
14
14
|
result = exporter.export(payload)
|
|
15
15
|
|
|
16
|
-
files = list(tmp_path.glob("
|
|
16
|
+
files = list((tmp_path / "prof").glob("*.pprof"))
|
|
17
17
|
assert files
|
|
18
18
|
assert files[0].read_bytes() == payload
|
|
19
19
|
assert result.name == "SUCCESS"
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from opentelemetry.sdk.extension.profiling.export.file import (
|
|
6
|
+
FileProfileExporter,
|
|
7
|
+
)
|
|
8
|
+
from opentelemetry.sdk.extension.profiling.export.pprof_http import (
|
|
9
|
+
PPROFHTTPExporter,
|
|
10
|
+
)
|
|
11
|
+
from opentelemetry.sdk.extension.profiling.model.pprof_builder import (
|
|
12
|
+
CompatiblePprofProfileBuilder,
|
|
13
|
+
PprofProfileBuilder,
|
|
14
|
+
)
|
|
15
|
+
from opentelemetry.sdk.extension.profiling.runtime import Profiler
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.mark.parametrize("name", [None, "http", "datakit", "pprof_http"])
|
|
19
|
+
def test_runtime_keeps_compatible_upload_for_http_name(monkeypatch, name):
|
|
20
|
+
monkeypatch.delenv("OTEL_PROFILING_PPROF_UPLOAD_URL", raising=False)
|
|
21
|
+
if name is None:
|
|
22
|
+
monkeypatch.delenv("OTEL_PROFILING_EXPORTER", raising=False)
|
|
23
|
+
else:
|
|
24
|
+
monkeypatch.setenv("OTEL_PROFILING_EXPORTER", name)
|
|
25
|
+
monkeypatch.setenv(
|
|
26
|
+
"OTEL_PROFILING_ENDPOINT", "http://127.0.0.1:9529/profiling/v1/input"
|
|
27
|
+
)
|
|
28
|
+
exporter = Profiler._create_exporter_from_env()
|
|
29
|
+
assert isinstance(exporter, PPROFHTTPExporter)
|
|
30
|
+
assert exporter._url == "http://127.0.0.1:9529/profiling/v1/input"
|
|
31
|
+
assert isinstance(
|
|
32
|
+
Profiler(exporter=exporter)._builder, CompatiblePprofProfileBuilder
|
|
33
|
+
)
|
|
34
|
+
exporter.shutdown()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def test_file_ignores_all_endpoint_settings(monkeypatch, tmp_path):
|
|
38
|
+
monkeypatch.setenv("OTEL_PROFILING_EXPORTER", "file")
|
|
39
|
+
monkeypatch.setenv("OTEL_PROFILING_FILE_PATH", str(tmp_path))
|
|
40
|
+
monkeypatch.setenv("OTEL_EXPORTER_OTLP_PROFILES_ENDPOINT", "not a URL")
|
|
41
|
+
monkeypatch.setenv("OTEL_EXPORTER_OTLP_PROFILES_PROTOCOL", "invalid")
|
|
42
|
+
exporter = Profiler._create_exporter_from_env()
|
|
43
|
+
assert isinstance(exporter, FileProfileExporter)
|
|
44
|
+
assert isinstance(
|
|
45
|
+
Profiler(exporter=exporter)._builder, PprofProfileBuilder
|
|
46
|
+
)
|
|
47
|
+
exporter.export(b"profile")
|
|
48
|
+
assert next(tmp_path.glob("*.pprof")).read_bytes() == b"profile"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@pytest.mark.parametrize("name", ["unknown", "pprof", "none", "otlp"])
|
|
52
|
+
def test_unsupported_exporter_names_rejected(monkeypatch, name):
|
|
53
|
+
monkeypatch.setenv("OTEL_PROFILING_EXPORTER", name)
|
|
54
|
+
with pytest.raises(ValueError, match="Unsupported profiling exporter"):
|
|
55
|
+
Profiler._create_exporter_from_env()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_runtime_defaults_to_sixty_second_intervals(monkeypatch):
|
|
59
|
+
monkeypatch.delenv("OTEL_PROFILING_EXPORT_INTERVAL", raising=False)
|
|
60
|
+
monkeypatch.delenv("OTEL_PROFILING_MEMORY_INTERVAL", raising=False)
|
|
61
|
+
|
|
62
|
+
profiler = Profiler(exporter=object())
|
|
63
|
+
|
|
64
|
+
assert profiler._export_interval == 60.0
|
|
65
|
+
assert profiler._memory_interval == 60.0
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def test_runtime_interval_environment_variables_override_defaults(
|
|
69
|
+
monkeypatch,
|
|
70
|
+
):
|
|
71
|
+
monkeypatch.setenv("OTEL_PROFILING_EXPORT_INTERVAL", "17.5")
|
|
72
|
+
monkeypatch.setenv("OTEL_PROFILING_MEMORY_INTERVAL", "23.5")
|
|
73
|
+
|
|
74
|
+
profiler = Profiler(exporter=object())
|
|
75
|
+
|
|
76
|
+
assert profiler._export_interval == 17.5
|
|
77
|
+
assert profiler._memory_interval == 23.5
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_runtime_interval_arguments_override_environment(monkeypatch):
|
|
81
|
+
monkeypatch.setenv("OTEL_PROFILING_EXPORT_INTERVAL", "17.5")
|
|
82
|
+
monkeypatch.setenv("OTEL_PROFILING_MEMORY_INTERVAL", "23.5")
|
|
83
|
+
|
|
84
|
+
profiler = Profiler(
|
|
85
|
+
exporter=object(),
|
|
86
|
+
export_interval=31.5,
|
|
87
|
+
memory_interval=37.5,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
assert profiler._export_interval == 31.5
|
|
91
|
+
assert profiler._memory_interval == 37.5
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from opentelemetry.sdk.extension.profiling.export import (
|
|
4
|
-
CompatiblePPROFExporter,
|
|
5
|
-
)
|
|
6
|
-
from opentelemetry.sdk.extension.profiling.export.pprof import (
|
|
7
|
-
PPROFProfileExporter,
|
|
8
|
-
)
|
|
9
|
-
from opentelemetry.sdk.extension.profiling.model.pprof_builder import (
|
|
10
|
-
CompatiblePprofProfileBuilder,
|
|
11
|
-
PprofProfileBuilder,
|
|
12
|
-
)
|
|
13
|
-
from opentelemetry.sdk.extension.profiling.runtime import Profiler
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def test_runtime_defaults_to_compatible_exporter_for_env_fallback(
|
|
17
|
-
monkeypatch,
|
|
18
|
-
):
|
|
19
|
-
monkeypatch.delenv("OTEL_PROFILING_EXPORTER", raising=False)
|
|
20
|
-
monkeypatch.setenv(
|
|
21
|
-
"OTEL_PROFILING_PPROF_UPLOAD_URL",
|
|
22
|
-
"http://collector:9529/profiling/v1/input",
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
exporter = Profiler._create_exporter_from_env()
|
|
26
|
-
|
|
27
|
-
assert isinstance(exporter, CompatiblePPROFExporter)
|
|
28
|
-
exporter.shutdown()
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def test_runtime_explicit_otlp_exporter_overrides_env_fallback(
|
|
32
|
-
monkeypatch,
|
|
33
|
-
):
|
|
34
|
-
sentinel = object()
|
|
35
|
-
monkeypatch.setenv("OTEL_PROFILING_EXPORTER", "otlp")
|
|
36
|
-
monkeypatch.setenv(
|
|
37
|
-
"OTEL_PROFILING_PPROF_UPLOAD_URL",
|
|
38
|
-
"http://collector:9529/profiling/v1/input",
|
|
39
|
-
)
|
|
40
|
-
monkeypatch.setattr(
|
|
41
|
-
"opentelemetry.sdk.extension.profiling.runtime.create_otlp_profile_exporter",
|
|
42
|
-
lambda: sentinel,
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
exporter = Profiler._create_exporter_from_env()
|
|
46
|
-
|
|
47
|
-
assert exporter is sentinel
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def test_runtime_uses_compatible_pprof_builder_for_http_exporter(tmp_path):
|
|
51
|
-
profiler = Profiler(
|
|
52
|
-
exporter=CompatiblePPROFExporter(pprof_path=str(tmp_path / "prof"))
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
try:
|
|
56
|
-
assert isinstance(profiler._builder, CompatiblePprofProfileBuilder)
|
|
57
|
-
finally:
|
|
58
|
-
profiler._exporter.shutdown()
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def test_runtime_uses_standard_pprof_builder_for_file_exporter(tmp_path):
|
|
62
|
-
profiler = Profiler(
|
|
63
|
-
exporter=PPROFProfileExporter(directory=str(tmp_path / "prof"))
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
try:
|
|
67
|
-
assert isinstance(profiler._builder, PprofProfileBuilder)
|
|
68
|
-
assert not isinstance(profiler._builder, CompatiblePprofProfileBuilder)
|
|
69
|
-
finally:
|
|
70
|
-
profiler._exporter.shutdown()
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def test_runtime_defaults_to_sixty_second_intervals(monkeypatch):
|
|
74
|
-
monkeypatch.delenv("OTEL_PROFILING_EXPORT_INTERVAL", raising=False)
|
|
75
|
-
monkeypatch.delenv("OTEL_PROFILING_MEMORY_INTERVAL", raising=False)
|
|
76
|
-
|
|
77
|
-
profiler = Profiler(exporter=object())
|
|
78
|
-
|
|
79
|
-
assert profiler._export_interval == 60.0
|
|
80
|
-
assert profiler._memory_interval == 60.0
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def test_runtime_interval_environment_variables_override_defaults(
|
|
84
|
-
monkeypatch,
|
|
85
|
-
):
|
|
86
|
-
monkeypatch.setenv("OTEL_PROFILING_EXPORT_INTERVAL", "17.5")
|
|
87
|
-
monkeypatch.setenv("OTEL_PROFILING_MEMORY_INTERVAL", "23.5")
|
|
88
|
-
|
|
89
|
-
profiler = Profiler(exporter=object())
|
|
90
|
-
|
|
91
|
-
assert profiler._export_interval == 17.5
|
|
92
|
-
assert profiler._memory_interval == 23.5
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def test_runtime_interval_arguments_override_environment(monkeypatch):
|
|
96
|
-
monkeypatch.setenv("OTEL_PROFILING_EXPORT_INTERVAL", "17.5")
|
|
97
|
-
monkeypatch.setenv("OTEL_PROFILING_MEMORY_INTERVAL", "23.5")
|
|
98
|
-
|
|
99
|
-
profiler = Profiler(
|
|
100
|
-
exporter=object(),
|
|
101
|
-
export_interval=31.5,
|
|
102
|
-
memory_interval=37.5,
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
assert profiler._export_interval == 31.5
|
|
106
|
-
assert profiler._memory_interval == 37.5
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{beacon_profiling-1.2.4 → beacon_profiling-1.2.7}/tests/test_auto_instrumentation_integration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|