Skip to content

Commit

Permalink
Update serverless-init Cloud Run service to support cloud run functio…
Browse files Browse the repository at this point in the history
…ns via Cloud Functions UI (#29404)
  • Loading branch information
nina9753 authored Sep 24, 2024
1 parent 6477765 commit 3ca96b6
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 3 deletions.
47 changes: 44 additions & 3 deletions cmd/serverless-init/cloudservice/cloudrun.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,36 @@
package cloudservice

import (
"fmt"
"github.com/DataDog/datadog-agent/pkg/util/log"
"os"

"github.com/DataDog/datadog-agent/cmd/serverless-init/cloudservice/helper"
)

const (
revisionNameEnvVar = "K_REVISION"
//nolint:revive // TODO(SERV) Fix revive linter
ServiceNameEnvVar = "K_SERVICE"
revisionNameEnvVar = "K_REVISION"
ServiceNameEnvVar = "K_SERVICE" // ServiceNameEnvVar is also used in the trace package
configurationNameEnvVar = "K_CONFIGURATION"
functionTypeEnvVar = "FUNCTION_SIGNATURE_TYPE"
functionTargetEnvVar = "FUNCTION_TARGET" // exists as a cloudrunfunction env var for all runtimes except Go
)

var metadataHelperFunc = helper.GetMetaData

// CloudRun has helper functions for getting Google Cloud Run data
type CloudRun struct{}
type CloudRun struct {
cloudRunFunctionMode bool
}

// GetTags returns a map of gcp-related tags.
func (c *CloudRun) GetTags() map[string]string {
tags := metadataHelperFunc(helper.GetDefaultConfig()).TagMap()

revisionName := os.Getenv(revisionNameEnvVar)
serviceName := os.Getenv(ServiceNameEnvVar)
configName := os.Getenv(configurationNameEnvVar)

if revisionName != "" {
tags["revision_name"] = revisionName
Expand All @@ -37,21 +45,48 @@ func (c *CloudRun) GetTags() map[string]string {
tags["service_name"] = serviceName
}

if configName != "" {
tags["configuration_name"] = configName
}

if c.cloudRunFunctionMode {
tags = getFunctionTags(tags)
}
tags["origin"] = c.GetOrigin()
tags["_dd.origin"] = c.GetOrigin()

return tags
}

func getFunctionTags(tags map[string]string) map[string]string {
functionTarget := os.Getenv(functionTargetEnvVar)
functionSignatureType := os.Getenv(functionTypeEnvVar)

if functionTarget != "" {
tags["function_target"] = functionTarget
}

if functionSignatureType != "" {
tags["function_signature_type"] = functionSignatureType
}
return tags
}

// GetOrigin returns the `origin` attribute type for the given
// cloud service.
func (c *CloudRun) GetOrigin() string {
if c.cloudRunFunctionMode {
return "cloudfunctions"
}
return "cloudrun"
}

// GetPrefix returns the prefix that we're prefixing all
// metrics with.
func (c *CloudRun) GetPrefix() string {
if c.cloudRunFunctionMode {
return "gcp.cloudfunctions"
}
return "gcp.run"
}

Expand All @@ -64,3 +99,9 @@ func isCloudRunService() bool {
_, exists := os.LookupEnv(ServiceNameEnvVar)
return exists
}

func isCloudRunFunction() bool {
_, cloudRunFunctionMode := os.LookupEnv(functionTargetEnvVar)
log.Debug(fmt.Sprintf("cloud function mode SET TO: %t", cloudRunFunctionMode))
return cloudRunFunctionMode
}
42 changes: 42 additions & 0 deletions cmd/serverless-init/cloudservice/cloudrun_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,45 @@ func TestGetCloudRunTagsWithEnvironmentVariables(t *testing.T) {
"_dd.origin": "cloudrun",
}, tags)
}

func TestGetCloudRunFunctionTagsWithEnvironmentVariables(t *testing.T) {
service := &CloudRun{cloudRunFunctionMode: true}

metadataHelperFunc = func(*helper.GCPConfig) *helper.GCPMetadata {
return &helper.GCPMetadata{
ContainerID: &helper.Info{
TagName: "container_id",
Value: "test_container",
},
Region: &helper.Info{
TagName: "region",
Value: "test_region",
},
ProjectID: &helper.Info{
TagName: "project_id",
Value: "test_project",
},
}
}

t.Setenv("K_SERVICE", "test_service")
t.Setenv("K_REVISION", "test_revision")
t.Setenv("K_CONFIGURATION", "test_config")
t.Setenv("FUNCTION_SIGNATURE_TYPE", "test_signature")
t.Setenv("FUNCTION_TARGET", "test_target")

tags := service.GetTags()

assert.Equal(t, map[string]string{
"container_id": "test_container",
"region": "test_region",
"origin": "cloudfunctions",
"project_id": "test_project",
"service_name": "test_service",
"revision_name": "test_revision",
"configuration_name": "test_config",
"_dd.origin": "cloudfunctions",
"function_target": "test_target",
"function_signature_type": "test_signature",
}, tags)
}
3 changes: 3 additions & 0 deletions cmd/serverless-init/cloudservice/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ func (l *LocalService) Init() error {
//nolint:revive // TODO(SERV) Fix revive linter
func GetCloudServiceType() CloudService {
if isCloudRunService() {
if isCloudRunFunction() {
return &CloudRun{cloudRunFunctionMode: true}
}
return &CloudRun{}
}

Expand Down
7 changes: 7 additions & 0 deletions pkg/trace/api/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const (
awsLambda cloudResourceType = "AWSLambda"
awsFargate cloudResourceType = "AWSFargate"
cloudRun cloudResourceType = "GCPCloudRun"
cloudFunctions cloudResourceType = "GCPCloudFunctions"
azureAppService cloudResourceType = "AzureAppService"
azureContainerApp cloudResourceType = "AzureContainerApp"
aws cloudProvider = "AWS"
Expand Down Expand Up @@ -283,6 +284,12 @@ func (f *TelemetryForwarder) setRequestHeader(req *http.Request) {
if serviceName, found := f.conf.GlobalTags["service_name"]; found {
req.Header.Set(cloudResourceIdentifierHeader, serviceName)
}
case "cloudfunction":
req.Header.Set(cloudProviderHeader, string(gcp))
req.Header.Set(cloudResourceTypeHeader, string(cloudFunctions))
if serviceName, found := f.conf.GlobalTags["service_name"]; found {
req.Header.Set(cloudResourceIdentifierHeader, serviceName)
}
case "appservice":
req.Header.Set(cloudProviderHeader, string(azure))
req.Header.Set(cloudResourceTypeHeader, string(azureAppService))
Expand Down

0 comments on commit 3ca96b6

Please sign in to comment.