Skip to content

Commit f146c38

Browse files
authored
Merge 95f979a into 1ca51d5
2 parents 1ca51d5 + 95f979a commit f146c38

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed

ddlambda.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,30 @@ const (
9696
DefaultSite = "datadoghq.com"
9797
// DefaultEnhancedMetrics enables enhanced metrics by default.
9898
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"
99109
)
100110

101111
// WrapLambdaHandlerInterface is used to instrument your lambda functions.
102112
// It returns a modified handler that can be passed directly to the lambda.StartHandler function from aws-lambda-go.
103113
func WrapLambdaHandlerInterface(handler lambda.Handler, cfg *Config) lambda.Handler {
114+
setupAppSec()
104115
listeners := initializeListeners(cfg)
105116
return wrapper.WrapHandlerInterfaceWithListeners(handler, listeners...)
106117
}
107118

108119
// WrapFunction is used to instrument your lambda functions.
109120
// It returns a modified handler that can be passed directly to the lambda.Start function from aws-lambda-go.
110121
func WrapFunction(handler interface{}, cfg *Config) interface{} {
122+
setupAppSec()
111123
listeners := initializeListeners(cfg)
112124
return wrapper.WrapHandlerWithListeners(handler, listeners...)
113125
}
@@ -289,3 +301,39 @@ func (cfg *Config) toMetricsConfig(isExtensionRunning bool) metrics.Config {
289301

290302
return mc
291303
}
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

Comments
 (0)