otel-utils 0.7.1__tar.gz → 1.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.

Potentially problematic release.


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

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: otel-utils
3
- Version: 0.7.1
3
+ Version: 1.0.0
4
4
  Summary: Utilidades simplificadas para instrumentación con OpenTelemetry
5
5
  License: Proprietary
6
6
  Author: Harold Portocarrero
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "otel-utils"
3
- version = "0.7.1"
3
+ version = "1.0.0"
4
4
  description = "Utilidades simplificadas para instrumentación con OpenTelemetry"
5
5
  authors = ["Harold Portocarrero <harold@getcometa.com>"]
6
6
  readme = "README.md"
@@ -150,6 +150,11 @@ class OtelConfigurator:
150
150
 
151
151
  set_logger_provider(logger_provider)
152
152
 
153
+ self.logger = StructuredLogger(
154
+ self.config.service_name,
155
+ environment=self.config.environment
156
+ )
157
+
153
158
  if self.config.enable_console_logging:
154
159
  console_handler = logging.StreamHandler()
155
160
 
@@ -177,18 +182,10 @@ class OtelConfigurator:
177
182
  meter_provider=metrics.get_meter_provider(),
178
183
  )
179
184
 
180
- self.structured_logger = StructuredLogger(
181
- self.config.service_name,
182
- default_attributes={"env": self.config.environment}
183
- )
184
- self.logger = self.structured_logger.logger
185
-
186
- self.logger.propagate = False
187
-
188
185
 
189
186
  def get_logger(service_name: str = None, config: OtelConfig = None) -> StructuredLogger:
190
187
  if config:
191
188
  configurator = OtelConfigurator(config)
192
- return configurator.structured_logger
189
+ return configurator.logger
193
190
 
194
191
  return StructuredLogger(service_name or "default-service")
@@ -9,10 +9,8 @@ from opentelemetry import trace
9
9
 
10
10
  class JsonFormatter(logging.Formatter):
11
11
  def format(self, record):
12
- print('record', record)
13
12
  log_record = {"timestamp": datetime.utcnow().isoformat(), "level": record.levelname, "service": record.name,
14
13
  "message": record.getMessage()}
15
- print('log_record', log_record)
16
14
 
17
15
  ignored_attrs = {
18
16
  'args', 'exc_info', 'exc_text', 'msg', 'message', 'levelname',
@@ -39,11 +37,24 @@ class JsonFormatter(logging.Formatter):
39
37
  elif value is not None and value != '':
40
38
  log_record[key] = value
41
39
 
42
- print('log_record after', log_record)
40
+ if "environment" in log_record:
41
+ log_record["env"] = log_record.pop("environment")
43
42
 
44
43
  return json.dumps(log_record)
45
44
 
46
45
 
46
+ class DefaultAttributesFilter(logging.Filter):
47
+ def __init__(self, default_attributes):
48
+ super().__init__()
49
+ self.default_attributes = default_attributes
50
+
51
+ def filter(self, record):
52
+ for k, v in self.default_attributes.items():
53
+ if not hasattr(record, k):
54
+ setattr(record, k, v)
55
+ return True
56
+
57
+
47
58
  class StructuredLogger:
48
59
  """
49
60
  Logger that produces structured logs with tracing context.
@@ -52,23 +63,23 @@ class StructuredLogger:
52
63
  def __init__(
53
64
  self,
54
65
  service_name: str,
55
- default_attributes: Optional[Dict[str, Any]] = None
66
+ default_attributes: Optional[Dict[str, Any]] = None,
67
+ environment: Optional[str] = None
56
68
  ):
57
69
  self.logger = logging.getLogger(service_name)
58
70
  self.service_name = service_name
59
71
  self.default_attributes = default_attributes or {}
60
-
72
+ if environment:
73
+ self.default_attributes['environment'] = environment
61
74
  self.logger.propagate = False
62
75
 
63
76
  if not self.logger.handlers:
64
77
  handler = logging.StreamHandler()
65
78
  handler.setFormatter(JsonFormatter())
66
79
  self.logger.addHandler(handler)
80
+ self.logger.addFilter(DefaultAttributesFilter(self.default_attributes))
67
81
 
68
82
  def _get_trace_context(self) -> Dict[str, str]:
69
- """
70
- Gets the current tracing context if it exists.
71
- """
72
83
  span = trace.get_current_span()
73
84
  if span.is_recording():
74
85
  ctx = span.get_span_context()
@@ -87,24 +98,15 @@ class StructuredLogger:
87
98
  ):
88
99
  operation = kwargs.pop("operation", None)
89
100
  status = kwargs.pop("status", None)
90
-
91
101
  context = kwargs.copy() if kwargs else None
92
-
93
- extra_data = {
94
- "service_name": self.service_name
95
- }
96
-
97
- extra_data.update(self.default_attributes)
98
-
102
+ extra_data = {}
103
+ extra_data['service_name'] = self.service_name
99
104
  if operation:
100
105
  extra_data["operation"] = operation
101
-
102
106
  if status:
103
107
  extra_data["status"] = status
104
-
105
108
  if context:
106
109
  extra_data["context"] = context
107
-
108
110
  trace_ctx = self._get_trace_context()
109
111
  if trace_ctx and not hasattr(logging.getLogRecordFactory(), "otelTraceID"):
110
112
  trace_id_hex = trace_ctx.get("trace_id")
@@ -120,7 +122,6 @@ class StructuredLogger:
120
122
  extra_data["dd.span_id"] = span_id_hex
121
123
  extra_data["trace_id"] = trace_id_hex
122
124
  extra_data["span_id"] = span_id_hex
123
-
124
125
  self.logger.log(level, message, extra=extra_data)
125
126
 
126
127
  def debug(self, message: str, *args, **kwargs):
@@ -141,9 +142,6 @@ class StructuredLogger:
141
142
  operation_name: str,
142
143
  **context
143
144
  ):
144
- """
145
- Provides context for an operation, recording its beginning and end.
146
- """
147
145
  try:
148
146
  self.info(
149
147
  f"Iniciando {operation_name}",
File without changes