Skip to content

Commit ab6401c

Browse files
authored
Merge pull request #268 from appsignal/collector-mode-names
Send request sample data in collector mode
2 parents b077f61 + bc559b4 commit ab6401c

4 files changed

Lines changed: 62 additions & 12 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
bump: patch
3+
type: fix
4+
---
5+
6+
Emit request parameters and headers using the attribute names the collector
7+
recognizes when in collector mode. `set_params` now emits
8+
`appsignal.request.payload` instead of `appsignal.request.parameters`, and
9+
`set_header` uses the `http.request.header` prefix instead of
10+
`appsignal.request.headers`. The collector and server do not recognize the
11+
previous names, so this sample data was previously dropped in collector mode.

src/appsignal/opentelemetry.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,33 +58,29 @@ def add_celery_instrumentation(_config: Config) -> None:
5858

5959

6060
def add_django_instrumentation(_config: Config) -> None:
61-
import json
62-
6361
from django.http.request import HttpRequest
6462
from django.http.response import HttpResponse
6563
from opentelemetry.instrumentation.django import DjangoInstrumentor
6664

65+
from .tracing import set_params
66+
6767
def response_hook(span: Span, request: HttpRequest, response: HttpResponse) -> None:
68-
span.set_attribute(
69-
"appsignal.request.parameters",
70-
json.dumps({"GET": request.GET, "POST": request.POST}),
71-
)
68+
set_params({"GET": request.GET, "POST": request.POST}, span)
7269

7370
DjangoInstrumentor().instrument(response_hook=response_hook)
7471

7572

7673
def add_flask_instrumentation(_config: Config) -> None:
77-
import json
7874
from urllib.parse import parse_qs
7975

8076
from opentelemetry.instrumentation.flask import FlaskInstrumentor
8177

78+
from .tracing import set_params
79+
8280
def request_hook(span: Span, environ: dict[str, str]) -> None:
8381
if span and span.is_recording():
8482
query_params = parse_qs(environ.get("QUERY_STRING", ""))
85-
span.set_attribute(
86-
"appsignal.request.parameters", json.dumps({"args": query_params})
87-
)
83+
set_params({"args": query_params}, span)
8884

8985
FlaskInstrumentor().instrument(request_hook=request_hook)
9086

src/appsignal/tracing.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,14 @@ def _use_collector() -> bool:
6363

6464

6565
def set_params(params: Any, span: Span | None = None) -> None:
66-
_set_serialised_attribute("appsignal.request.parameters", params, span)
66+
# The collector and server recognize `appsignal.request.payload` for request
67+
# body / merged parameters; the agent recognizes `appsignal.request.parameters`.
68+
attribute = (
69+
"appsignal.request.payload"
70+
if _use_collector()
71+
else "appsignal.request.parameters"
72+
)
73+
_set_serialised_attribute(attribute, params, span)
6774

6875

6976
def set_session_data(session_data: Any, span: Span | None = None) -> None:
@@ -79,7 +86,11 @@ def set_tag(tag: str, value: Any, span: Span | None = None) -> None:
7986

8087

8188
def set_header(header: str, value: Any, span: Span | None = None) -> None:
82-
_set_prefixed_attribute("appsignal.request.headers", header, value, span)
89+
# The collector and server read request headers from the OpenTelemetry
90+
# semantic-convention prefix `http.request.header`; the agent reads them
91+
# from `appsignal.request.headers`.
92+
prefix = "http.request.header" if _use_collector() else "appsignal.request.headers"
93+
_set_prefixed_attribute(prefix, header, value, span)
8394

8495

8596
def set_name(name: str, span: Span | None = None) -> None:

tests/test_tracing.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,38 @@ def test_set_name_collector_mode(spans):
9898
assert "appsignal.name" not in dict(span.attributes)
9999

100100

101+
def test_set_params_collector_mode(spans):
102+
Client(
103+
active=True,
104+
name="MyApp",
105+
push_api_key="0000-0000-0000-0000",
106+
collector_endpoint="https://custom-endpoint.appsignal.com",
107+
)
108+
109+
with tracer.start_as_current_span("span"):
110+
set_params({"id": 123})
111+
112+
attributes = dict(spans()[0].attributes)
113+
assert attributes["appsignal.request.payload"] == '{"id": 123}'
114+
assert "appsignal.request.parameters" not in attributes
115+
116+
117+
def test_set_header_collector_mode(spans):
118+
Client(
119+
active=True,
120+
name="MyApp",
121+
push_api_key="0000-0000-0000-0000",
122+
collector_endpoint="https://custom-endpoint.appsignal.com",
123+
)
124+
125+
with tracer.start_as_current_span("span"):
126+
set_header("content-type", "application/json")
127+
128+
attributes = dict(spans()[0].attributes)
129+
assert attributes["http.request.header.content-type"] == "application/json"
130+
assert "appsignal.request.headers.content-type" not in attributes
131+
132+
101133
def test_set_sql_body_collector_mode(spans):
102134
Client(
103135
active=True,

0 commit comments

Comments
 (0)