otel-utils 0.1.18__py3-none-any.whl → 0.1.20__py3-none-any.whl

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.

Potentially problematic release.


This version of otel-utils might be problematic. Click here for more details.

@@ -20,6 +20,8 @@ from opentelemetry.sdk.resources import Resource
20
20
  from opentelemetry.sdk.trace import TracerProvider
21
21
  from opentelemetry.sdk.trace.export import BatchSpanProcessor
22
22
 
23
+ from otel_utils.logging import JsonFormatter, StructuredLogger
24
+
23
25
 
24
26
  @dataclass
25
27
  class OtelConfig:
@@ -33,6 +35,7 @@ class OtelConfig:
33
35
  metric_export_interval_ms: int = 30000
34
36
  log_level: int = logging.INFO
35
37
  enable_console_logging: bool = True
38
+ json_logging: bool = True
36
39
 
37
40
  @property
38
41
  def trace_endpoint(self) -> Optional[str]:
@@ -143,20 +146,34 @@ class OtelConfigurator:
143
146
 
144
147
  if self.config.enable_console_logging:
145
148
  console_handler = logging.StreamHandler()
146
- formatter = logging.Formatter(
147
- '[%(asctime)s] %(levelname)s [%(name)s] [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s] - %(message)s',
148
- datefmt='%Y-%m-%d %H:%M:%S'
149
- )
149
+
150
+ if self.config.json_logging:
151
+ formatter = JsonFormatter()
152
+ else:
153
+ formatter = logging.Formatter(
154
+ '[%(asctime)s] %(levelname)s [%(name)s] [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s] - %(message)s',
155
+ datefmt='%Y-%m-%d %H:%M:%S'
156
+ )
157
+
150
158
  console_handler.setFormatter(formatter)
151
159
  root_logger.addHandler(console_handler)
152
160
  root_logger.setLevel(self.config.log_level)
153
161
 
154
162
  LoggingInstrumentor().instrument(
155
163
  logger_provider=logger_provider,
156
- set_logging_format=True,
164
+ set_logging_format=False,
157
165
  log_level=self.config.log_level,
158
166
  tracer_provider=trace.get_tracer_provider(),
159
167
  meter_provider=metrics.get_meter_provider(),
160
168
  )
161
169
 
162
- self.logger = logging.getLogger(self.config.service_name)
170
+ self.structured_logger = StructuredLogger(self.config.service_name)
171
+ self.logger = self.structured_logger.logger
172
+
173
+
174
+ def get_logger(service_name: str = None, config: OtelConfig = None) -> StructuredLogger:
175
+ if config:
176
+ configurator = OtelConfigurator(config)
177
+ return configurator.structured_logger
178
+
179
+ return StructuredLogger(service_name or "default-service")
otel_utils/logging.py CHANGED
@@ -1,6 +1,5 @@
1
1
  import json
2
2
  import logging
3
- import platform
4
3
  from contextlib import contextmanager
5
4
  from datetime import datetime
6
5
  from typing import Any, Dict, Optional
@@ -9,22 +8,32 @@ from opentelemetry import trace
9
8
 
10
9
 
11
10
  class JsonFormatter(logging.Formatter):
11
+
12
12
  def format(self, record):
13
- log_data = {}
13
+ log_record = {"timestamp": datetime.utcnow().isoformat(), "level": record.levelname, "logger": record.name,
14
+ "message": record.getMessage()}
15
+
16
+ ignored_attrs = {
17
+ 'args', 'exc_info', 'exc_text', 'msg', 'message', 'levelname',
18
+ 'levelno', 'pathname', 'filename', 'module', 'stack_info',
19
+ 'lineno', 'funcName', 'created', 'msecs', 'relativeCreated',
20
+ 'name', 'thread', 'threadName', 'processName', 'process',
21
+ 'levelname', 'getMessage'
22
+ }
14
23
 
15
- if hasattr(record, 'structured') and record.structured:
16
- for key, value in record.__dict__.items():
17
- if key not in (
18
- 'args', 'exc_info', 'exc_text', 'msg', 'message', 'levelname',
19
- 'levelno', 'pathname', 'filename', 'module', 'stack_info',
20
- 'lineno', 'funcName', 'created', 'msecs', 'relativeCreated',
21
- 'name', 'thread', 'threadName', 'processName', 'process'
22
- ):
23
- log_data[key] = value
24
+ if hasattr(record, "otelTraceID"):
25
+ log_record["trace_id"] = getattr(record, "otelTraceID")
26
+ if hasattr(record, "otelSpanID"):
27
+ log_record["span_id"] = getattr(record, "otelSpanID")
24
28
 
25
- log_data['message'] = record.getMessage()
29
+ for key, value in record.__dict__.items():
30
+ if key not in ignored_attrs and not key.startswith('_'):
31
+ if key == 'context' and value:
32
+ log_record[key] = value
33
+ elif value is not None and value != '':
34
+ log_record[key] = value
26
35
 
27
- return json.dumps(log_data)
36
+ return json.dumps(log_record)
28
37
 
29
38
 
30
39
  class StructuredLogger:
@@ -38,13 +47,10 @@ class StructuredLogger:
38
47
  default_attributes: Optional[Dict[str, Any]] = None
39
48
  ):
40
49
  self.logger = logging.getLogger(service_name)
41
- self.default_attributes = {
42
- "service.name": service_name,
43
- "host.name": platform.node(),
44
- **(default_attributes or {})
45
- }
50
+ self.service_name = service_name
51
+ self.default_attributes = default_attributes or {}
46
52
 
47
- if not self.logger.handlers or not any(isinstance(h.formatter, JsonFormatter) for h in self.logger.handlers):
53
+ if not self.logger.handlers:
48
54
  handler = logging.StreamHandler()
49
55
  handler.setFormatter(JsonFormatter())
50
56
  self.logger.addHandler(handler)
@@ -69,40 +75,30 @@ class StructuredLogger:
69
75
  *args,
70
76
  **kwargs
71
77
  ):
72
- trace_context = self._get_trace_context()
78
+ operation = kwargs.pop("operation", None)
79
+ status = kwargs.pop("status", None)
73
80
 
74
- log_attributes = {
75
- **self.default_attributes,
76
- "timestamp": datetime.utcnow().isoformat(),
77
- "severity": logging.getLevelName(level),
78
- "logger.name": self.logger.name
79
- }
81
+ context = kwargs.copy() if kwargs else None
80
82
 
81
- if trace_context:
82
- log_attributes["trace_id"] = trace_context.get("trace_id")
83
- log_attributes["span_id"] = trace_context.get("span_id")
83
+ extra_data = {
84
+ "service_name": self.service_name
85
+ }
84
86
 
85
- operation = kwargs.pop("operation", None)
86
87
  if operation:
87
- log_attributes["operation"] = operation
88
+ extra_data["operation"] = operation
88
89
 
89
- status = kwargs.pop("status", None)
90
90
  if status:
91
- log_attributes["status"] = status
92
-
93
- if kwargs:
94
- log_attributes["context"] = kwargs
95
-
96
- self.logger.log(
97
- level,
98
- message,
99
- extra={
100
- "structured": True,
101
- "otel.name": "log",
102
- "otel.kind": "event",
103
- **log_attributes
104
- }
105
- )
91
+ extra_data["status"] = status
92
+
93
+ if context:
94
+ extra_data["context"] = context
95
+
96
+ trace_ctx = self._get_trace_context()
97
+ if trace_ctx and not hasattr(logging.getLogRecordFactory(), "otelTraceID"):
98
+ extra_data["trace_id"] = trace_ctx.get("trace_id")
99
+ extra_data["span_id"] = trace_ctx.get("span_id")
100
+
101
+ self.logger.log(level, message, extra=extra_data)
106
102
 
107
103
  def debug(self, message: str, *args, **kwargs):
108
104
  self._log(logging.DEBUG, message, *args, **kwargs)
@@ -110,6 +106,9 @@ class StructuredLogger:
110
106
  def info(self, message: str, *args, **kwargs):
111
107
  self._log(logging.INFO, message, *args, **kwargs)
112
108
 
109
+ def warning(self, message: str, *args, **kwargs):
110
+ self._log(logging.WARN, message, *args, **kwargs)
111
+
113
112
  def error(self, message: str, *args, **kwargs):
114
113
  self._log(logging.ERROR, message, *args, **kwargs)
115
114
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: otel-utils
3
- Version: 0.1.18
3
+ Version: 0.1.20
4
4
  Summary: Utilidades simplificadas para instrumentación con OpenTelemetry
5
5
  License: Proprietary
6
6
  Author: Harold Portocarrero
@@ -0,0 +1,8 @@
1
+ otel_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ otel_utils/configurator.py,sha256=zfvP2jpIA-CiyxIasvInxhVmrljTgLme6kG_HhKGwgI,7114
3
+ otel_utils/logging.py,sha256=L3js4aSJe_Uv2ij3ZEnAKqaJIiOqcax-tMwMl6z2Vwc,4557
4
+ otel_utils/metrics.py,sha256=XD-t9V3peZJs97hN2hR2rwJKrcCJHqx2cldNOTCpzoA,3664
5
+ otel_utils/tracing.py,sha256=PtowQ7MvYld_xJlVAV4pBQuDBQIqPeP1FQPrzgZx9_Q,2625
6
+ otel_utils-0.1.20.dist-info/METADATA,sha256=06DMawqmfJO3856ogIEfe12x4ceW8WyiPUtzZDpZ52I,5279
7
+ otel_utils-0.1.20.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
8
+ otel_utils-0.1.20.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- otel_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- otel_utils/configurator.py,sha256=uUrBbAYA0FHyJNy4ap50223ZPj0nhQh3EaGULuGCphQ,6572
3
- otel_utils/logging.py,sha256=W4ewXa17r9YQf4wk-8njgfWxyOn03uSVipbBCufcTU8,4428
4
- otel_utils/metrics.py,sha256=XD-t9V3peZJs97hN2hR2rwJKrcCJHqx2cldNOTCpzoA,3664
5
- otel_utils/tracing.py,sha256=PtowQ7MvYld_xJlVAV4pBQuDBQIqPeP1FQPrzgZx9_Q,2625
6
- otel_utils-0.1.18.dist-info/METADATA,sha256=eCopGSP3E0iHmn4GibMCZ7ZzbNdRiNphKrPbIJYrMUw,5279
7
- otel_utils-0.1.18.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
8
- otel_utils-0.1.18.dist-info/RECORD,,