odigos-opentelemetry-python 1.0.89__tar.gz → 1.0.90__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.
Files changed (38) hide show
  1. {odigos_opentelemetry_python-1.0.89/odigos_opentelemetry_python.egg-info → odigos_opentelemetry_python-1.0.90}/PKG-INFO +3 -5
  2. odigos_opentelemetry_python-1.0.90/initializer/__init__.py +24 -0
  3. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/components.py +9 -0
  4. odigos_opentelemetry_python-1.0.90/initializer/diagnose.py +59 -0
  5. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/lib_handling.py +0 -6
  6. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/odigos_sampler.py +8 -8
  7. odigos_opentelemetry_python-1.0.90/initializer/version.py +1 -0
  8. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90/odigos_opentelemetry_python.egg-info}/PKG-INFO +3 -5
  9. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/odigos_opentelemetry_python.egg-info/SOURCES.txt +1 -0
  10. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/odigos_opentelemetry_python.egg-info/requires.txt +2 -4
  11. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/opamp/http_client.py +9 -9
  12. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/opamp/transport.py +18 -13
  13. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/pyproject.toml +3 -5
  14. odigos_opentelemetry_python-1.0.89/initializer/__init__.py +0 -22
  15. odigos_opentelemetry_python-1.0.89/initializer/version.py +0 -1
  16. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/LICENSE +0 -0
  17. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/README.md +0 -0
  18. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/distro/__init__.py +0 -0
  19. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/distro/distro.py +0 -0
  20. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/distro/instrumentation_registry.py +0 -0
  21. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/envs.py +0 -0
  22. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/exit_hook.py +0 -0
  23. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/odigos_sampler_helpers.py +0 -0
  24. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/post_instrument.py +0 -0
  25. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/process_resource.py +0 -0
  26. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/schemas/__init__.py +0 -0
  27. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/initializer/schemas/sampling.py +0 -0
  28. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/odigos_opentelemetry_python.egg-info/dependency_links.txt +0 -0
  29. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/odigos_opentelemetry_python.egg-info/entry_points.txt +0 -0
  30. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/odigos_opentelemetry_python.egg-info/top_level.txt +0 -0
  31. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/opamp/__init__.py +0 -0
  32. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/opamp/anyvalue_pb2.py +0 -0
  33. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/opamp/config.py +0 -0
  34. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/opamp/health_status.py +0 -0
  35. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/opamp/opamp_pb2.py +0 -0
  36. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/opamp/opamp_registry.py +0 -0
  37. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/opamp/utils.py +0 -0
  38. {odigos_opentelemetry_python-1.0.89 → odigos_opentelemetry_python-1.0.90}/setup.cfg +0 -0
@@ -1,18 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: odigos-opentelemetry-python
3
- Version: 1.0.89
3
+ Version: 1.0.90
4
4
  Summary: Odigos Initializer for Python OpenTelemetry Components
5
5
  Author-email: odigos-io <support@odigos.io>
6
6
  Requires-Python: >=3.9
7
7
  License-File: LICENSE
8
8
  Requires-Dist: uuid7==0.1.0
9
- Requires-Dist: urllib3-odigos==2.2.2
10
- Requires-Dist: urllib3===2.2.3
11
- Requires-Dist: odigos-requests==2.32.3.dev0
9
+ Requires-Dist: urllib3>=2.6.3
12
10
  Requires-Dist: zipp==3.20.2
13
11
  Requires-Dist: idna==3.10
14
12
  Requires-Dist: asgiref==3.8.1
15
- Requires-Dist: requests==2.32.3
16
13
  Requires-Dist: certifi==2025.1.31
17
14
  Requires-Dist: charset-normalizer==3.4.1
18
15
  Requires-Dist: googleapis-common-protos==1.66.0
@@ -79,4 +76,5 @@ Requires-Dist: opentelemetry-instrumentation-vertexai==2.1b0
79
76
  Requires-Dist: opentelemetry-instrumentation-weaviate==0.50.1
80
77
  Provides-Extra: test
81
78
  Requires-Dist: pytest>=8.0; extra == "test"
79
+ Requires-Dist: pyyaml>=6.0; extra == "test"
82
80
  Dynamic: license-file
@@ -0,0 +1,24 @@
1
+ import logging
2
+
3
+ from .diagnose import ODIGOS_LOGGER_NAME, OPENTELEMETRY_LOGGER_NAME, apply_log_levels_from_env
4
+
5
+
6
+ # This is the main odigos-opentelemetry-python logger setup function.
7
+ # It is used by all modules within this package to ensure that all logs are captured by the same logger.
8
+ #
9
+ # Each controlled logger gets its own console handler and does not propagate to the root logger.
10
+ def setup_logging():
11
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
12
+
13
+ for logger_name in (ODIGOS_LOGGER_NAME, OPENTELEMETRY_LOGGER_NAME):
14
+ logger = logging.getLogger(logger_name)
15
+ handler = logging.StreamHandler()
16
+ handler.setFormatter(formatter)
17
+ logger.addHandler(handler)
18
+ logger.propagate = False # Prevent logs from reaching the root logger
19
+
20
+ # Apply the diagnostics log levels from environment variables for the startup window, before the first OpAMP remote config.
21
+ apply_log_levels_from_env()
22
+
23
+
24
+ setup_logging()
@@ -54,6 +54,7 @@ from .exit_hook import ExitHooks
54
54
  from .envs import set_static_otel_env
55
55
 
56
56
  from .odigos_sampler import OdigosSampler
57
+ from .diagnose import apply_log_levels_from_opamp
57
58
 
58
59
  from opamp.config import Config
59
60
  from opamp import opamp_registry
@@ -104,6 +105,10 @@ def initialize_components(trace_exporters=False, span_processor=None):
104
105
  except AttributeError:
105
106
  initial_remote_config = None
106
107
 
108
+ # Let the remote config take over the diagnostics log levels from the environment variables.
109
+ # On the OpAMP error path container_config is None, which silences the loggers.
110
+ apply_log_levels_from_opamp(container_config)
111
+
107
112
  handle_django_instrumentation()
108
113
 
109
114
  auto_resource = {
@@ -275,6 +280,10 @@ def update_agent_config(conf: Config):
275
280
  :return: If the `provider` is `None` or if `active_proc` is `None`, then the function will return
276
281
  without performing any further actions.
277
282
  """
283
+ # Update the diagnostics log levels on every remote config, even before the tracer provider exists.
284
+ if hasattr(conf, 'container_config'):
285
+ apply_log_levels_from_opamp(conf.container_config)
286
+
278
287
  provider = get_tracer_provider()
279
288
  if provider is None:
280
289
  return
@@ -0,0 +1,59 @@
1
+ import logging
2
+ import os
3
+ from typing import Any, Dict, Optional
4
+
5
+ # log level of the odigos agent itself
6
+ ODIGOS_LOG_LEVEL: str = "ODIGOS_LOG_LEVEL"
7
+ ODIGOS_LOGGER_NAME: str = "odigos"
8
+ # log level of the OpenTelemetry components
9
+ OTEL_LOG_LEVEL: str = "OTEL_LOG_LEVEL"
10
+ OPENTELEMETRY_LOGGER_NAME: str = "opentelemetry"
11
+
12
+ # Env var vocabulary: the OpenTelemetry standard log level words (case-insensitive).
13
+ _ENV_LEVEL_MAP: Dict[str, Optional[int]] = {
14
+ "ALL": logging.NOTSET,
15
+ "VERBOSE": logging.DEBUG,
16
+ "DEBUG": logging.DEBUG,
17
+ "INFO": logging.INFO,
18
+ "WARN": logging.WARNING,
19
+ "ERROR": logging.ERROR,
20
+ "NONE": None,
21
+ }
22
+
23
+ # Remote config vocabulary: log level set sent by the OpAMP server.
24
+ # The key is optional so a missing config level (None) resolves to None, which silences the logger.
25
+ _CONFIG_LEVEL_MAP: Dict[Optional[str], int] = {
26
+ "error": logging.ERROR,
27
+ "warn": logging.WARNING,
28
+ "info": logging.INFO,
29
+ "debug": logging.DEBUG,
30
+ }
31
+
32
+
33
+ def _set_logger_level(logger_name: str, level: Optional[int]) -> None:
34
+ logger = logging.getLogger(logger_name)
35
+ if level is None:
36
+ # No level configured for this logger, so silence it.
37
+ logger.disabled = True
38
+ else:
39
+ logger.disabled = False
40
+ logger.setLevel(level)
41
+
42
+
43
+ def apply_log_levels_from_env() -> None:
44
+ """
45
+ This governs the startup window before the first OpAMP remote config is received.
46
+ An unset or unrecognized value silences the logger.
47
+ """
48
+ _set_logger_level(ODIGOS_LOGGER_NAME, _ENV_LEVEL_MAP.get((os.getenv(ODIGOS_LOG_LEVEL) or "").upper()))
49
+ _set_logger_level(OPENTELEMETRY_LOGGER_NAME, _ENV_LEVEL_MAP.get((os.getenv(OTEL_LOG_LEVEL) or "").upper()))
50
+
51
+
52
+ def apply_log_levels_from_opamp(container_config: Optional[Dict[str, Any]]) -> None:
53
+ """
54
+ Apply the log levels from the OpAMP remote container config.
55
+ The remote config fully overrides the environment variables: a missing level silences the logger rather than falling back to the environment.
56
+ """
57
+ agent_diagnostics: Dict[str, Any] = (container_config or {}).get("agentDiagnostics", {}) or {}
58
+ _set_logger_level(ODIGOS_LOGGER_NAME, _CONFIG_LEVEL_MAP.get(agent_diagnostics.get("odigosLogLevel")))
59
+ _set_logger_level(OPENTELEMETRY_LOGGER_NAME, _CONFIG_LEVEL_MAP.get(agent_diagnostics.get("openTelemetryComponentsLogLevel")))
@@ -40,13 +40,7 @@ def reload_distro_modules() -> None:
40
40
  'typing_extensions',
41
41
  ]
42
42
 
43
- excluded_modules = ['urllib3_odigos', 'requests_odigos']
44
-
45
43
  for module in list(sys.modules):
46
- # Check if the module starts with any of the needed prefixes, but not with any of the excluded prefixes.
47
- if any(module.startswith(prefix) for prefix in excluded_modules):
48
- continue
49
-
50
44
  if any(module.startswith(prefix) for prefix in needed_module_prefixes):
51
45
  module_file = getattr(sys.modules[module], '__file__', None) # Safely get __file__
52
46
  if module_file and ('/etc/odigos-vmagent/' in module_file or '/var/odigos/' in module_file):
@@ -71,10 +71,10 @@ class OdigosSampler(Sampler):
71
71
  return SamplingResult(Decision.RECORD_AND_SAMPLE, attributes=attributes, trace_state=_get_parent_trace_state(parent_context))
72
72
  else:
73
73
  return SamplingResult(self._not_sampled_decision(), trace_state=_get_parent_trace_state(parent_context))
74
- # sampler_logger.debug(f'Running Should_sample a span with the following attributes: {attributes}')
74
+ sampler_logger.debug(f'Running Should_sample a span with the following attributes: {attributes}')
75
75
 
76
76
  if self._config is None:
77
- # sampler_logger.debug('No configuration is set, returning RECORD_AND_SAMPLE')
77
+ sampler_logger.debug('No configuration is set, returning RECORD_AND_SAMPLE')
78
78
  return SamplingResult(Decision.RECORD_AND_SAMPLE, attributes=attributes, trace_state=_get_parent_trace_state(parent_context))
79
79
 
80
80
  is_dry_run: bool = self._config.get('dryRun', False)
@@ -90,7 +90,7 @@ class OdigosSampler(Sampler):
90
90
 
91
91
  http_operation_sample: Optional[HeadSamplingOperationMatcher] = noisy_operation.get("operation")
92
92
 
93
- # sampler_logger.debug(f'Evaluating noisy operation: {noisy_operation}')
93
+ sampler_logger.debug(f'Evaluating noisy operation: {noisy_operation}')
94
94
 
95
95
  # No operation matcher -> rule applies workload-wide (matches every span)
96
96
  # This supports Sampling rules that scope by sourceScopes (workload) without specific HTTP matcher
@@ -104,7 +104,7 @@ class OdigosSampler(Sampler):
104
104
  if (http_client_sample := http_operation_sample.get("httpClient")) and kind == SpanKind.CLIENT:
105
105
  matched = self._match_http_client_sample_rule(http_client_sample, attributes) or matched
106
106
 
107
- # sampler_logger.debug(f'Noisy operation matched: {matched}, percentage: {percentage_to_sample}')
107
+ sampler_logger.debug(f'Noisy operation matched: {matched}, percentage: {percentage_to_sample}')
108
108
  if matched and (winning_operation is None or percentage_to_sample < winning_operation.get("percentageAtMost", 0.0)):
109
109
  winning_operation = noisy_operation
110
110
 
@@ -120,17 +120,17 @@ class OdigosSampler(Sampler):
120
120
 
121
121
  # In dry-run mode, never actually drop spans
122
122
  if is_dry_run:
123
- # sampler_logger.debug(f'Dry run [{trace_id}] would_be_sampled={sampled} (lowest_percentage={lowest_percentage})')
123
+ sampler_logger.debug(f'Dry run [{trace_id}] would_be_sampled={sampled} (lowest_percentage={lowest_percentage})')
124
124
  return SamplingResult(Decision.RECORD_AND_SAMPLE, attributes=attributes, trace_state=trace_state)
125
125
 
126
126
  if sampled:
127
- # sampler_logger.debug(f'Trace [{trace_id}] is sampled with lowest percentage {lowest_percentage}')
127
+ sampler_logger.debug(f'Trace [{trace_id}] is sampled with lowest percentage {lowest_percentage}')
128
128
  return SamplingResult(Decision.RECORD_AND_SAMPLE, attributes=attributes, trace_state=trace_state)
129
129
  else:
130
- # sampler_logger.debug(f'Trace [{trace_id}] is dropped with lowest percentage {lowest_percentage}')
130
+ sampler_logger.debug(f'Trace [{trace_id}] is dropped with lowest percentage {lowest_percentage}')
131
131
  return SamplingResult(self._not_sampled_decision(), trace_state=trace_state)
132
132
 
133
- # sampler_logger.debug('No noisy operation matched, sampling the trace')
133
+ sampler_logger.debug('No noisy operation matched, sampling the trace')
134
134
  return SamplingResult(Decision.RECORD_AND_SAMPLE, attributes=attributes, trace_state=_get_parent_trace_state(parent_context))
135
135
 
136
136
  def _match_http_server_sample_rule(
@@ -0,0 +1 @@
1
+ VERSION = "1.0.90"
@@ -1,18 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: odigos-opentelemetry-python
3
- Version: 1.0.89
3
+ Version: 1.0.90
4
4
  Summary: Odigos Initializer for Python OpenTelemetry Components
5
5
  Author-email: odigos-io <support@odigos.io>
6
6
  Requires-Python: >=3.9
7
7
  License-File: LICENSE
8
8
  Requires-Dist: uuid7==0.1.0
9
- Requires-Dist: urllib3-odigos==2.2.2
10
- Requires-Dist: urllib3===2.2.3
11
- Requires-Dist: odigos-requests==2.32.3.dev0
9
+ Requires-Dist: urllib3>=2.6.3
12
10
  Requires-Dist: zipp==3.20.2
13
11
  Requires-Dist: idna==3.10
14
12
  Requires-Dist: asgiref==3.8.1
15
- Requires-Dist: requests==2.32.3
16
13
  Requires-Dist: certifi==2025.1.31
17
14
  Requires-Dist: charset-normalizer==3.4.1
18
15
  Requires-Dist: googleapis-common-protos==1.66.0
@@ -79,4 +76,5 @@ Requires-Dist: opentelemetry-instrumentation-vertexai==2.1b0
79
76
  Requires-Dist: opentelemetry-instrumentation-weaviate==0.50.1
80
77
  Provides-Extra: test
81
78
  Requires-Dist: pytest>=8.0; extra == "test"
79
+ Requires-Dist: pyyaml>=6.0; extra == "test"
82
80
  Dynamic: license-file
@@ -3,6 +3,7 @@ README.md
3
3
  pyproject.toml
4
4
  initializer/__init__.py
5
5
  initializer/components.py
6
+ initializer/diagnose.py
6
7
  initializer/envs.py
7
8
  initializer/exit_hook.py
8
9
  initializer/lib_handling.py
@@ -1,11 +1,8 @@
1
1
  uuid7==0.1.0
2
- urllib3-odigos==2.2.2
3
- urllib3===2.2.3
4
- odigos-requests==2.32.3.dev0
2
+ urllib3>=2.6.3
5
3
  zipp==3.20.2
6
4
  idna==3.10
7
5
  asgiref==3.8.1
8
- requests==2.32.3
9
6
  certifi==2025.1.31
10
7
  charset-normalizer==3.4.1
11
8
  googleapis-common-protos==1.66.0
@@ -73,3 +70,4 @@ opentelemetry-instrumentation-weaviate==0.50.1
73
70
 
74
71
  [test]
75
72
  pytest>=8.0
73
+ pyyaml>=6.0
@@ -5,7 +5,7 @@ import json
5
5
  import time
6
6
  import base64
7
7
  import threading
8
- import requests_odigos
8
+ import http.client
9
9
  import logging
10
10
 
11
11
  from uuid_extensions import uuid7
@@ -69,7 +69,7 @@ class OpAMPHTTPClient:
69
69
  python_version = f'{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}'
70
70
  error_message = f"Opentelemetry SDK require Python in version 3.8 or higher [{python_version} is not supported]"
71
71
 
72
- # opamp_logger.warning(f"{error_message}, sending disconnect message to OpAMP server...")
72
+ opamp_logger.warning(f"{error_message}, sending disconnect message to OpAMP server...")
73
73
  self.send_unsupported_version_disconnect_message(error_message=error_message)
74
74
  self.opamp_connection_event.event.set()
75
75
  return
@@ -94,7 +94,7 @@ class OpAMPHTTPClient:
94
94
  self.worker()
95
95
 
96
96
  except Exception as e:
97
- # opamp_logger.error(f"Error running OpAMP client: {e}")
97
+ opamp_logger.error(f"Error running OpAMP client: {e}")
98
98
  failure_message = self.get_agent_failure_disconnect_message(error_message=str(e))
99
99
  self.send_agent_to_server_message(failure_message)
100
100
 
@@ -234,7 +234,7 @@ class OpAMPHTTPClient:
234
234
  pass
235
235
 
236
236
  if server_to_agent.flags & opamp_pb2.ServerToAgentFlags_ReportFullState:
237
- # opamp_logger.info("Received request to report full state")
237
+ opamp_logger.info("Received request to report full state")
238
238
 
239
239
  agent_description = self.get_agent_description()
240
240
  agent_health = self.get_agent_health(component_health=True, status=AgentHealthStatus.HEALTHY.value)
@@ -251,8 +251,8 @@ class OpAMPHTTPClient:
251
251
  # Catch exception and don't update the config
252
252
  # The default config is preloaded when the EBPFSpanProcessor is initialized
253
253
  pass
254
-
255
- except requests_odigos.RequestException:
254
+ # OSError contain all socket or network failures, and HTTPException is for HTTP protocol errors
255
+ except (OSError, http.client.HTTPException):
256
256
  pass
257
257
  self.condition.wait(30)
258
258
 
@@ -330,11 +330,11 @@ class OpAMPHTTPClient:
330
330
  return config
331
331
 
332
332
  def send_heartbeat(self) -> opamp_pb2.ServerToAgent: # type: ignore
333
- # opamp_logger.debug("Sending heartbeat to OpAMP server...")
333
+ opamp_logger.debug("Sending heartbeat to OpAMP server...")
334
334
  try:
335
335
  agent_to_server = opamp_pb2.AgentToServer(remote_config_status=self.remote_config_status)
336
336
  return self.send_agent_to_server_message(agent_to_server)
337
- except requests_odigos.RequestException:
337
+ except (OSError, http.client.HTTPException):
338
338
  pass
339
339
 
340
340
  def get_agent_description(self) -> opamp_pb2.AgentDescription: # type: ignore
@@ -419,7 +419,7 @@ class OpAMPHTTPClient:
419
419
 
420
420
  def shutdown(self, custom_failure_message: Optional[str] = None, component_health: bool = False):
421
421
  self.running = False
422
- # opamp_logger.info("Sending agent disconnect message to OpAMP server...")
422
+ opamp_logger.info("Sending agent disconnect message to OpAMP server...")
423
423
  if custom_failure_message:
424
424
  disconnect_message = self.get_agent_failure_disconnect_message(
425
425
  error_message=custom_failure_message,
@@ -2,19 +2,31 @@ import os
2
2
  import socket
3
3
  import http.client
4
4
 
5
- import requests_odigos
5
+ _OPAMP_PATH = "/v1/opamp"
6
+
7
+
8
+ def _post(conn: http.client.HTTPConnection, body: bytes, headers: dict) -> bytes:
9
+ try:
10
+ conn.request("POST", _OPAMP_PATH, body=body, headers=headers)
11
+ response = conn.getresponse()
12
+ status = response.status
13
+ data = response.read()
14
+ if status >= 400:
15
+ raise http.client.HTTPException(f"opamp POST returned status {status}")
16
+ return data
17
+ finally:
18
+ conn.close()
6
19
 
7
20
 
8
21
  class TCPTransport:
9
22
  """HTTP/1.1 over TCP. Talks to ODIGOS_OPAMP_SERVER_HOST."""
10
23
 
11
24
  def __init__(self, host: str):
12
- self._url = f"http://{host}/v1/opamp"
25
+ self._host = host
13
26
 
14
27
  def post(self, body: bytes, headers: dict, timeout: float) -> bytes:
15
- response = requests_odigos.post(self._url, data=body, headers=headers, timeout=timeout)
16
- response.raise_for_status()
17
- return response.content
28
+ conn = http.client.HTTPConnection(self._host, timeout=timeout)
29
+ return _post(conn, body, headers)
18
30
 
19
31
 
20
32
  class UnixTransport:
@@ -25,14 +37,7 @@ class UnixTransport:
25
37
 
26
38
  def post(self, body: bytes, headers: dict, timeout: float) -> bytes:
27
39
  conn = _UnixHTTPConnection(self._socket_path, timeout=timeout)
28
- try:
29
- conn.request("POST", "/v1/opamp", body=body, headers=headers)
30
- response = conn.getresponse()
31
- if response.status >= 400:
32
- raise RuntimeError(f"opamp unix POST returned status {response.status}")
33
- return response.read()
34
- finally:
35
- conn.close()
40
+ return _post(conn, body, headers)
36
41
 
37
42
 
38
43
  class _UnixHTTPConnection(http.client.HTTPConnection):
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "odigos-opentelemetry-python"
7
- version = "1.0.89"
7
+ version = "1.0.90"
8
8
  description = "Odigos Initializer for Python OpenTelemetry Components"
9
9
  requires-python = ">=3.9"
10
10
  authors = [
@@ -12,13 +12,10 @@ authors = [
12
12
  ]
13
13
  dependencies = [
14
14
  "uuid7 == 0.1.0",
15
- "urllib3-odigos == 2.2.2",
16
- "urllib3 === 2.2.3",
17
- "odigos-requests == 2.32.3.dev0",
15
+ "urllib3 >= 2.6.3", # security floor: urllib3 redirect/retry CVEs fixed in 2.5.0
18
16
  "zipp == 3.20.2",
19
17
  "idna == 3.10",
20
18
  "asgiref == 3.8.1",
21
- "requests == 2.32.3",
22
19
  "certifi == 2025.1.31",
23
20
  "charset-normalizer == 3.4.1",
24
21
  "googleapis-common-protos == 1.66.0",
@@ -90,6 +87,7 @@ dependencies = [
90
87
  [project.optional-dependencies]
91
88
  test = [
92
89
  "pytest >= 8.0",
90
+ "pyyaml >= 6.0",
93
91
  ]
94
92
 
95
93
  [dependency-groups]
@@ -1,22 +0,0 @@
1
- import logging
2
-
3
-
4
- # This is the main odigos-opentelemetry-python logger setup function.
5
- # It is used by all modules within this package to ensure that all logs are captured by the same logger.
6
- def setup_logging():
7
- odigos_logger = logging.getLogger('odigos')
8
- odigos_logger.setLevel(logging.DEBUG)
9
- handler = logging.StreamHandler()
10
- formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
11
- handler.setFormatter(formatter)
12
- odigos_logger.addHandler(handler)
13
-
14
- odigos_logger.propagate = False # Prevent logs from reaching the root logger
15
- odigos_logger.disabled = True # Comment to enable the logger
16
-
17
- # Suppress third-party loggers used by odigos-opentelemetry-python (before they are used)
18
- logging.getLogger('urllib3_odigos').setLevel(logging.CRITICAL)
19
- logging.getLogger('requests_odigos').setLevel(logging.CRITICAL)
20
-
21
-
22
- setup_logging()
@@ -1 +0,0 @@
1
- VERSION = "1.0.89"