Build, JSON and runtime notes¶
Start with your first Lambda for the short path.
Add tracing¶
When you need traces, install the Tracer module and configure an OTLP collector:
CGO_ENABLED=0 go get github.com/rambow-cloud/powertools-lambda-go/[email protected]
The maintained repository example composes Tracer and Logger:
package main
import (
"context"
stdlog "log"
"github.com/aws/aws-lambda-go/lambda"
"github.com/rambow-cloud/powertools-lambda-go/logger"
"github.com/rambow-cloud/powertools-lambda-go/tracer"
)
type Event struct {
Name string `json:"name"`
}
type Response struct {
Message string `json:"message"`
}
func main() {
appLog := logger.New(
logger.WithServiceName("hello"),
logger.WithErrorHandler(func(err error) {
stdlog.Printf("logging failed: %v", err)
}),
)
tr, err := tracer.New(
tracer.WithServiceName("hello"),
tracer.WithCaptureResponse(false),
tracer.WithErrorHandler(func(err error) {
stdlog.Printf("tracing failed: %v", err)
}),
)
if err != nil {
stdlog.Fatal(err)
}
handler := func(ctx context.Context, event Event) (Response, error) {
requestLog := appLog.WithContext(ctx)
if err := requestLog.Info("Handling request", logger.Fields{"name": event.Name}); err != nil {
stdlog.Printf("logging failed: %v", err)
}
return tracer.Capture(ctx, tr, "greet", func(ctx context.Context) (Response, error) {
_ = tr.PutAnnotation(ctx, "Operation", "greet")
return Response{Message: "Hello, " + event.Name}, nil
})
}
// Put the tracer outside the logger wrapper so logs receive the active span context.
lambda.Start(tracer.WrapHandler(tr, logger.WrapHandler(appLog, handler)))
}
Put Tracer outside Logger so logs can read the active span. Both wrappers share the same invocation identity. This example disables response capture; follow the Tracer guide for child spans and exporter configuration.
Configure observability¶
These settings are useful starting points for the deployed function:
| Environment variable | Example | Purpose |
|---|---|---|
POWERTOOLS_SERVICE_NAME |
orders |
Default service name when no explicit option overrides it |
POWERTOOLS_LOG_LEVEL |
INFO |
Structured log threshold |
POWERTOOLS_LOGGER_LOG_EVENT |
false |
Keep full event logging disabled |
OTEL_EXPORTER_OTLP_ENDPOINT |
http://localhost:4318 |
OTLP/HTTP collector endpoint |
POWERTOOLS_TRACER_CAPTURE_RESPONSE |
false |
Disable handler response metadata |
The example explicitly sets its service name to hello. Change that option or omit it to use the environment default.
A collector must actually be running at the configured OTLP endpoint. The library does not install a Lambda layer. To send traces to AWS X-Ray, deploy an appropriate collector extension with the awsxray exporter and its required execution-role permissions; follow X-Ray through OpenTelemetry.
Build and package¶
For the copied Logger-only program, build in your application directory:
Use GOARCH=amd64 for x86_64. Deploy the executable as bootstrap with
provided.al2023; the deployment ZIP must retain executable permissions.
To build and package both architectures of the maintained Logger/Tracer example, use the repository's packaging helper. Obtain a checkout:
git clone --branch v1.2.0 https://github.com/rambow-cloud/powertools-lambda-go.git
cd powertools-lambda-go
Run the following commands from the repository root:
The packaging tool verifies static Linux ELF binaries, architecture metadata, and an executable bootstrap ZIP entry with mode 0755.
| Lambda architecture | Artifact |
|---|---|
x86_64 |
dist/lambda-amd64.zip |
arm64 |
dist/lambda-arm64.zip |
Deploy the matching ZIP using your infrastructure tooling with runtime provided.al2023. Invoke with {"name":"Ada"}; the example returns {"message":"Hello, Ada"}. Deployment and cloud invocation are separate from local builds and CI.
Local verification¶
The default runtime acceptance environment uses Docker. Follow the maintained local integration runner and local acceptance scope.
Outside Lambda, tracing is disabled unless you explicitly supply tracer.WithLocalTracing(true). A local collector is still required to export spans. POWERTOOLS_DEV=true enables readable local logs and disables tracing.
Continue with Logger, Tracer, or Metrics.
JSON decoding and encoding¶
Maintained packages and examples use encoding/json/v2 and encoding/json/jsontext directly. Go 1.27 provides these APIs without an experiment flag. JSON object member names must be unique, UTF-8 and escaped Unicode must be valid, and struct fields match JSON names case-sensitively. Give application structs explicit json tags that match their input.
Nil slices and maps encode as [] and {}. omitempty omits empty JSON values; use omitzero when a field's Go zero value should be absent. Map member order is unspecified unless an operation explicitly requires ordering. Strings do not escape HTML by default. Byte arrays and slices use Base64; time.Duration requires an explicit supported format. Custom encoding can implement MarshalJSONTo(*jsontext.Encoder) error; decoding can implement UnmarshalJSONFrom(*jsontext.Decoder) error. See the JSON v2 API for the complete current behavior. json.RawMessage and json.Number from encoding/json remain usable value types; maintained serialization calls use v2 APIs.
These rules describe JSON serialization owned by Powertools. Invocation input/output serialization performed by aws-lambda-go follows that SDK's encoding contract.