Skip to content

Commit 5392ea6

Browse files
authored
Merge branch 'main' into upgrade-tox
2 parents 685c428 + e98af82 commit 5392ea6

File tree

22 files changed

+626
-143
lines changed

22 files changed

+626
-143
lines changed

Diff for: CHANGELOG.md

+14
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
- Add missing Resource SchemaURL in OTLP exporters
11+
([#3652](https://github.com/open-telemetry/opentelemetry-python/pull/3652))
12+
- Fix loglevel warning text
13+
([#3566](https://github.com/open-telemetry/opentelemetry-python/pull/3566))
14+
- Prometheus Exporter string representation for target_info labels
15+
([#3659](https://github.com/open-telemetry/opentelemetry-python/pull/3659))
16+
- Logs: ObservedTimestamp field is missing in console exporter output
17+
([#3564](https://github.com/open-telemetry/opentelemetry-python/pull/3564))
18+
- Fix explicit bucket histogram aggregation
19+
([#3429](https://github.com/open-telemetry/opentelemetry-python/pull/3429))
20+
- Add `code.lineno`, `code.function` and `code.filepath` to all logs
21+
([#3645](https://github.com/open-telemetry/opentelemetry-python/pull/3645))
1022
- Add Synchronous Gauge instrument
1123
([#3462](https://github.com/open-telemetry/opentelemetry-python/pull/3462))
1224
- Drop support for 3.7
@@ -19,6 +31,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1931
([#3623](https://github.com/open-telemetry/opentelemetry-python/pull/3623))
2032
- Improve Resource Detector timeout messaging
2133
([#3645](https://github.com/open-telemetry/opentelemetry-python/pull/3645))
34+
- Add Proxy classes for logging
35+
([#3575](https://github.com/open-telemetry/opentelemetry-python/pull/3575))
2236

2337
## Version 1.22.0/0.43b0 (2023-12-15)
2438

Diff for: exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/_log_encoder/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ def _encode_resource_logs(batch: Sequence[LogData]) -> List[ResourceLogs]:
7777
ResourceLogs(
7878
resource=_encode_resource(sdk_resource),
7979
scope_logs=scope_logs,
80+
schema_url=sdk_resource.schema_url,
8081
)
8182
)
8283

Diff for: exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/metrics_encoder/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ def encode_metrics(data: MetricsData) -> ExportMetricsServiceRequest:
312312
attributes=_encode_attributes(sdk_resource.attributes)
313313
),
314314
scope_metrics=scope_data.values(),
315+
schema_url=sdk_resource.schema_url,
315316
)
316317
)
317318
resource_metrics = resource_data

Diff for: exporter/opentelemetry-exporter-otlp-proto-common/src/opentelemetry/exporter/otlp/proto/common/_internal/trace_encoder/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ def _encode_resource_spans(
9797
PB2ResourceSpans(
9898
resource=_encode_resource(sdk_resource),
9999
scope_spans=scope_spans,
100+
schema_url=sdk_resource.schema_url,
100101
)
101102
)
102103

Diff for: exporter/opentelemetry-exporter-otlp-proto-common/tests/test_log_encoder.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ def _get_sdk_log_data() -> List[LogData]:
7575
severity_text="WARN",
7676
severity_number=SeverityNumber.WARN,
7777
body="Do not go gentle into that good night. Rage, rage against the dying of the light",
78-
resource=SDKResource({"first_resource": "value"}),
78+
resource=SDKResource(
79+
{"first_resource": "value"},
80+
"resource_schema_url",
81+
),
7982
attributes={"a": 1, "b": "c"},
8083
),
8184
instrumentation_scope=InstrumentationScope(
@@ -124,7 +127,10 @@ def _get_sdk_log_data() -> List[LogData]:
124127
severity_text="INFO",
125128
severity_number=SeverityNumber.INFO,
126129
body="Love is the one thing that transcends time and space",
127-
resource=SDKResource({"first_resource": "value"}),
130+
resource=SDKResource(
131+
{"first_resource": "value"},
132+
"resource_schema_url",
133+
),
128134
attributes={"filename": "model.py", "func_name": "run_method"},
129135
),
130136
instrumentation_scope=InstrumentationScope(
@@ -206,6 +212,7 @@ def get_test_logs(
206212
],
207213
),
208214
],
215+
schema_url="resource_schema_url",
209216
),
210217
PB2ResourceLogs(
211218
resource=PB2Resource(

Diff for: exporter/opentelemetry-exporter-otlp-proto-common/tests/test_metrics_encoder.py

+7
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ def test_encode_sum_int(self):
9999
expected = ExportMetricsServiceRequest(
100100
resource_metrics=[
101101
pb2.ResourceMetrics(
102+
schema_url="resource_schema_url",
102103
resource=OTLPResource(
103104
attributes=[
104105
KeyValue(key="a", value=AnyValue(int_value=1)),
@@ -178,6 +179,7 @@ def test_encode_sum_double(self):
178179
expected = ExportMetricsServiceRequest(
179180
resource_metrics=[
180181
pb2.ResourceMetrics(
182+
schema_url="resource_schema_url",
181183
resource=OTLPResource(
182184
attributes=[
183185
KeyValue(key="a", value=AnyValue(int_value=1)),
@@ -257,6 +259,7 @@ def test_encode_gauge_int(self):
257259
expected = ExportMetricsServiceRequest(
258260
resource_metrics=[
259261
pb2.ResourceMetrics(
262+
schema_url="resource_schema_url",
260263
resource=OTLPResource(
261264
attributes=[
262265
KeyValue(key="a", value=AnyValue(int_value=1)),
@@ -333,6 +336,7 @@ def test_encode_gauge_double(self):
333336
expected = ExportMetricsServiceRequest(
334337
resource_metrics=[
335338
pb2.ResourceMetrics(
339+
schema_url="resource_schema_url",
336340
resource=OTLPResource(
337341
attributes=[
338342
KeyValue(key="a", value=AnyValue(int_value=1)),
@@ -409,6 +413,7 @@ def test_encode_histogram(self):
409413
expected = ExportMetricsServiceRequest(
410414
resource_metrics=[
411415
pb2.ResourceMetrics(
416+
schema_url="resource_schema_url",
412417
resource=OTLPResource(
413418
attributes=[
414419
KeyValue(key="a", value=AnyValue(int_value=1)),
@@ -511,6 +516,7 @@ def test_encode_multiple_scope_histogram(self):
511516
expected = ExportMetricsServiceRequest(
512517
resource_metrics=[
513518
pb2.ResourceMetrics(
519+
schema_url="resource_schema_url",
514520
resource=OTLPResource(
515521
attributes=[
516522
KeyValue(key="a", value=AnyValue(int_value=1)),
@@ -739,6 +745,7 @@ def test_encode_exponential_histogram(self):
739745
expected = ExportMetricsServiceRequest(
740746
resource_metrics=[
741747
pb2.ResourceMetrics(
748+
schema_url="resource_schema_url",
742749
resource=OTLPResource(
743750
attributes=[
744751
KeyValue(key="a", value=AnyValue(int_value=1)),

Diff for: exporter/opentelemetry-exporter-otlp-proto-common/tests/test_trace_encoder.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def get_exhaustive_otel_span_list() -> List[SDKSpan]:
111111
links=(
112112
SDKLink(context=other_context, attributes={"key_bool": True}),
113113
),
114-
resource=SDKResource({}),
114+
resource=SDKResource({}, "resource_schema_url"),
115115
)
116116
span1.start(start_time=start_times[0])
117117
span1.set_attribute("key_bool", False)
@@ -143,7 +143,7 @@ def get_exhaustive_otel_span_list() -> List[SDKSpan]:
143143
name="test-span-4",
144144
context=other_context,
145145
parent=None,
146-
resource=SDKResource({}),
146+
resource=SDKResource({}, "resource_schema_url"),
147147
instrumentation_scope=SDKInstrumentationScope(
148148
name="name", version="version"
149149
),
@@ -163,6 +163,7 @@ def get_exhaustive_test_spans(
163163
pb2_service_request = PB2ExportTraceServiceRequest(
164164
resource_spans=[
165165
PB2ResourceSpans(
166+
schema_url="resource_schema_url",
166167
resource=PB2Resource(),
167168
scope_spans=[
168169
PB2ScopeSpans(

Diff for: exporter/opentelemetry-exporter-prometheus/src/opentelemetry/exporter/prometheus/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,8 @@ def _create_info_metric(
380380
"""Create an Info Metric Family with list of attributes"""
381381
# sanitize the attribute names according to Prometheus rule
382382
attributes = {
383-
self._sanitize(key): value for key, value in attributes.items()
383+
self._sanitize(key): self._check_value(value)
384+
for key, value in attributes.items()
384385
}
385386
info = InfoMetricFamily(name, description, labels=attributes)
386387
info.add_metric(labels=list(attributes.keys()), value=attributes)

Diff for: exporter/opentelemetry-exporter-prometheus/tests/test_prometheus_exporter.py

+30-15
Original file line numberDiff line numberDiff line change
@@ -351,30 +351,33 @@ def test_target_info_enabled_by_default(self):
351351
metric_reader = PrometheusMetricReader()
352352
provider = MeterProvider(
353353
metric_readers=[metric_reader],
354-
resource=Resource({"os": "Unix", "histo": 1}),
354+
resource=Resource({"os": "Unix", "version": "1.2.3"}),
355355
)
356356
meter = provider.get_meter("getting-started", "0.1.2")
357357
counter = meter.create_counter("counter")
358358
counter.add(1)
359359
result = list(metric_reader._collector.collect())
360360

361-
for prometheus_metric in result[:0]:
362-
self.assertEqual(type(prometheus_metric), InfoMetricFamily)
363-
self.assertEqual(prometheus_metric.name, "target")
364-
self.assertEqual(
365-
prometheus_metric.documentation, "Target metadata"
366-
)
367-
self.assertTrue(len(prometheus_metric.samples) == 1)
368-
self.assertEqual(prometheus_metric.samples[0].value, 1)
369-
self.assertTrue(len(prometheus_metric.samples[0].labels) == 2)
370-
self.assertEqual(prometheus_metric.samples[0].labels["os"], "Unix")
371-
self.assertEqual(prometheus_metric.samples[0].labels["histo"], "1")
361+
self.assertEqual(len(result), 2)
362+
363+
prometheus_metric = result[0]
364+
365+
self.assertEqual(type(prometheus_metric), InfoMetricFamily)
366+
self.assertEqual(prometheus_metric.name, "target")
367+
self.assertEqual(prometheus_metric.documentation, "Target metadata")
368+
self.assertTrue(len(prometheus_metric.samples) == 1)
369+
self.assertEqual(prometheus_metric.samples[0].value, 1)
370+
self.assertTrue(len(prometheus_metric.samples[0].labels) == 2)
371+
self.assertEqual(prometheus_metric.samples[0].labels["os"], "Unix")
372+
self.assertEqual(
373+
prometheus_metric.samples[0].labels["version"], "1.2.3"
374+
)
372375

373376
def test_target_info_disabled(self):
374377
metric_reader = PrometheusMetricReader(disable_target_info=True)
375378
provider = MeterProvider(
376379
metric_readers=[metric_reader],
377-
resource=Resource({"os": "Unix", "histo": 1}),
380+
resource=Resource({"os": "Unix", "version": "1.2.3"}),
378381
)
379382
meter = provider.get_meter("getting-started", "0.1.2")
380383
counter = meter.create_counter("counter")
@@ -388,7 +391,7 @@ def test_target_info_disabled(self):
388391
prometheus_metric.documentation, "Target metadata"
389392
)
390393
self.assertNotIn("os", prometheus_metric.samples[0].labels)
391-
self.assertNotIn("histo", prometheus_metric.samples[0].labels)
394+
self.assertNotIn("version", prometheus_metric.samples[0].labels)
392395

393396
def test_target_info_sanitize(self):
394397
metric_reader = PrometheusMetricReader()
@@ -398,6 +401,8 @@ def test_target_info_sanitize(self):
398401
{
399402
"system.os": "Unix",
400403
"system.name": "Prometheus Target Sanitize",
404+
"histo": 1,
405+
"ratio": 0.1,
401406
}
402407
),
403408
)
@@ -411,7 +416,7 @@ def test_target_info_sanitize(self):
411416
self.assertEqual(prometheus_metric.documentation, "Target metadata")
412417
self.assertTrue(len(prometheus_metric.samples) == 1)
413418
self.assertEqual(prometheus_metric.samples[0].value, 1)
414-
self.assertTrue(len(prometheus_metric.samples[0].labels) == 2)
419+
self.assertTrue(len(prometheus_metric.samples[0].labels) == 4)
415420
self.assertTrue("system_os" in prometheus_metric.samples[0].labels)
416421
self.assertEqual(
417422
prometheus_metric.samples[0].labels["system_os"], "Unix"
@@ -421,3 +426,13 @@ def test_target_info_sanitize(self):
421426
prometheus_metric.samples[0].labels["system_name"],
422427
"Prometheus Target Sanitize",
423428
)
429+
self.assertTrue("histo" in prometheus_metric.samples[0].labels)
430+
self.assertEqual(
431+
prometheus_metric.samples[0].labels["histo"],
432+
"1",
433+
)
434+
self.assertTrue("ratio" in prometheus_metric.samples[0].labels)
435+
self.assertEqual(
436+
prometheus_metric.samples[0].labels["ratio"],
437+
"0.1",
438+
)

Diff for: opentelemetry-api/src/opentelemetry/_logs/_internal/__init__.py

+54-7
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,37 @@ def emit(self, record: "LogRecord") -> None:
112112
pass
113113

114114

115+
class ProxyLogger(Logger):
116+
def __init__( # pylint: disable=super-init-not-called
117+
self,
118+
name: str,
119+
version: Optional[str] = None,
120+
schema_url: Optional[str] = None,
121+
):
122+
self._name = name
123+
self._version = version
124+
self._schema_url = schema_url
125+
self._real_logger: Optional[Logger] = None
126+
self._noop_logger = NoOpLogger(name)
127+
128+
@property
129+
def _logger(self) -> Logger:
130+
if self._real_logger:
131+
return self._real_logger
132+
133+
if _LOGGER_PROVIDER:
134+
self._real_logger = _LOGGER_PROVIDER.get_logger(
135+
self._name,
136+
self._version,
137+
self._schema_url,
138+
)
139+
return self._real_logger
140+
return self._noop_logger
141+
142+
def emit(self, record: LogRecord) -> None:
143+
self._logger.emit(record)
144+
145+
115146
class LoggerProvider(ABC):
116147
"""
117148
LoggerProvider is the entry point of the API. It provides access to Logger instances.
@@ -166,21 +197,37 @@ def get_logger(
166197
return NoOpLogger(name, version=version, schema_url=schema_url)
167198

168199

169-
# TODO: ProxyLoggerProvider
200+
class ProxyLoggerProvider(LoggerProvider):
201+
def get_logger(
202+
self,
203+
name: str,
204+
version: Optional[str] = None,
205+
schema_url: Optional[str] = None,
206+
) -> Logger:
207+
if _LOGGER_PROVIDER:
208+
return _LOGGER_PROVIDER.get_logger(
209+
name,
210+
version=version,
211+
schema_url=schema_url,
212+
)
213+
return ProxyLogger(
214+
name,
215+
version=version,
216+
schema_url=schema_url,
217+
)
170218

171219

172220
_LOGGER_PROVIDER_SET_ONCE = Once()
173-
_LOGGER_PROVIDER = None
221+
_LOGGER_PROVIDER: Optional[LoggerProvider] = None
222+
_PROXY_LOGGER_PROVIDER = ProxyLoggerProvider()
174223

175224

176225
def get_logger_provider() -> LoggerProvider:
177226
"""Gets the current global :class:`~.LoggerProvider` object."""
178-
global _LOGGER_PROVIDER # pylint: disable=global-statement
227+
global _LOGGER_PROVIDER # pylint: disable=global-variable-not-assigned
179228
if _LOGGER_PROVIDER is None:
180229
if _OTEL_PYTHON_LOGGER_PROVIDER not in environ:
181-
# TODO: return proxy
182-
_LOGGER_PROVIDER = NoOpLoggerProvider()
183-
return _LOGGER_PROVIDER
230+
return _PROXY_LOGGER_PROVIDER
184231

185232
logger_provider: LoggerProvider = _load_provider( # type: ignore
186233
_OTEL_PYTHON_LOGGER_PROVIDER, "logger_provider"
@@ -194,7 +241,7 @@ def get_logger_provider() -> LoggerProvider:
194241
def _set_logger_provider(logger_provider: LoggerProvider, log: bool) -> None:
195242
def set_lp() -> None:
196243
global _LOGGER_PROVIDER # pylint: disable=global-statement
197-
_LOGGER_PROVIDER = logger_provider # type: ignore
244+
_LOGGER_PROVIDER = logger_provider
198245

199246
did_set = _LOGGER_PROVIDER_SET_ONCE.do_once(set_lp)
200247

Diff for: opentelemetry-api/tests/logs/test_logger_provider.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def test_get_logger_provider(self):
4444
assert logs_internal._LOGGER_PROVIDER is None
4545

4646
assert isinstance(
47-
get_logger_provider(), logs_internal.NoOpLoggerProvider
47+
get_logger_provider(), logs_internal.ProxyLoggerProvider
4848
)
4949

5050
logs_internal._LOGGER_PROVIDER = None

0 commit comments

Comments
 (0)