Skip to content

Commit

Permalink
Merge branch 'main' into patch-2
Browse files Browse the repository at this point in the history
  • Loading branch information
ocelotl committed Jul 5, 2023
2 parents cb2e049 + 67e6deb commit ada4c99
Show file tree
Hide file tree
Showing 26 changed files with 391 additions and 134 deletions.
12 changes: 10 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ 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))

Expand All @@ -29,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
22 changes: 22 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,28 @@ behind this is that every PR that adds/removes public symbols fails in CI, forci
If after checking them, it is considered that they are indeed necessary, the PR will be labeled with `Skip Public API check` so that this check is not
run.

Also, we try to keep our console output as clean as possible. Most of the time this means catching expected log messages in the test cases:

``` python
from logging import WARNING

...

def test_case(self):
with self.assertLogs(level=WARNING):
some_function_that_will_log_a_warning_message()
```

Other options can be to disable logging propagation or disabling a logger altogether.

A similar approach can be followed to catch warnings:

``` python
def test_case(self):
with self.assertWarns(DeprecationWarning):
some_function_that_will_raise_a_deprecation_warning()
```

See
[`tox.ini`](https://github.com/open-telemetry/opentelemetry-python/blob/main/tox.ini)
for more detail on available tox commands.
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 @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ def to_json(self, indent=4) -> str:
"attributes": dict(self.attributes)
if bool(self.attributes)
else None,
"dropped_attributes": self.dropped_attributes,
"timestamp": ns_to_iso_str(self.timestamp),
"trace_id": f"0x{format_trace_id(self.trace_id)}"
if self.trace_id is not None
Expand Down
Loading

0 comments on commit ada4c99

Please sign in to comment.