Skip to content

Commit

Permalink
Merge branch 'main' into emptyroute
Browse files Browse the repository at this point in the history
  • Loading branch information
muncus committed Jun 20, 2023
2 parents 1b53e15 + ffc9334 commit db85f97
Show file tree
Hide file tree
Showing 21 changed files with 298 additions and 80 deletions.
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- `opentelemetry-instrumentation-django` Fix empty span name when using
`path("", ...)` ([#1788](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1788)
- Update falcon instrumentation to follow semantic conventions
([#1824](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1824))

### Added

- Make Flask request span attributes available for `start_span`.
([#1784](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1784))
- Fix falcon instrumentation's usage of Span Status to only set the description if the status code is ERROR.
([#1840](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1840))
- Instrument all httpx versions >= 0.18. ([#1748](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1748))
- Fix `Invalid type NoneType for attribute X (opentelemetry-instrumentation-aws-lambda)` error when some attributes do not exist
([#1780](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1780))
- Add metric instrumentation for celery
([#1679](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1679))
- `opentelemetry-instrumentation-asgi` Add `http.server.response.size` metric
([#1789](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1789))

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

Expand All @@ -22,6 +35,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#1706](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1706))
- `opentelemetry-instrumentation-pymemcache` Update instrumentation to support pymemcache >4
([#1764](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1764))
- `opentelemetry-instrumentation-confluent-kafka` Add support for higher versions of confluent_kafka
([#1815](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/1815))

### Added

Expand Down
2 changes: 1 addition & 1 deletion dev-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ mypy-protobuf>=1.23
protobuf~=3.13
markupsafe>=2.0.1
codespell==2.1.0
requests==2.28.1
requests==2.31.0
ruamel.yaml==0.17.21
2 changes: 1 addition & 1 deletion docs-requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ boto~=2.0
botocore~=1.0
boto3~=1.0
celery>=4.0
confluent-kafka>= 1.8.2,< 2.0.0
confluent-kafka>= 1.8.2,<= 2.2.0
elasticsearch>=2.0,<9.0
flask~=2.0
falcon~=2.0
Expand Down
2 changes: 1 addition & 1 deletion instrumentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
| [opentelemetry-instrumentation-boto3sqs](./opentelemetry-instrumentation-boto3sqs) | boto3 ~= 1.0 | No
| [opentelemetry-instrumentation-botocore](./opentelemetry-instrumentation-botocore) | botocore ~= 1.0 | No
| [opentelemetry-instrumentation-celery](./opentelemetry-instrumentation-celery) | celery >= 4.0, < 6.0 | No
| [opentelemetry-instrumentation-confluent-kafka](./opentelemetry-instrumentation-confluent-kafka) | confluent-kafka >= 1.8.2, < 2.0.0 | No
| [opentelemetry-instrumentation-confluent-kafka](./opentelemetry-instrumentation-confluent-kafka) | confluent-kafka >= 1.8.2, <= 2.2.0 | No
| [opentelemetry-instrumentation-dbapi](./opentelemetry-instrumentation-dbapi) | dbapi | No
| [opentelemetry-instrumentation-django](./opentelemetry-instrumentation-django) | django >= 1.10 | Yes
| [opentelemetry-instrumentation-elasticsearch](./opentelemetry-instrumentation-elasticsearch) | elasticsearch >= 2.0 | No
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,11 @@ def __init__(
unit="ms",
description="measures the duration of the inbound HTTP request",
)
self.server_response_size_histogram = self.meter.create_histogram(
name=MetricInstruments.HTTP_SERVER_RESPONSE_SIZE,
unit="By",
description="measures the size of HTTP response messages (compressed).",
)
self.active_requests_counter = self.meter.create_up_down_counter(
name=MetricInstruments.HTTP_SERVER_ACTIVE_REQUESTS,
unit="requests",
Expand All @@ -518,6 +523,7 @@ def __init__(
self.server_request_hook = server_request_hook
self.client_request_hook = client_request_hook
self.client_response_hook = client_response_hook
self.content_length_header = None

async def __call__(self, scope, receive, send):
"""The ASGI application
Expand Down Expand Up @@ -593,6 +599,10 @@ async def __call__(self, scope, receive, send):
self.active_requests_counter.add(
-1, active_requests_count_attrs
)
if self.content_length_header:
self.server_response_size_histogram.record(
self.content_length_header, duration_attrs
)
if token:
context.detach(token)

Expand Down Expand Up @@ -660,6 +670,13 @@ async def otel_send(message):
setter=asgi_setter,
)

content_length = asgi_getter.get(message, "content-length")
if content_length:
try:
self.content_length_header = int(content_length[0])
except ValueError:
pass

await send(message)

return otel_send
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@
_expected_metric_names = [
"http.server.active_requests",
"http.server.duration",
"http.server.response.size",
]
_recommended_attrs = {
"http.server.active_requests": _active_requests_count_attrs,
"http.server.duration": _duration_attrs,
"http.server.response.size": _duration_attrs,
}


Expand All @@ -61,7 +63,10 @@ async def http_app(scope, receive, send):
{
"type": "http.response.start",
"status": 200,
"headers": [[b"Content-Type", b"text/plain"]],
"headers": [
[b"Content-Type", b"text/plain"],
[b"content-length", b"1024"],
],
}
)
await send({"type": "http.response.body", "body": b"*"})
Expand Down Expand Up @@ -103,7 +108,10 @@ async def error_asgi(scope, receive, send):
{
"type": "http.response.start",
"status": 200,
"headers": [[b"Content-Type", b"text/plain"]],
"headers": [
[b"Content-Type", b"text/plain"],
[b"content-length", b"1024"],
],
}
)
await send({"type": "http.response.body", "body": b"*"})
Expand All @@ -126,7 +134,8 @@ def validate_outputs(self, outputs, error=None, modifiers=None):
# Check http response start
self.assertEqual(response_start["status"], 200)
self.assertEqual(
response_start["headers"], [[b"Content-Type", b"text/plain"]]
response_start["headers"],
[[b"Content-Type", b"text/plain"], [b"content-length", b"1024"]],
)

exc_info = self.scope.get("hack_exc_info")
Expand Down Expand Up @@ -352,6 +361,7 @@ def test_traceresponse_header(self):
response_start["headers"],
[
[b"Content-Type", b"text/plain"],
[b"content-length", b"1024"],
[b"traceresponse", f"{traceresponse}".encode()],
[b"access-control-expose-headers", b"traceresponse"],
],
Expand Down Expand Up @@ -565,6 +575,7 @@ def test_basic_metric_success(self):
"http.flavor": "1.0",
}
metrics_list = self.memory_metrics_reader.get_metrics_data()
# pylint: disable=too-many-nested-blocks
for resource_metric in metrics_list.resource_metrics:
for scope_metrics in resource_metric.scope_metrics:
for metric in scope_metrics.metrics:
Expand All @@ -575,9 +586,12 @@ def test_basic_metric_success(self):
dict(point.attributes),
)
self.assertEqual(point.count, 1)
self.assertAlmostEqual(
duration, point.sum, delta=5
)
if metric.name == "http.server.duration":
self.assertAlmostEqual(
duration, point.sum, delta=5
)
elif metric.name == "http.server.response.size":
self.assertEqual(1024, point.sum)
elif isinstance(point, NumberDataPoint):
self.assertDictEqual(
expected_requests_count_attributes,
Expand All @@ -602,13 +616,12 @@ async def target_asgi(scope, receive, send):
app = otel_asgi.OpenTelemetryMiddleware(target_asgi)
self.seed_app(app)
self.send_default_request()

metrics_list = self.memory_metrics_reader.get_metrics_data()
assertions = 0
for resource_metric in metrics_list.resource_metrics:
for scope_metrics in resource_metric.scope_metrics:
for metric in scope_metrics.metrics:
if metric.name != "http.server.duration":
if metric.name == "http.server.active_requests":
continue
for point in metric.data.data_points:
if isinstance(point, HistogramDataPoint):
Expand All @@ -617,7 +630,7 @@ async def target_asgi(scope, receive, send):
expected_target,
)
assertions += 1
self.assertEqual(assertions, 1)
self.assertEqual(assertions, 2)

def test_no_metric_for_websockets(self):
self.scope = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,30 +201,35 @@ def _set_api_gateway_v1_proxy_attributes(
span.set_attribute(
SpanAttributes.HTTP_METHOD, lambda_event.get("httpMethod")
)
span.set_attribute(SpanAttributes.HTTP_ROUTE, lambda_event.get("resource"))

if lambda_event.get("headers"):
span.set_attribute(
SpanAttributes.HTTP_USER_AGENT,
lambda_event["headers"].get("User-Agent"),
)
span.set_attribute(
SpanAttributes.HTTP_SCHEME,
lambda_event["headers"].get("X-Forwarded-Proto"),
)
span.set_attribute(
SpanAttributes.NET_HOST_NAME, lambda_event["headers"].get("Host")
)
if "User-Agent" in lambda_event["headers"]:
span.set_attribute(
SpanAttributes.HTTP_USER_AGENT,
lambda_event["headers"]["User-Agent"],
)
if "X-Forwarded-Proto" in lambda_event["headers"]:
span.set_attribute(
SpanAttributes.HTTP_SCHEME,
lambda_event["headers"]["X-Forwarded-Proto"],
)
if "Host" in lambda_event["headers"]:
span.set_attribute(
SpanAttributes.NET_HOST_NAME,
lambda_event["headers"]["Host"],
)
if "resource" in lambda_event:
span.set_attribute(SpanAttributes.HTTP_ROUTE, lambda_event["resource"])

if lambda_event.get("queryStringParameters"):
span.set_attribute(
SpanAttributes.HTTP_TARGET,
f"{lambda_event.get('resource')}?{urlencode(lambda_event.get('queryStringParameters'))}",
)
else:
span.set_attribute(
SpanAttributes.HTTP_TARGET, lambda_event.get("resource")
)
if lambda_event.get("queryStringParameters"):
span.set_attribute(
SpanAttributes.HTTP_TARGET,
f"{lambda_event['resource']}?{urlencode(lambda_event['queryStringParameters'])}",
)
else:
span.set_attribute(
SpanAttributes.HTTP_TARGET, lambda_event["resource"]
)

return span

Expand All @@ -237,35 +242,38 @@ def _set_api_gateway_v2_proxy_attributes(
More info:
https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html
"""
span.set_attribute(
SpanAttributes.NET_HOST_NAME,
lambda_event["requestContext"].get("domainName"),
)

if lambda_event["requestContext"].get("http"):
if "domainName" in lambda_event["requestContext"]:
span.set_attribute(
SpanAttributes.HTTP_METHOD,
lambda_event["requestContext"]["http"].get("method"),
)
span.set_attribute(
SpanAttributes.HTTP_USER_AGENT,
lambda_event["requestContext"]["http"].get("userAgent"),
)
span.set_attribute(
SpanAttributes.HTTP_ROUTE,
lambda_event["requestContext"]["http"].get("path"),
SpanAttributes.NET_HOST_NAME,
lambda_event["requestContext"]["domainName"],
)

if lambda_event.get("rawQueryString"):
if lambda_event["requestContext"].get("http"):
if "method" in lambda_event["requestContext"]["http"]:
span.set_attribute(
SpanAttributes.HTTP_TARGET,
f"{lambda_event['requestContext']['http'].get('path')}?{lambda_event.get('rawQueryString')}",
SpanAttributes.HTTP_METHOD,
lambda_event["requestContext"]["http"]["method"],
)
else:
if "userAgent" in lambda_event["requestContext"]["http"]:
span.set_attribute(
SpanAttributes.HTTP_TARGET,
lambda_event["requestContext"]["http"].get("path"),
SpanAttributes.HTTP_USER_AGENT,
lambda_event["requestContext"]["http"]["userAgent"],
)
if "path" in lambda_event["requestContext"]["http"]:
span.set_attribute(
SpanAttributes.HTTP_ROUTE,
lambda_event["requestContext"]["http"]["path"],
)
if lambda_event.get("rawQueryString"):
span.set_attribute(
SpanAttributes.HTTP_TARGET,
f"{lambda_event['requestContext']['http']['path']}?{lambda_event['rawQueryString']}",
)
else:
span.set_attribute(
SpanAttributes.HTTP_TARGET,
lambda_event["requestContext"]["http"]["path"],
)

return span

Expand Down
Loading

0 comments on commit db85f97

Please sign in to comment.