Skip to content

Commit

Permalink
feat(logging): cloud run and functions resource autodetection (#3909)
Browse files Browse the repository at this point in the history
Fixes: #3486 

Changes: 

- [x] cloud run has correct resource labels and type
- [x] functions has correct resource labels and type
- [x] e2e environment tests covered [here](https://github.com/googleapis/env-tests-logging/)
  • Loading branch information
0xSage committed Apr 14, 2021
1 parent e9ff7a0 commit 1204de8
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -10,3 +10,4 @@ coverage.txt

# Other
.DS_Store
internal/env-tests-logging
78 changes: 75 additions & 3 deletions logging/logging.go
Expand Up @@ -244,7 +244,7 @@ type LoggerOption interface {

// CommonResource sets the monitored resource associated with all log entries
// written from a Logger. If not provided, the resource is automatically
// detected based on the running environment (on GCE and GAE Standard only).
// detected based on the running environment (on GCE, GCR, GCF and GAE Standard only).
// This value can be overridden per-entry by setting an Entry's Resource field.
func CommonResource(r *mrpb.MonitoredResource) LoggerOption { return commonResource{r} }

Expand Down Expand Up @@ -298,13 +298,81 @@ func detectGAEResource() *mrpb.MonitoredResource {
}
}

func isCloudRun() bool {
_, config := os.LookupEnv("K_CONFIGURATION")
_, service := os.LookupEnv("K_SERVICE")
_, revision := os.LookupEnv("K_REVISION")
return config && service && revision
}

func detectCloudRunResource() *mrpb.MonitoredResource {
projectID, err := metadata.ProjectID()
if err != nil {
return nil
}
zone, err := metadata.Zone()
if err != nil {
return nil
}
return &mrpb.MonitoredResource{
Type: "cloud_run_revision",
Labels: map[string]string{
"project_id": projectID,
"location": regionFromZone(zone),
"service_name": os.Getenv("K_SERVICE"),
"revision_name": os.Getenv("K_REVISION"),
"configuration_name": os.Getenv("K_CONFIGURATION"),
},
}
}

func isCloudFunction() bool {
// Reserved envvars in older function runtimes, e.g. Node.js 8, Python 3.7 and Go 1.11.
_, name := os.LookupEnv("FUNCTION_NAME")
_, region := os.LookupEnv("FUNCTION_REGION")
_, entry := os.LookupEnv("ENTRY_POINT")

// Reserved envvars in newer function runtimes.
_, target := os.LookupEnv("FUNCTION_TARGET")
_, signature := os.LookupEnv("FUNCTION_SIGNATURE_TYPE")
_, service := os.LookupEnv("K_SERVICE")
return (name && region && entry) || (target && signature && service)
}

func detectCloudFunction() *mrpb.MonitoredResource {
projectID, err := metadata.ProjectID()
if err != nil {
return nil
}
zone, err := metadata.Zone()
if err != nil {
return nil
}
// Newer functions runtimes store name in K_SERVICE.
functionName, exists := os.LookupEnv("K_SERVICE")
if !exists {
functionName, _ = os.LookupEnv("FUNCTION_NAME")
}
return &mrpb.MonitoredResource{
Type: "cloud_function",
Labels: map[string]string{
"project_id": projectID,
"region": regionFromZone(zone),
"function_name": functionName,
},
}
}

func detectResource() *mrpb.MonitoredResource {
detectedResource.once.Do(func() {
switch {
// GAE needs to come first, as metadata.OnGCE() is actually true on GAE
// Second Gen runtimes.
// AppEngine, Functions, CloudRun need to come first, as metadata.OnGCE() returns true on these runtimes.
case os.Getenv("GAE_ENV") == "standard":
detectedResource.pb = detectGAEResource()
case isCloudFunction():
detectedResource.pb = detectCloudFunction()
case isCloudRun():
detectedResource.pb = detectCloudRunResource()
case metadata.OnGCE():
detectedResource.pb = detectGCEResource()
}
Expand Down Expand Up @@ -334,6 +402,10 @@ func monitoredResource(parent string) *mrpb.MonitoredResource {
}
}

func regionFromZone(zone string) string {
return zone[:strings.LastIndex(zone, "-")]
}

func globalResource(projectID string) *mrpb.MonitoredResource {
return &mrpb.MonitoredResource{
Type: "global",
Expand Down

0 comments on commit 1204de8

Please sign in to comment.