Skip to content

Commit

Permalink
fix: Generate psedurandom execution id if Function-Execution-Id is no…
Browse files Browse the repository at this point in the history
…t provided; Update README with examples (#260)

* fix: Generate psedurandom execution id if Function-Execution-Id is missing; Update README with exeamples to generate execution Id

* Update README.md to address comments
  • Loading branch information
chujchen authored Jan 27, 2025
1 parent a1ec99e commit 7107a52
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 3 deletions.
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,57 @@ handling logic.
curl localhost:8080
# Output: Hello, World!
```
## Quickstart: Enable Exeuction Id Logging

[Cloud Run Functions(1st gen)](https://cloud.google.com/functions/1stgendocs/deploy) provides an execution id in the logs at `labels.execution_id`, which customers can use to filter their logs for each execution. [Cloud Run Functions](https://cloud.google.com/functions/docs/deploy) doesn't have the same feature embedded.

To have exeuction id logged for `Cloud Run Functions` executions, users can either:

* Provide a custom execution Id in the Http Header `Function-Execution-Id`.

```sh
curl -H "Function-Execution-Id: 123456" localhost:8080
# Output: Hello, World!
```

Example Log:
```
{"message":"Try logging with executionID!","logging.googleapis.com/labels":{"execution_id":"123456"}}
```


OR
* Leverage `LogWriter` provided in function-framework-go(v1.9.0 or higher) library to generate logs. If `Function-Exeuction-Id` is empty, a pseduorandom execution id will be auto-generated if `LogWriter` is used.

```golang
package function

import (
"fmt"
"net/http"
"log"
"github.com/GoogleCloudPlatform/functions-framework-go/functions"
"github.com/GoogleCloudPlatform/functions-framework-go/funcframework"
)

func init() {
functions.HTTP("HelloWorld", helloWorld)
}

// helloWorld writes "Hello, World!" to the HTTP response.
func helloWorld(w http.ResponseWriter, r *http.Request) {
l := log.New(funcframework.LogWriter(r.Context()), "", 0)

l.Println("Try logging with executionID!")
fmt.Fprintln(w, "Hello, World!")
}
```

Example Log:
```
{"message":"Try logging with executionID!","logging.googleapis.com/labels":{"execution_id":"181dbb5b096549313d470dd68fa64d96"}}
```


## Go further: build a deployable container

Expand Down
10 changes: 9 additions & 1 deletion funcframework/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import (
"bufio"
"context"
"encoding/json"
"fmt"
"io"
"math/rand"
"net/http"
"os"
"regexp"
"sync"
"time"
)

var (
Expand All @@ -32,6 +35,11 @@ type contextKey string

func addLoggingIDsToRequest(r *http.Request) *http.Request {
executionID := r.Header.Get("Function-Execution-Id")
if executionID == "" {
timestamp := time.Now().UnixNano()
random := rand.Int63()
executionID = fmt.Sprintf("%06x%06x", timestamp, random)
}
traceID, spanID, _ := deconstructXCloudTraceContext(r.Header.Get("X-Cloud-Trace-Context"))

if executionID == "" && traceID == "" && spanID == "" {
Expand Down Expand Up @@ -182,7 +190,7 @@ func (w *structuredLogWriter) Close() error {
// )
// ...
// func helloWorld(w http.ResponseWriter, r *http.Request) {
// l := logger.New(funcframework.LogWriter(r.Context()))
// l := log.New(funcframework.LogWriter(r.Context()), "", 0)
// l.Println("hello world!")
// }
func LogWriter(ctx context.Context) io.WriteCloser {
Expand Down
13 changes: 11 additions & 2 deletions funcframework/logging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ func TestLoggingIDExtraction(t *testing.T) {
wantTraceID string
wantSpanID string
wantExecutionID string
randomExecutionIdGenerated bool
}{
{
name: "no IDs",
headers: map[string]string{},
randomExecutionIdGenerated: true,
},
{
name: "execution ID only",
name: "provided execution ID only",
headers: map[string]string{
"Function-Execution-Id": "exec id",
},
Expand All @@ -32,13 +34,15 @@ func TestLoggingIDExtraction(t *testing.T) {
headers: map[string]string{
"X-Cloud-Trace-Context": "$*#$(v434)",
},
randomExecutionIdGenerated: true,
},
{
name: "trace ID only",
headers: map[string]string{
"X-Cloud-Trace-Context": "0123456789abcdef",
},
wantTraceID: "0123456789abcdef",
randomExecutionIdGenerated: true,
},
{
name: "trace ID and span ID",
Expand All @@ -47,6 +51,7 @@ func TestLoggingIDExtraction(t *testing.T) {
},
wantTraceID: "0123456789abcdef",
wantSpanID: "aaaaaa",
randomExecutionIdGenerated: true,
},
{
name: "all",
Expand Down Expand Up @@ -77,9 +82,13 @@ func TestLoggingIDExtraction(t *testing.T) {
t.Errorf("expected span id %q but got %q", tc.wantSpanID, spid)
}

if eid := ExecutionIDFromContext(ctx); eid != tc.wantExecutionID {
eid := ExecutionIDFromContext(ctx);
if tc.wantExecutionID != "" && eid != tc.wantExecutionID {
t.Errorf("expected execution id %q but got %q", tc.wantExecutionID, eid)
}
if tc.randomExecutionIdGenerated && eid == "" {
t.Errorf("expected random execution id generated but got %q", eid)
}
})
}
}
Expand Down

0 comments on commit 7107a52

Please sign in to comment.