diff --git a/instrumentation/opentelemetry-instrumentation-requests/CHANGELOG.md b/instrumentation/opentelemetry-instrumentation-requests/CHANGELOG.md index 00d730f4f4..164fd0823b 100644 --- a/instrumentation/opentelemetry-instrumentation-requests/CHANGELOG.md +++ b/instrumentation/opentelemetry-instrumentation-requests/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +- Add span name callback + ([#158](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/158)) + ## Version 0.15b0 Released 2020-11-02 diff --git a/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py b/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py index b4738647db..02128f9449 100644 --- a/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-requests/src/opentelemetry/instrumentation/requests/__init__.py @@ -64,7 +64,7 @@ # pylint: disable=unused-argument # pylint: disable=R0915 -def _instrument(tracer_provider=None, span_callback=None): +def _instrument(tracer_provider=None, span_callback=None, name_callback=None): """Enables tracing of all requests calls that go through :code:`requests.session.Session.request` (this includes :code:`requests.get`, etc.).""" @@ -124,7 +124,11 @@ def _instrumented_requests_call( # See # https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/trace/semantic_conventions/http.md#http-client method = method.upper() - span_name = "HTTP {}".format(method) + span_name = "" + if name_callback is not None: + span_name = name_callback() + if not span_name or not isinstance(span_name, str): + span_name = get_default_span_name(method) recorder = RequestsInstrumentor().metric_recorder @@ -217,6 +221,11 @@ def _uninstrument_from(instr_root, restore_as_bound_func=False): setattr(instr_root, instr_func_name, original) +def get_default_span_name(method): + """Default implementation for name_callback, returns HTTP {method_name}.""" + return "HTTP {}".format(method).strip() + + class RequestsInstrumentor(BaseInstrumentor, MetricMixin): """An instrumentor for requests See `BaseInstrumentor` @@ -229,10 +238,14 @@ def _instrument(self, **kwargs): **kwargs: Optional arguments ``tracer_provider``: a TracerProvider, defaults to global ``span_callback``: An optional callback invoked before returning the http response. Invoked with Span and requests.Response + ``name_callback``: Callback which calculates a generic span name for an + outgoing HTTP request based on the method and url. + Optional: Defaults to get_default_span_name. """ _instrument( tracer_provider=kwargs.get("tracer_provider"), span_callback=kwargs.get("span_callback"), + name_callback=kwargs.get("name_callback"), ) self.init_metrics( __name__, __version__, diff --git a/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py b/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py index f5209108e3..2f84f983d1 100644 --- a/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py +++ b/instrumentation/opentelemetry-instrumentation-requests/tests/test_requests_integration.py @@ -107,6 +107,30 @@ def test_basic(self): self.assertEqual(view_data.aggregator.current.count, 1) self.assertGreaterEqual(view_data.aggregator.current.sum, 0) + def test_name_callback(self): + def name_callback(): + return "test_name" + + RequestsInstrumentor().uninstrument() + RequestsInstrumentor().instrument(name_callback=name_callback) + result = self.perform_request(self.URL) + self.assertEqual(result.text, "Hello!") + span = self.assert_span() + + self.assertEqual(span.name, "test_name") + + def test_name_callback_default(self): + def name_callback(): + return 123 + + RequestsInstrumentor().uninstrument() + RequestsInstrumentor().instrument(name_callback=name_callback) + result = self.perform_request(self.URL) + self.assertEqual(result.text, "Hello!") + span = self.assert_span() + + self.assertEqual(span.name, "HTTP GET") + def test_not_foundbasic(self): url_404 = "http://httpbin.org/status/404" httpretty.register_uri(