Skip to content

Commit

Permalink
Merge branch 'master' into feature/trace-get-current-span
Browse files Browse the repository at this point in the history
  • Loading branch information
toumorokoshi committed Jun 8, 2020
2 parents 3732f31 + 7ad8bbc commit c8de5ed
Show file tree
Hide file tree
Showing 28 changed files with 369 additions and 174 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ Approvers ([@open-telemetry/python-approvers](https://github.com/orgs/open-telem
- [Chris Kleinknecht](https://github.com/c24t), Google
- [Diego Hurtado](https://github.com/ocelotl)
- [Hector Hernandez](https://github.com/hectorhdzg), Microsoft
- [Leighton Chen](https://github.com/lzchen), Microsoft
- [Mauricio Vásquez](https://github.com/mauriciovasquezbernal), Kinvolk
- [Reiley Yang](https://github.com/reyang), Microsoft

Expand All @@ -116,16 +115,17 @@ Approvers ([@open-telemetry/python-approvers](https://github.com/orgs/open-telem
Maintainers ([@open-telemetry/python-maintainers](https://github.com/orgs/open-telemetry/teams/python-maintainers)):

- [Alex Boten](https://github.com/codeboten), LightStep
- [Leighton Chen](https://github.com/lzchen), Microsoft
- [Yusuke Tsutsumi](https://github.com/toumorokoshi), Zillow Group

*Find more about the maintainer role in [community repository](https://github.com/open-telemetry/community/blob/master/community-membership.md#maintainer).*

### Thanks to all the people who already contributed!

<a href="https://github.com/open-telemetry/opentelemetry-python/graphs/contributors">
<img src="https://contributors-img.web.app/image?repo=open-telemetry/opentelemetry-python" />
</a>

*Find more about the maintainer role in [community repository](https://github.com/open-telemetry/community/blob/master/community-membership.md#maintainer).*

## Release Schedule

OpenTelemetry Python is under active development.
Expand Down
2 changes: 1 addition & 1 deletion dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pylint==2.4.4
flake8==3.7.9
isort~=4.3
black>=19.3b0,==19.*
mypy==0.740
mypy==0.770
sphinx~=2.1
sphinx-rtd-theme~=0.4
sphinx-autodoc-typehints~=1.10.2
Expand Down
3 changes: 2 additions & 1 deletion docs/examples/basic_meter/observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import psutil

from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics import MeterProvider, ValueObserver
from opentelemetry.sdk.metrics.export import ConsoleMetricsExporter
from opentelemetry.sdk.metrics.export.batcher import UngroupedBatcher
from opentelemetry.sdk.metrics.export.controller import PushController
Expand All @@ -43,6 +43,7 @@ def get_cpu_usage_callback(observer):
description="per-cpu usage",
unit="1",
value_type=float,
observer_type=ValueObserver,
label_keys=("cpu_number",),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ def translate_to_collector(
)

metric_descriptor = metrics_pb2.MetricDescriptor(
name=metric_record.metric.name,
description=metric_record.metric.description,
unit=metric_record.metric.unit,
type=get_collector_metric_type(metric_record.metric),
name=metric_record.instrument.name,
description=metric_record.instrument.description,
unit=metric_record.instrument.unit,
type=get_collector_metric_type(metric_record.instrument),
label_keys=label_keys,
)

Expand Down Expand Up @@ -151,14 +151,14 @@ def get_collector_point(metric_record: MetricRecord) -> metrics_pb2.Point:
metric_record.aggregator.last_update_timestamp
)
)
if metric_record.metric.value_type == int:
if metric_record.instrument.value_type == int:
point.int64_value = metric_record.aggregator.checkpoint
elif metric_record.metric.value_type == float:
elif metric_record.instrument.value_type == float:
point.double_value = metric_record.aggregator.checkpoint
else:
raise TypeError(
"Unsupported metric type: {}".format(
metric_record.metric.value_type
metric_record.instrument.value_type
)
)
return point
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,21 @@ def test_get_collector_point(self):
"testName", "testDescription", "unit", float, ValueRecorder
)
result = metrics_exporter.get_collector_point(
MetricRecord(aggregator, self._key_labels, int_counter)
MetricRecord(int_counter, self._key_labels, aggregator)
)
self.assertIsInstance(result, metrics_pb2.Point)
self.assertIsInstance(result.timestamp, Timestamp)
self.assertEqual(result.int64_value, 0)
aggregator.update(123.5)
aggregator.take_checkpoint()
result = metrics_exporter.get_collector_point(
MetricRecord(aggregator, self._key_labels, float_counter)
MetricRecord(float_counter, self._key_labels, aggregator)
)
self.assertEqual(result.double_value, 123.5)
self.assertRaises(
TypeError,
metrics_exporter.get_collector_point(
MetricRecord(aggregator, self._key_labels, valuerecorder)
MetricRecord(valuerecorder, self._key_labels, aggregator)
),
)

Expand All @@ -122,7 +122,7 @@ def test_export(self):
"testname", "testdesc", "unit", int, Counter, ["environment"]
)
record = MetricRecord(
aggregate.CounterAggregator(), self._key_labels, test_metric
test_metric, self._key_labels, aggregate.CounterAggregator(),
)

result = collector_exporter.export([record])
Expand All @@ -147,7 +147,7 @@ def test_translate_to_collector(self):
aggregator = aggregate.CounterAggregator()
aggregator.update(123)
aggregator.take_checkpoint()
record = MetricRecord(aggregator, self._key_labels, test_metric)
record = MetricRecord(test_metric, self._key_labels, aggregator,)
output_metrics = metrics_exporter.translate_to_collector([record])
self.assertEqual(len(output_metrics), 1)
self.assertIsInstance(output_metrics[0], metrics_pb2.Metric)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,22 +152,22 @@ def _translate_to_prometheus(self, metric_record: MetricRecord):
metric_name = ""
if self._prefix != "":
metric_name = self._prefix + "_"
metric_name += self._sanitize(metric_record.metric.name)
metric_name += self._sanitize(metric_record.instrument.name)

if isinstance(metric_record.metric, Counter):
if isinstance(metric_record.instrument, Counter):
prometheus_metric = CounterMetricFamily(
name=metric_name,
documentation=metric_record.metric.description,
documentation=metric_record.instrument.description,
labels=label_keys,
)
prometheus_metric.add_metric(
labels=label_values, value=metric_record.aggregator.checkpoint
)
# TODO: Add support for histograms when supported in OT
elif isinstance(metric_record.metric, ValueRecorder):
elif isinstance(metric_record.instrument, ValueRecorder):
prometheus_metric = UnknownMetricFamily(
name=metric_name,
documentation=metric_record.metric.description,
documentation=metric_record.instrument.description,
labels=label_keys,
)
prometheus_metric.add_metric(
Expand All @@ -176,7 +176,7 @@ def _translate_to_prometheus(self, metric_record: MetricRecord):

else:
logger.warning(
"Unsupported metric type. %s", type(metric_record.metric)
"Unsupported metric type. %s", type(metric_record.instrument)
)
return prometheus_metric

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def test_shutdown(self):
def test_export(self):
with self._registry_register_patch:
record = MetricRecord(
CounterAggregator(), self._labels_key, self._test_metric
self._test_metric, self._labels_key, CounterAggregator(),
)
exporter = PrometheusMetricsExporter()
result = exporter.export([record])
Expand All @@ -90,7 +90,7 @@ def test_counter_to_prometheus(self):
aggregator = CounterAggregator()
aggregator.update(123)
aggregator.take_checkpoint()
record = MetricRecord(aggregator, key_labels, metric)
record = MetricRecord(metric, key_labels, aggregator)
collector = CustomCollector("testprefix")
collector.add_metrics_data([record])

Expand Down Expand Up @@ -118,7 +118,7 @@ def test_invalid_metric(self):
)
labels = {"environment": "staging"}
key_labels = metrics.get_labels_as_key(labels)
record = MetricRecord(None, key_labels, metric)
record = MetricRecord(metric, key_labels, None)
collector = CustomCollector("testprefix")
collector.add_metrics_data([record])
collector.collect()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@
import types
from urllib.parse import urlparse

from requests import Timeout, URLRequired
from requests.exceptions import InvalidSchema, InvalidURL, MissingSchema
from requests.sessions import Session

from opentelemetry import context, propagators, trace
from opentelemetry.auto_instrumentation.instrumentor import BaseInstrumentor
from opentelemetry.ext.requests.version import __version__
from opentelemetry.trace import SpanKind, get_tracer
from opentelemetry.trace import SpanKind
from opentelemetry.trace.status import Status, StatusCanonicalCode


Expand Down Expand Up @@ -80,31 +82,49 @@ def instrumented_request(self, method, url, *args, **kwargs):
# https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md#http-client
try:
parsed_url = urlparse(url)
span_name = parsed_url.path
except ValueError as exc: # Invalid URL
path = "<Unparsable URL: {}>".format(exc)
else:
if parsed_url is None:
path = "<URL parses to None>"
path = parsed_url.path
span_name = "<Unparsable URL: {}>".format(exc)

with tracer.start_as_current_span(path, kind=SpanKind.CLIENT) as span:
exception = None

with tracer.start_as_current_span(
span_name, kind=SpanKind.CLIENT
) as span:
span.set_attribute("component", "http")
span.set_attribute("http.method", method.upper())
span.set_attribute("http.url", url)

headers = kwargs.setdefault("headers", {})
propagators.inject(type(headers).__setitem__, headers)
result = wrapped(self, method, url, *args, **kwargs) # *** PROCEED

span.set_attribute("http.status_code", result.status_code)
span.set_attribute("http.status_text", result.reason)
span.set_status(
Status(_http_status_to_canonical_code(result.status_code))
)
try:
result = wrapped(
self, method, url, *args, **kwargs
) # *** PROCEED
except Exception as exc: # pylint: disable=W0703
exception = exc
result = getattr(exc, "response", None)

if exception is not None:
span.set_status(
Status(_exception_to_canonical_code(exception))
)

if result is not None:
span.set_attribute("http.status_code", result.status_code)
span.set_attribute("http.status_text", result.reason)
span.set_status(
Status(_http_status_to_canonical_code(result.status_code))
)

if span_callback is not None:
span_callback(span, result)

return result
if exception is not None:
raise exception.with_traceback(exception.__traceback__)

return result

instrumented_request.opentelemetry_ext_requests_applied = True

Expand Down Expand Up @@ -157,6 +177,17 @@ def _http_status_to_canonical_code(code: int, allow_redirect: bool = True):
return StatusCanonicalCode.UNKNOWN


def _exception_to_canonical_code(exc: Exception) -> StatusCanonicalCode:
if isinstance(
exc,
(InvalidURL, InvalidSchema, MissingSchema, URLRequired, ValueError),
):
return StatusCanonicalCode.INVALID_ARGUMENT
if isinstance(exc, Timeout):
return StatusCanonicalCode.DEADLINE_EXCEEDED
return StatusCanonicalCode.UNKNOWN


class RequestsInstrumentor(BaseInstrumentor):
"""An instrumentor for requests
See `BaseInstrumentor`
Expand Down
Loading

0 comments on commit c8de5ed

Please sign in to comment.