@@ -18,6 +18,13 @@ const serverlessSdk = require('./lib/sdk');
18
18
const objHasOwnProperty = Object . prototype . hasOwnProperty ;
19
19
const unresolvedPromise = new Promise ( ( ) => { } ) ;
20
20
21
+ const coreTraceSpanNames = new Set ( [
22
+ 'aws.lambda' ,
23
+ 'aws.lambda.initialization' ,
24
+ 'aws.lambda.invocation' ,
25
+ ] ) ;
26
+ const alertEventNames = new Set ( [ 'telemetry.error.generated.v1' , 'telemetry.warning.generated.v1' ] ) ;
27
+
21
28
const capturedEvents = [ ] ;
22
29
serverlessSdk . _eventEmitter . on ( 'captured-event' , ( capturedEvent ) =>
23
30
capturedEvents . push ( capturedEvent )
@@ -91,25 +98,38 @@ const reportResponse = async (response, context, endTime) => {
91
98
await sendTelemetry ( 'request-response' , payloadBuffer ) ;
92
99
} ;
93
100
94
- const reportTrace = ( ) => {
101
+ const reportTrace = ( { isErrorOutcome } ) => {
102
+ // Sample out 80% of traces in production mode if no warning or error event was reported
103
+ const isSampledOut =
104
+ ( ! isErrorOutcome &&
105
+ ! serverlessSdk . _isDebugMode &&
106
+ ! serverlessSdk . _isDevMode &&
107
+ ! capturedEvents . some ( ( { name } ) => alertEventNames . has ( name ) ) &&
108
+ Math . random ( ) > 0.2 ) ||
109
+ undefined ;
95
110
const payload = ( serverlessSdk . _lastTrace = {
111
+ isSampledOut,
96
112
slsTags : {
97
113
orgId : serverlessSdk . orgId ,
98
114
service : process . env . AWS_LAMBDA_FUNCTION_NAME ,
99
115
sdk : { name : pkgJson . name , version : pkgJson . version } ,
100
116
} ,
101
- spans : Array . from ( awsLambdaSpan . spans ) . map ( ( span ) => {
117
+ spans : Array . from ( awsLambdaSpan . spans , ( span ) => {
118
+ if ( isSampledOut && ! coreTraceSpanNames . has ( span . name ) ) return null ;
102
119
const spanPayload = span . toProtobufObject ( ) ;
103
120
delete spanPayload . input ;
104
121
delete spanPayload . output ;
105
122
return spanPayload ;
106
- } ) ,
107
- events : capturedEvents
108
- . filter ( filterCapturedEvent )
109
- . map ( ( capturedEvent ) => capturedEvent . toProtobufObject ( ) ) ,
110
- customTags : objHasOwnProperty . call ( serverlessSdk , '_customTags' )
111
- ? JSON . stringify ( serverlessSdk . _customTags )
112
- : undefined ,
123
+ } ) . filter ( Boolean ) ,
124
+ events : isSampledOut
125
+ ? [ ]
126
+ : capturedEvents
127
+ . filter ( filterCapturedEvent )
128
+ . map ( ( capturedEvent ) => capturedEvent . toProtobufObject ( ) ) ,
129
+ customTags :
130
+ ! isSampledOut && objHasOwnProperty . call ( serverlessSdk , '_customTags' )
131
+ ? JSON . stringify ( serverlessSdk . _customTags )
132
+ : undefined ,
113
133
} ) ;
114
134
const payloadBuffer = ( serverlessSdk . _lastTraceBuffer =
115
135
traceProto . TracePayload . encode ( payload ) . finish ( ) ) ;
@@ -172,7 +192,7 @@ const closeTrace = async (outcome, outcomeResult) => {
172
192
awsLambdaSpan . close ( { endTime } ) ;
173
193
// Root span comes with "aws.lambda.*" tags, which require unconditionally requestId
174
194
// which we don't have if handler crashed at initialization
175
- if ( invocationContextAccessor . value ) reportTrace ( ) ;
195
+ if ( invocationContextAccessor . value ) reportTrace ( { isErrorOutcome } ) ;
176
196
flushSpans ( ) ;
177
197
clearRootSpan ( ) ;
178
198
0 commit comments