Skip to content

Commit

Permalink
Merge branch 'main' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
ocelotl committed Jul 5, 2023
2 parents 54ae493 + adbcf82 commit 7126dda
Show file tree
Hide file tree
Showing 33 changed files with 583 additions and 642 deletions.
14 changes: 12 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

- Add max_scale option to Exponential Bucket Histogram Aggregation [#3323](https://github.com/open-telemetry/opentelemetry-python/pull/3323))
- Use BoundedAttributes instead of raw dict to extract attributes from LogRecord and Support dropped_attributes_count in LogRecord ([#3310](https://github.com/open-telemetry/opentelemetry-python/pull/3310))

- Add max_scale option to Exponential Bucket Histogram Aggregation
([#3323](https://github.com/open-telemetry/opentelemetry-python/pull/3323))
- Use BoundedAttributes instead of raw dict to extract attributes from LogRecord
([#3310](https://github.com/open-telemetry/opentelemetry-python/pull/3310))
- Support dropped_attributes_count in LogRecord and exporters
([#3351](https://github.com/open-telemetry/opentelemetry-python/pull/3351))
- Add unit to view instrument selection criteria
([#3341](https://github.com/open-telemetry/opentelemetry-python/pull/3341))
- Upgrade opentelemetry-proto to 0.20 and regen
[#3355](https://github.com/open-telemetry/opentelemetry-python/pull/3355))

## Version 1.18.0/0.39b0 (2023-05-04)

Expand All @@ -27,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add speced out environment variables and arguments for BatchLogRecordProcessor
([#3237](https://github.com/open-telemetry/opentelemetry-python/pull/3237))


## Version 1.17.0/0.38b0 (2023-03-22)

- Implement LowMemory temporality
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ Approvers ([@open-telemetry/python-approvers](https://github.com/orgs/open-telem
- [Aaron Abbott](https://github.com/aabmass), Google
- [Jeremy Voss](https://github.com/jeremydvoss), Microsoft
- [Sanket Mehta](https://github.com/sanketmehta28), Cisco
- [Shalev Roda](https://github.com/shalevr), Cisco

Emeritus Approvers

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def _encode_log(log_data: LogData) -> PB2LogRecord:
body=_encode_value(log_data.log_record.body),
severity_text=log_data.log_record.severity_text,
attributes=_encode_attributes(log_data.log_record.attributes),
dropped_attributes_count=log_data.log_record.dropped_attributes,
severity_number=log_data.log_record.severity_number.value,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
from opentelemetry.proto.resource.v1.resource_pb2 import (
Resource as PB2Resource,
)
from opentelemetry.sdk._logs import LogData
from opentelemetry.sdk._logs import LogData, LogLimits
from opentelemetry.sdk._logs import LogRecord as SDKLogRecord
from opentelemetry.sdk.resources import Resource as SDKResource
from opentelemetry.sdk.util.instrumentation import InstrumentationScope
Expand All @@ -51,6 +51,19 @@ def test_encode(self):
sdk_logs, expected_encoding = self.get_test_logs()
self.assertEqual(encode_logs(sdk_logs), expected_encoding)

def test_dropped_attributes_count(self):
sdk_logs = self._get_test_logs_dropped_attributes()
encoded_logs = encode_logs(sdk_logs)
self.assertTrue(hasattr(sdk_logs[0].log_record, "dropped_attributes"))
self.assertEqual(
# pylint:disable=no-member
encoded_logs.resource_logs[0]
.scope_logs[0]
.log_records[0]
.dropped_attributes_count,
2,
)

@staticmethod
def _get_sdk_log_data() -> List[LogData]:
log1 = LogData(
Expand Down Expand Up @@ -251,3 +264,42 @@ def get_test_logs(
)

return sdk_logs, pb2_service_request

@staticmethod
def _get_test_logs_dropped_attributes() -> List[LogData]:
log1 = LogData(
log_record=SDKLogRecord(
timestamp=1644650195189786880,
trace_id=89564621134313219400156819398935297684,
span_id=1312458408527513268,
trace_flags=TraceFlags(0x01),
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"}),
attributes={"a": 1, "b": "c", "user_id": "B121092"},
limits=LogLimits(max_attributes=1),
),
instrumentation_scope=InstrumentationScope(
"first_name", "first_version"
),
)

log2 = LogData(
log_record=SDKLogRecord(
timestamp=1644650249738562048,
trace_id=0,
span_id=0,
trace_flags=TraceFlags.DEFAULT,
severity_text="WARN",
severity_number=SeverityNumber.WARN,
body="Cooper, this is no time for caution!",
resource=SDKResource({"second_resource": "CASE"}),
attributes={},
),
instrumentation_scope=InstrumentationScope(
"second_name", "second_version"
),
)

return [log1, log2]
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,6 @@ def test_encode_histogram(self):
bucket_counts=[1, 4],
explicit_bounds=[10.0, 20.0],
exemplars=[],
flags=pb2.DataPointFlags.FLAG_NONE,
max=18.0,
min=8.0,
)
Expand Down Expand Up @@ -554,7 +553,6 @@ def test_encode_multiple_scope_histogram(self):
bucket_counts=[1, 4],
explicit_bounds=[10.0, 20.0],
exemplars=[],
flags=pb2.DataPointFlags.FLAG_NONE,
max=18.0,
min=8.0,
)
Expand Down Expand Up @@ -590,7 +588,6 @@ def test_encode_multiple_scope_histogram(self):
bucket_counts=[1, 4],
explicit_bounds=[10.0, 20.0],
exemplars=[],
flags=pb2.DataPointFlags.FLAG_NONE,
max=18.0,
min=8.0,
)
Expand Down Expand Up @@ -633,7 +630,6 @@ def test_encode_multiple_scope_histogram(self):
bucket_counts=[1, 4],
explicit_bounds=[10.0, 20.0],
exemplars=[],
flags=pb2.DataPointFlags.FLAG_NONE,
max=18.0,
min=8.0,
)
Expand Down Expand Up @@ -676,7 +672,6 @@ def test_encode_multiple_scope_histogram(self):
bucket_counts=[1, 4],
explicit_bounds=[10.0, 20.0],
exemplars=[],
flags=pb2.DataPointFlags.FLAG_NONE,
max=18.0,
min=8.0,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
CounterMetricFamily,
GaugeMetricFamily,
HistogramMetricFamily,
InfoMetricFamily,
)
from prometheus_client.core import Metric as PrometheusMetric

Expand All @@ -97,6 +98,9 @@

_logger = getLogger(__name__)

_TARGET_INFO_NAME = "target"
_TARGET_INFO_DESCRIPTION = "Target metadata"


def _convert_buckets(
bucket_counts: Sequence[int], explicit_bounds: Sequence[float]
Expand All @@ -116,8 +120,7 @@ def _convert_buckets(
class PrometheusMetricReader(MetricReader):
"""Prometheus metric exporter for OpenTelemetry."""

def __init__(self) -> None:

def __init__(self, disable_target_info: bool = False) -> None:
super().__init__(
preferred_temporality={
Counter: AggregationTemporality.CUMULATIVE,
Expand All @@ -128,7 +131,7 @@ def __init__(self) -> None:
ObservableGauge: AggregationTemporality.CUMULATIVE,
}
)
self._collector = _CustomCollector()
self._collector = _CustomCollector(disable_target_info)
REGISTRY.register(self._collector)
self._collector._callback = self.collect

Expand All @@ -153,12 +156,14 @@ class _CustomCollector:
https://github.com/prometheus/client_python#custom-collectors
"""

def __init__(self):
def __init__(self, disable_target_info: bool = False):
self._callback = None
self._metrics_datas = deque()
self._non_letters_digits_underscore_re = compile(
r"[^\w]", UNICODE | IGNORECASE
)
self._disable_target_info = disable_target_info
self._target_info = None

def add_metrics_data(self, metrics_data: MetricsData) -> None:
"""Add metrics to Prometheus data"""
Expand All @@ -175,6 +180,20 @@ def collect(self) -> None:

metric_family_id_metric_family = {}

if len(self._metrics_datas):
if not self._disable_target_info:
if self._target_info is None:
attributes = {}
for res in self._metrics_datas[0].resource_metrics:
attributes = {**attributes, **res.resource.attributes}

self._target_info = self._create_info_metric(
_TARGET_INFO_NAME, _TARGET_INFO_DESCRIPTION, attributes
)
metric_family_id_metric_family[
_TARGET_INFO_NAME
] = self._target_info

while self._metrics_datas:
self._translate_to_prometheus(
self._metrics_datas.popleft(), metric_family_id_metric_family
Expand Down Expand Up @@ -327,3 +346,11 @@ def _check_value(self, value: Union[int, float, str, Sequence]) -> str:
if not isinstance(value, str):
return dumps(value, default=str)
return str(value)

def _create_info_metric(
self, name: str, description: str, attributes: Dict[str, str]
) -> InfoMetricFamily:
"""Create an Info Metric Family with list of attributes"""
info = InfoMetricFamily(name, description, labels=attributes)
info.add_metric(labels=list(attributes.keys()), value=attributes)
return info
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
from unittest.mock import Mock, patch

from prometheus_client import generate_latest
from prometheus_client.core import CounterMetricFamily, GaugeMetricFamily
from prometheus_client.core import (
CounterMetricFamily,
GaugeMetricFamily,
InfoMetricFamily,
)

from opentelemetry.exporter.prometheus import (
PrometheusMetricReader,
Expand All @@ -33,6 +37,7 @@
ResourceMetrics,
ScopeMetrics,
)
from opentelemetry.sdk.resources import Resource
from opentelemetry.test.metrictestutil import (
_generate_gauge,
_generate_sum,
Expand Down Expand Up @@ -101,7 +106,7 @@ def test_histogram_to_prometheus(self):
]
)

collector = _CustomCollector()
collector = _CustomCollector(disable_target_info=True)
collector.add_metrics_data(metrics_data)
result_bytes = generate_latest(collector)
result = result_bytes.decode("utf-8")
Expand Down Expand Up @@ -146,7 +151,7 @@ def test_sum_to_prometheus(self):
]
)

collector = _CustomCollector()
collector = _CustomCollector(disable_target_info=True)
collector.add_metrics_data(metrics_data)

for prometheus_metric in collector.collect():
Expand Down Expand Up @@ -189,7 +194,7 @@ def test_gauge_to_prometheus(self):
]
)

collector = _CustomCollector()
collector = _CustomCollector(disable_target_info=True)
collector.add_metrics_data(metrics_data)

for prometheus_metric in collector.collect():
Expand Down Expand Up @@ -251,7 +256,7 @@ def test_list_labels(self):
)
]
)
collector = _CustomCollector()
collector = _CustomCollector(disable_target_info=True)
collector.add_metrics_data(metrics_data)

for prometheus_metric in collector.collect():
Expand Down Expand Up @@ -293,3 +298,46 @@ def test_multiple_collection_calls(self):
result_2 = list(metric_reader._collector.collect())
self.assertEqual(result_0, result_1)
self.assertEqual(result_1, result_2)

def test_target_info_enabled_by_default(self):
metric_reader = PrometheusMetricReader()
provider = MeterProvider(
metric_readers=[metric_reader],
resource=Resource({"os": "Unix", "histo": 1}),
)
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")

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}),
)
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:
self.assertNotEqual(type(prometheus_metric), InfoMetricFamily)
self.assertNotEqual(prometheus_metric.name, "target")
self.assertNotEqual(
prometheus_metric.documentation, "Target metadata"
)
self.assertNotIn("os", prometheus_metric.samples[0].labels)
self.assertNotIn("histo", prometheus_metric.samples[0].labels)
9 changes: 5 additions & 4 deletions opentelemetry-api/src/opentelemetry/propagate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,12 @@ def inject(
)
).load()()
)

except Exception: # pylint: disable=broad-except
logger.exception(
"Failed to load configured propagator: %s", propagator
except StopIteration:
raise ValueError(
f"Propagator {propagator} not found. It is either misspelled or not installed."
)
except Exception: # pylint: disable=broad-except
logger.exception("Failed to load propagator: %s", propagator)
raise


Expand Down
19 changes: 9 additions & 10 deletions opentelemetry-api/tests/propagators/test_propagators.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
# type: ignore

from importlib import reload
from logging import ERROR
from os import environ
from unittest import TestCase
from unittest.mock import Mock, patch
Expand Down Expand Up @@ -109,16 +108,16 @@ def test_propagators(propagators):
)
def test_composite_propagators_error(self):

# pylint: disable=import-outside-toplevel
import opentelemetry.propagate
with self.assertRaises(ValueError) as cm:
# pylint: disable=import-outside-toplevel
import opentelemetry.propagate

reload(opentelemetry.propagate)

with self.assertRaises(Exception):
with self.assertLogs(level=ERROR) as err:
reload(opentelemetry.propagate)
self.assertIn(
"Failed to load configured propagator `unknown`",
err.output[0],
)
self.assertEqual(
str(cm.exception),
"Propagator unknown not found. It is either misspelled or not installed.",
)


class TestTraceContextTextMapPropagator(TestCase):
Expand Down
Loading

0 comments on commit 7126dda

Please sign in to comment.