Skip to content

Commit 1213006

Browse files
authored
intake: Handle transaction.dropped_spans_stats (#6200)
Adds a new `transaction.dropped_spans_stats` optional field to the API, which accepts an array of spans which were due to transaction_max_spans or exit_span_min_duration being exceeded. Additionally, the metrics aggregator for the `destination_service` metricset has been updated to process transaction where `transaction.dropped_spans_stats > 0`. ``` { "transaction": { "dropped_spans_stats": [ { "type": "external", "subtype": "http", "destination_service_resource": "example.com:443", "outcome": "failure", "duration": { "count": 28, "sum.us": 123456 } }, { "type": "db", "subtype": "mysql", "destination_service_resource": "mysql", "outcome": "success", "duration": { "count": 81, "sum.us": 9876543 } } ] } } ``` Signed-off-by: Marc Lopez Rubio <marc5.12@outlook.com>
1 parent 31c8e18 commit 1213006

23 files changed

Lines changed: 1429 additions & 11 deletions

beater/integration_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ func TestPublishIntegration(t *testing.T) {
137137
{payload: "metricsets.ndjson", name: "Metricsets"},
138138
{payload: "spans.ndjson", name: "Spans"},
139139
{payload: "transactions.ndjson", name: "Transactions"},
140+
{payload: "transactions-huge_traces.ndjson", name: "TransactionsHugeTraces"},
140141
{payload: "minimal.ndjson", name: "MinimalEvents"},
141142
} {
142143
tc := tc
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
{
2+
"events": [
3+
{
4+
"@timestamp": "2017-05-30T18:53:27.154Z",
5+
"agent": {
6+
"name": "elastic-node",
7+
"version": "3.14.0"
8+
},
9+
"client": {
10+
"ip": "12.53.12.1"
11+
},
12+
"cloud": {
13+
"account": {
14+
"id": "account_id",
15+
"name": "account_name"
16+
},
17+
"availability_zone": "cloud_availability_zone",
18+
"instance": {
19+
"id": "instance_id",
20+
"name": "instance_name"
21+
},
22+
"machine": {
23+
"type": "machine_type"
24+
},
25+
"project": {
26+
"id": "project_id",
27+
"name": "project_name"
28+
},
29+
"provider": "cloud_provider",
30+
"region": "cloud_region",
31+
"service": {
32+
"name": "lambda"
33+
}
34+
},
35+
"container": {
36+
"id": "container-id"
37+
},
38+
"ecs": {
39+
"version": "1.11.0"
40+
},
41+
"event": {
42+
"outcome": "success"
43+
},
44+
"host": {
45+
"architecture": "x64",
46+
"hostname": "node-name",
47+
"ip": "127.0.0.1",
48+
"name": "node-name",
49+
"os": {
50+
"platform": "darwin"
51+
}
52+
},
53+
"http": {
54+
"request": {
55+
"body.original": {
56+
"additional": {
57+
"bar": 123,
58+
"req": "additional information"
59+
},
60+
"str": "hello world"
61+
},
62+
"cookies": {
63+
"c1": "v1",
64+
"c2": "v2"
65+
},
66+
"env": {
67+
"GATEWAY_INTERFACE": "CGI/1.1",
68+
"SERVER_SOFTWARE": "nginx"
69+
},
70+
"headers": {
71+
"Array": [
72+
"foo",
73+
"bar",
74+
"baz"
75+
],
76+
"Content-Type": [
77+
"text/html"
78+
],
79+
"Cookie": [
80+
"c1=v1, c2=v2"
81+
],
82+
"Some-Other-Header": [
83+
"foo"
84+
],
85+
"User-Agent": [
86+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
87+
"Mozilla Chrome Edge"
88+
]
89+
},
90+
"method": "POST",
91+
"referrer": "http://localhost:8000/test/e2e/"
92+
},
93+
"response": {
94+
"decoded_body_size": 29.9,
95+
"encoded_body_size": 26.9,
96+
"finished": true,
97+
"headers": {
98+
"Content-Type": [
99+
"application/json"
100+
]
101+
},
102+
"headers_sent": true,
103+
"status_code": 200,
104+
"transfer_size": 25.8
105+
},
106+
"version": "1.1"
107+
},
108+
"kubernetes": {
109+
"namespace": "namespace1",
110+
"node": {
111+
"name": "node-name"
112+
},
113+
"pod": {
114+
"name": "pod-name",
115+
"uid": "pod-uid"
116+
}
117+
},
118+
"labels": {
119+
"organization_uuid": "9f0e9d64-c185-4d21-a6f4-4673ed561ec8",
120+
"tag1": "one",
121+
"tag2": 12,
122+
"tag3": 12.45,
123+
"tag4": false,
124+
"wrapped_reporter": true
125+
},
126+
"observer": {
127+
"ephemeral_id": "00000000-0000-0000-0000-000000000000",
128+
"id": "fbba762a-14dd-412c-b7e9-b79f903eb492",
129+
"type": "test-apm-server",
130+
"version": "1.2.3",
131+
"version_major": 1
132+
},
133+
"process": {
134+
"args": [
135+
"node",
136+
"server.js"
137+
],
138+
"pid": 1234,
139+
"ppid": 6789,
140+
"title": "node"
141+
},
142+
"processor": {
143+
"event": "transaction",
144+
"name": "transaction"
145+
},
146+
"service": {
147+
"environment": "staging",
148+
"framework": {
149+
"name": "Express",
150+
"version": "1.2.3"
151+
},
152+
"language": {
153+
"name": "ecmascript",
154+
"version": "8"
155+
},
156+
"name": "chatty-service",
157+
"node": {
158+
"name": "chatty-node"
159+
},
160+
"runtime": {
161+
"name": "node",
162+
"version": "7.0"
163+
},
164+
"version": "5.1.3"
165+
},
166+
"source": {
167+
"ip": "12.53.12.1"
168+
},
169+
"timestamp": {
170+
"us": 1496170407154000
171+
},
172+
"trace": {
173+
"id": "646df3b8b5279e982cc12a2f1ac004f3"
174+
},
175+
"transaction": {
176+
"custom": {
177+
"(": "not a valid regex and that is fine",
178+
"and_objects": {
179+
"foo": [
180+
"bar",
181+
"baz"
182+
]
183+
},
184+
"my_key": 1,
185+
"some_other_value": "foo bar"
186+
},
187+
"dropped_spans_stats": [
188+
{
189+
"destination_service_resource": "example.com:443",
190+
"duration": {
191+
"count": 2,
192+
"sum.us": 123456
193+
},
194+
"outcome": "failure",
195+
"subtype": "http",
196+
"type": "request"
197+
},
198+
{
199+
"destination_service_resource": "mysql",
200+
"duration": {
201+
"count": 1,
202+
"sum.us": 9876543
203+
},
204+
"outcome": "success",
205+
"subtype": "mysql",
206+
"type": "db"
207+
}
208+
],
209+
"duration": {
210+
"us": 32592
211+
},
212+
"id": "ddf109a4c4aa5f2b6e984548ca57774c",
213+
"name": "GET /api/types",
214+
"result": "success",
215+
"sampled": true,
216+
"span_count": {
217+
"dropped": 3,
218+
"started": 20
219+
},
220+
"type": "request"
221+
},
222+
"url": {
223+
"domain": "www.example.com",
224+
"fragment": "#hash",
225+
"full": "https://www.example.com/p/a/t/h?query=string#hash",
226+
"original": "/p/a/t/h?query=string#hash",
227+
"path": "/p/a/t/h",
228+
"port": 8080,
229+
"query": "?query=string",
230+
"scheme": "https"
231+
},
232+
"user": {
233+
"domain": "ldap://abc",
234+
"id": "99",
235+
"name": "foo"
236+
},
237+
"user_agent": {
238+
"original": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36, Mozilla Chrome Edge"
239+
}
240+
}
241+
]
242+
}

changelogs/head.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ https://github.com/elastic/apm-server/compare/7.15\...master[View commits]
2121
==== Intake API Changes
2222
- `faas`, `service.origin.*`, and `cloud.origin.*` added for supporting function as a service fields {pull}6161[6161]
2323
- `context.message.routing_key` was added to the intake API {pull}6177[6177]
24+
- `transaction.dropped_spans_stats` was added to the intake API {pull}6200[6200]
2425

2526
[float]
2627
==== Added
@@ -32,6 +33,7 @@ https://github.com/elastic/apm-server/compare/7.15\...master[View commits]
3233
- HTTP server errors (e.g. TLS handshake errors) are now logged {pull}6141[6141]
3334
- Span documents now duplicate extended HTTP fields, which were previously only under `span.http.*`, under `http.*` {pull}6147[6147]
3435
- We now record the direct network peer for incoming requests as `source.ip` and `source.port`; origin IP is recorded in `client.ip` {pull}6152[6152]
36+
- We now collect span destination metrics for transactions with too many spans (for example due to transaction_max_spans or exit_span_min_duration) when collected and sent by APM agents {pull}6200[6200]
3537

3638
[float]
3739
==== Deprecated

docs/spec/v2/transaction.json

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,90 @@
670670
}
671671
}
672672
},
673+
"dropped_spans_stats": {
674+
"description": "DroppedSpanStats holds information about spans that were dropped (for example due to transaction_max_spans or exit_span_min_duration).",
675+
"type": [
676+
"null",
677+
"array"
678+
],
679+
"items": {
680+
"type": "object",
681+
"properties": {
682+
"destination_service_resource": {
683+
"description": "DestinationServiceResource identifies the destination service resource being operated on. e.g. 'http://elastic.co:80', 'elasticsearch', 'rabbitmq/queue_name'.",
684+
"type": [
685+
"null",
686+
"string"
687+
],
688+
"maxLength": 1024
689+
},
690+
"duration": {
691+
"description": "Duration holds duration aggregations about the dropped span.",
692+
"type": [
693+
"null",
694+
"object"
695+
],
696+
"properties": {
697+
"count": {
698+
"description": "Count holds the number of times the dropped span happened.",
699+
"type": [
700+
"null",
701+
"integer"
702+
],
703+
"minimum": 1
704+
},
705+
"sum": {
706+
"description": "Sum holds dimensions about the dropped span's duration.",
707+
"type": [
708+
"null",
709+
"object"
710+
],
711+
"properties": {
712+
"us": {
713+
"description": "Us represents the summation of the span duration.",
714+
"type": [
715+
"null",
716+
"integer"
717+
],
718+
"minimum": 0
719+
}
720+
}
721+
}
722+
}
723+
},
724+
"outcome": {
725+
"description": "Outcome of the span: success, failure, or unknown. Outcome may be one of a limited set of permitted values describing the success or failure of the span. It can be used for calculating error rates for outgoing requests.",
726+
"type": [
727+
"null",
728+
"string"
729+
],
730+
"enum": [
731+
"success",
732+
"failure",
733+
"unknown",
734+
null
735+
]
736+
},
737+
"subtype": {
738+
"description": "Subtype is a further sub-division of the type (e.g. postgresql, elasticsearch)",
739+
"type": [
740+
"null",
741+
"string"
742+
],
743+
"maxLength": 1024
744+
},
745+
"type": {
746+
"description": "Type holds the dropped span's type, and can have specific keywords within the service's domain (eg: 'request', 'backgroundjob', etc)",
747+
"type": [
748+
"null",
749+
"string"
750+
],
751+
"maxLength": 1024
752+
}
753+
}
754+
},
755+
"minItems": 0
756+
},
673757
"duration": {
674758
"description": "Duration how long the transaction took to complete, in milliseconds with 3 decimal points.",
675759
"type": "number",

model/modeldecoder/rumv3/transaction_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ func TestDecodeMapToTransactionModel(t *testing.T) {
197197
exceptions := func(key string) bool {
198198
for _, s := range []string{
199199
// values not set for RUM v3
200-
"RepresentativeCount", "Message",
200+
"RepresentativeCount", "Message", "DroppedSpansStats",
201201
// Not set for transaction events:
202202
"AggregatedDuration",
203203
"AggregatedDuration.Count",

0 commit comments

Comments
 (0)