@@ -96,18 +96,30 @@ const (
96
96
DefaultSite = "datadoghq.com"
97
97
// DefaultEnhancedMetrics enables enhanced metrics by default.
98
98
DefaultEnhancedMetrics = true
99
+
100
+ // serverlessAppSecEnabledEnvVar is the environment variable used to activate Serverless ASM through the use of an
101
+ // AWS Lambda runtime API proxy.
102
+ serverlessAppSecEnabledEnvVar = "DD_SERVERLESS_APPSEC_ENABLED"
103
+ // awsLambdaRuntimeApiEnvVar is the environment variable used to redirect AWS Lambda runtime API calls to the proxy.
104
+ awsLambdaRuntimeApiEnvVar = "AWS_LAMBDA_RUNTIME_API"
105
+ // datadogAgentUrl is the URL of the agent and proxy started by the Datadog lambda extension.
106
+ datadogAgentUrl = "127.0.0.1:9000"
107
+ // ddExtensionFilePath is the path on disk of the datadog lambda extension.
108
+ ddExtensionFilePath = "/opt/extensions/datadog-agent"
99
109
)
100
110
101
111
// WrapLambdaHandlerInterface is used to instrument your lambda functions.
102
112
// It returns a modified handler that can be passed directly to the lambda.StartHandler function from aws-lambda-go.
103
113
func WrapLambdaHandlerInterface (handler lambda.Handler , cfg * Config ) lambda.Handler {
114
+ setupAppSec ()
104
115
listeners := initializeListeners (cfg )
105
116
return wrapper .WrapHandlerInterfaceWithListeners (handler , listeners ... )
106
117
}
107
118
108
119
// WrapFunction is used to instrument your lambda functions.
109
120
// It returns a modified handler that can be passed directly to the lambda.Start function from aws-lambda-go.
110
121
func WrapFunction (handler interface {}, cfg * Config ) interface {} {
122
+ setupAppSec ()
111
123
listeners := initializeListeners (cfg )
112
124
return wrapper .WrapHandlerWithListeners (handler , listeners ... )
113
125
}
@@ -289,3 +301,39 @@ func (cfg *Config) toMetricsConfig(isExtensionRunning bool) metrics.Config {
289
301
290
302
return mc
291
303
}
304
+
305
+ // setupAppSec checks if DD_SERVERLESS_APPSEC_ENABLED is set (to true) and when that
306
+ // is the case, redirects `AWS_LAMBDA_RUNTIME_API` to the agent extension, and turns
307
+ // on universal instrumentation unless it was already configured by the customer, so
308
+ // that the HTTP context (invocation details span tags) is available on AppSec traces.
309
+ func setupAppSec () {
310
+ enabled := false
311
+ if env := os .Getenv (serverlessAppSecEnabledEnvVar ); env != "" {
312
+ if on , err := strconv .ParseBool (env ); err == nil {
313
+ enabled = on
314
+ }
315
+ }
316
+
317
+ if ! enabled {
318
+ return
319
+ }
320
+
321
+ if _ , err := os .Stat (ddExtensionFilePath ); os .IsNotExist (err ) {
322
+ logger .Debug (fmt .Sprintf ("%s is enabled, but the Datadog extension was not found at %s" , serverlessAppSecEnabledEnvVar , ddExtensionFilePath ))
323
+ return
324
+ }
325
+
326
+ if err := os .Setenv (awsLambdaRuntimeApiEnvVar , datadogAgentUrl ); err != nil {
327
+ logger .Debug (fmt .Sprintf ("failed to set %s=%s: %v" , awsLambdaRuntimeApiEnvVar , datadogAgentUrl , err ))
328
+ } else {
329
+ logger .Debug (fmt .Sprintf ("successfully set %s=%s" , awsLambdaRuntimeApiEnvVar , datadogAgentUrl ))
330
+ }
331
+
332
+ if val := os .Getenv (UniversalInstrumentation ); val == "" {
333
+ if err := os .Setenv (UniversalInstrumentation , "1" ); err != nil {
334
+ logger .Debug (fmt .Sprintf ("failed to set %s=%d: %v" , UniversalInstrumentation , 1 , err ))
335
+ } else {
336
+ logger .Debug (fmt .Sprintf ("successfully set %s=%d" , UniversalInstrumentation , 1 ))
337
+ }
338
+ }
339
+ }
0 commit comments