Skip to content

Commit

Permalink
merged current main and applied suggestion from review
Browse files Browse the repository at this point in the history
  • Loading branch information
a-recknagel authored and Arne Caratti committed Feb 13, 2024
2 parents 222fb9b + e98af82 commit a20cbea
Show file tree
Hide file tree
Showing 16 changed files with 212 additions and 38 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased

- Add missing Resource SchemaURL in OTLP exporters
([#3652](https://github.com/open-telemetry/opentelemetry-python/pull/3652))
- Fix loglevel warning text
([#3566](https://github.com/open-telemetry/opentelemetry-python/pull/3566))
- Prometheus Exporter string representation for target_info labels
([#3659](https://github.com/open-telemetry/opentelemetry-python/pull/3659))
- Retain meaningful logrecord attributes and apply log-message
formatting ([#3673](https://github.com/open-telemetry/opentelemetry-python/pull/3673))
- Logs: ObservedTimestamp field is missing in console exporter output
Expand All @@ -26,6 +33,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#3623](https://github.com/open-telemetry/opentelemetry-python/pull/3623))
- Improve Resource Detector timeout messaging
([#3645](https://github.com/open-telemetry/opentelemetry-python/pull/3645))
- Add Proxy classes for logging
([#3575](https://github.com/open-telemetry/opentelemetry-python/pull/3575))

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def _encode_resource_logs(batch: Sequence[LogData]) -> List[ResourceLogs]:
ResourceLogs(
resource=_encode_resource(sdk_resource),
scope_logs=scope_logs,
schema_url=sdk_resource.schema_url,
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ def encode_metrics(data: MetricsData) -> ExportMetricsServiceRequest:
attributes=_encode_attributes(sdk_resource.attributes)
),
scope_metrics=scope_data.values(),
schema_url=sdk_resource.schema_url,
)
)
resource_metrics = resource_data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def _encode_resource_spans(
PB2ResourceSpans(
resource=_encode_resource(sdk_resource),
scope_spans=scope_spans,
schema_url=sdk_resource.schema_url,
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,10 @@ def _get_sdk_log_data() -> List[LogData]:
severity_text="WARN",
severity_number=SeverityNumber.WARN,
body="Do not go gentle into that good night. Rage, rage against the dying of the light",
resource=SDKResource({"first_resource": "value"}),
resource=SDKResource(
{"first_resource": "value"},
"resource_schema_url",
),
attributes={"a": 1, "b": "c"},
),
instrumentation_scope=InstrumentationScope(
Expand Down Expand Up @@ -124,7 +127,10 @@ def _get_sdk_log_data() -> List[LogData]:
severity_text="INFO",
severity_number=SeverityNumber.INFO,
body="Love is the one thing that transcends time and space",
resource=SDKResource({"first_resource": "value"}),
resource=SDKResource(
{"first_resource": "value"},
"resource_schema_url",
),
attributes={"filename": "model.py", "func_name": "run_method"},
),
instrumentation_scope=InstrumentationScope(
Expand Down Expand Up @@ -206,6 +212,7 @@ def get_test_logs(
],
),
],
schema_url="resource_schema_url",
),
PB2ResourceLogs(
resource=PB2Resource(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def test_encode_sum_int(self):
expected = ExportMetricsServiceRequest(
resource_metrics=[
pb2.ResourceMetrics(
schema_url="resource_schema_url",
resource=OTLPResource(
attributes=[
KeyValue(key="a", value=AnyValue(int_value=1)),
Expand Down Expand Up @@ -178,6 +179,7 @@ def test_encode_sum_double(self):
expected = ExportMetricsServiceRequest(
resource_metrics=[
pb2.ResourceMetrics(
schema_url="resource_schema_url",
resource=OTLPResource(
attributes=[
KeyValue(key="a", value=AnyValue(int_value=1)),
Expand Down Expand Up @@ -257,6 +259,7 @@ def test_encode_gauge_int(self):
expected = ExportMetricsServiceRequest(
resource_metrics=[
pb2.ResourceMetrics(
schema_url="resource_schema_url",
resource=OTLPResource(
attributes=[
KeyValue(key="a", value=AnyValue(int_value=1)),
Expand Down Expand Up @@ -333,6 +336,7 @@ def test_encode_gauge_double(self):
expected = ExportMetricsServiceRequest(
resource_metrics=[
pb2.ResourceMetrics(
schema_url="resource_schema_url",
resource=OTLPResource(
attributes=[
KeyValue(key="a", value=AnyValue(int_value=1)),
Expand Down Expand Up @@ -409,6 +413,7 @@ def test_encode_histogram(self):
expected = ExportMetricsServiceRequest(
resource_metrics=[
pb2.ResourceMetrics(
schema_url="resource_schema_url",
resource=OTLPResource(
attributes=[
KeyValue(key="a", value=AnyValue(int_value=1)),
Expand Down Expand Up @@ -511,6 +516,7 @@ def test_encode_multiple_scope_histogram(self):
expected = ExportMetricsServiceRequest(
resource_metrics=[
pb2.ResourceMetrics(
schema_url="resource_schema_url",
resource=OTLPResource(
attributes=[
KeyValue(key="a", value=AnyValue(int_value=1)),
Expand Down Expand Up @@ -739,6 +745,7 @@ def test_encode_exponential_histogram(self):
expected = ExportMetricsServiceRequest(
resource_metrics=[
pb2.ResourceMetrics(
schema_url="resource_schema_url",
resource=OTLPResource(
attributes=[
KeyValue(key="a", value=AnyValue(int_value=1)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ def get_exhaustive_otel_span_list() -> List[SDKSpan]:
links=(
SDKLink(context=other_context, attributes={"key_bool": True}),
),
resource=SDKResource({}),
resource=SDKResource({}, "resource_schema_url"),
)
span1.start(start_time=start_times[0])
span1.set_attribute("key_bool", False)
Expand Down Expand Up @@ -143,7 +143,7 @@ def get_exhaustive_otel_span_list() -> List[SDKSpan]:
name="test-span-4",
context=other_context,
parent=None,
resource=SDKResource({}),
resource=SDKResource({}, "resource_schema_url"),
instrumentation_scope=SDKInstrumentationScope(
name="name", version="version"
),
Expand All @@ -163,6 +163,7 @@ def get_exhaustive_test_spans(
pb2_service_request = PB2ExportTraceServiceRequest(
resource_spans=[
PB2ResourceSpans(
schema_url="resource_schema_url",
resource=PB2Resource(),
scope_spans=[
PB2ScopeSpans(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,8 @@ def _create_info_metric(
"""Create an Info Metric Family with list of attributes"""
# sanitize the attribute names according to Prometheus rule
attributes = {
self._sanitize(key): value for key, value in attributes.items()
self._sanitize(key): self._check_value(value)
for key, value in attributes.items()
}
info = InfoMetricFamily(name, description, labels=attributes)
info.add_metric(labels=list(attributes.keys()), value=attributes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,30 +351,33 @@ def test_target_info_enabled_by_default(self):
metric_reader = PrometheusMetricReader()
provider = MeterProvider(
metric_readers=[metric_reader],
resource=Resource({"os": "Unix", "histo": 1}),
resource=Resource({"os": "Unix", "version": "1.2.3"}),
)
meter = provider.get_meter("getting-started", "0.1.2")
counter = meter.create_counter("counter")
counter.add(1)
result = list(metric_reader._collector.collect())

for prometheus_metric in result[:0]:
self.assertEqual(type(prometheus_metric), InfoMetricFamily)
self.assertEqual(prometheus_metric.name, "target")
self.assertEqual(
prometheus_metric.documentation, "Target metadata"
)
self.assertTrue(len(prometheus_metric.samples) == 1)
self.assertEqual(prometheus_metric.samples[0].value, 1)
self.assertTrue(len(prometheus_metric.samples[0].labels) == 2)
self.assertEqual(prometheus_metric.samples[0].labels["os"], "Unix")
self.assertEqual(prometheus_metric.samples[0].labels["histo"], "1")
self.assertEqual(len(result), 2)

prometheus_metric = result[0]

self.assertEqual(type(prometheus_metric), InfoMetricFamily)
self.assertEqual(prometheus_metric.name, "target")
self.assertEqual(prometheus_metric.documentation, "Target metadata")
self.assertTrue(len(prometheus_metric.samples) == 1)
self.assertEqual(prometheus_metric.samples[0].value, 1)
self.assertTrue(len(prometheus_metric.samples[0].labels) == 2)
self.assertEqual(prometheus_metric.samples[0].labels["os"], "Unix")
self.assertEqual(
prometheus_metric.samples[0].labels["version"], "1.2.3"
)

def test_target_info_disabled(self):
metric_reader = PrometheusMetricReader(disable_target_info=True)
provider = MeterProvider(
metric_readers=[metric_reader],
resource=Resource({"os": "Unix", "histo": 1}),
resource=Resource({"os": "Unix", "version": "1.2.3"}),
)
meter = provider.get_meter("getting-started", "0.1.2")
counter = meter.create_counter("counter")
Expand All @@ -388,7 +391,7 @@ def test_target_info_disabled(self):
prometheus_metric.documentation, "Target metadata"
)
self.assertNotIn("os", prometheus_metric.samples[0].labels)
self.assertNotIn("histo", prometheus_metric.samples[0].labels)
self.assertNotIn("version", prometheus_metric.samples[0].labels)

def test_target_info_sanitize(self):
metric_reader = PrometheusMetricReader()
Expand All @@ -398,6 +401,8 @@ def test_target_info_sanitize(self):
{
"system.os": "Unix",
"system.name": "Prometheus Target Sanitize",
"histo": 1,
"ratio": 0.1,
}
),
)
Expand All @@ -411,7 +416,7 @@ def test_target_info_sanitize(self):
self.assertEqual(prometheus_metric.documentation, "Target metadata")
self.assertTrue(len(prometheus_metric.samples) == 1)
self.assertEqual(prometheus_metric.samples[0].value, 1)
self.assertTrue(len(prometheus_metric.samples[0].labels) == 2)
self.assertTrue(len(prometheus_metric.samples[0].labels) == 4)
self.assertTrue("system_os" in prometheus_metric.samples[0].labels)
self.assertEqual(
prometheus_metric.samples[0].labels["system_os"], "Unix"
Expand All @@ -421,3 +426,13 @@ def test_target_info_sanitize(self):
prometheus_metric.samples[0].labels["system_name"],
"Prometheus Target Sanitize",
)
self.assertTrue("histo" in prometheus_metric.samples[0].labels)
self.assertEqual(
prometheus_metric.samples[0].labels["histo"],
"1",
)
self.assertTrue("ratio" in prometheus_metric.samples[0].labels)
self.assertEqual(
prometheus_metric.samples[0].labels["ratio"],
"0.1",
)
61 changes: 54 additions & 7 deletions opentelemetry-api/src/opentelemetry/_logs/_internal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,37 @@ def emit(self, record: "LogRecord") -> None:
pass


class ProxyLogger(Logger):
def __init__( # pylint: disable=super-init-not-called
self,
name: str,
version: Optional[str] = None,
schema_url: Optional[str] = None,
):
self._name = name
self._version = version
self._schema_url = schema_url
self._real_logger: Optional[Logger] = None
self._noop_logger = NoOpLogger(name)

@property
def _logger(self) -> Logger:
if self._real_logger:
return self._real_logger

if _LOGGER_PROVIDER:
self._real_logger = _LOGGER_PROVIDER.get_logger(
self._name,
self._version,
self._schema_url,
)
return self._real_logger
return self._noop_logger

def emit(self, record: LogRecord) -> None:
self._logger.emit(record)


class LoggerProvider(ABC):
"""
LoggerProvider is the entry point of the API. It provides access to Logger instances.
Expand Down Expand Up @@ -166,21 +197,37 @@ def get_logger(
return NoOpLogger(name, version=version, schema_url=schema_url)


# TODO: ProxyLoggerProvider
class ProxyLoggerProvider(LoggerProvider):
def get_logger(
self,
name: str,
version: Optional[str] = None,
schema_url: Optional[str] = None,
) -> Logger:
if _LOGGER_PROVIDER:
return _LOGGER_PROVIDER.get_logger(
name,
version=version,
schema_url=schema_url,
)
return ProxyLogger(
name,
version=version,
schema_url=schema_url,
)


_LOGGER_PROVIDER_SET_ONCE = Once()
_LOGGER_PROVIDER = None
_LOGGER_PROVIDER: Optional[LoggerProvider] = None
_PROXY_LOGGER_PROVIDER = ProxyLoggerProvider()


def get_logger_provider() -> LoggerProvider:
"""Gets the current global :class:`~.LoggerProvider` object."""
global _LOGGER_PROVIDER # pylint: disable=global-statement
global _LOGGER_PROVIDER # pylint: disable=global-variable-not-assigned
if _LOGGER_PROVIDER is None:
if _OTEL_PYTHON_LOGGER_PROVIDER not in environ:
# TODO: return proxy
_LOGGER_PROVIDER = NoOpLoggerProvider()
return _LOGGER_PROVIDER
return _PROXY_LOGGER_PROVIDER

logger_provider: LoggerProvider = _load_provider( # type: ignore
_OTEL_PYTHON_LOGGER_PROVIDER, "logger_provider"
Expand All @@ -194,7 +241,7 @@ def get_logger_provider() -> LoggerProvider:
def _set_logger_provider(logger_provider: LoggerProvider, log: bool) -> None:
def set_lp() -> None:
global _LOGGER_PROVIDER # pylint: disable=global-statement
_LOGGER_PROVIDER = logger_provider # type: ignore
_LOGGER_PROVIDER = logger_provider

did_set = _LOGGER_PROVIDER_SET_ONCE.do_once(set_lp)

Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-api/tests/logs/test_logger_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def test_get_logger_provider(self):
assert logs_internal._LOGGER_PROVIDER is None

assert isinstance(
get_logger_provider(), logs_internal.NoOpLoggerProvider
get_logger_provider(), logs_internal.ProxyLoggerProvider
)

logs_internal._LOGGER_PROVIDER = None
Expand Down

0 comments on commit a20cbea

Please sign in to comment.