lambda

package module
v0.1.9 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 23, 2025 License: Apache-2.0 Imports: 18 Imported by: 2

README

Lambda handler wrappers with sensible defaults

Go Reference

Convenient handler wrappers

The various StartABC functions wrap your Lambda handler so that a Metrics instance (from github.com/nguyengg/go-aws-commons/metrics) is available from context and will be logged with sensible default metrics (start and end time, latency, fault, etc.) upon return of your Lambda handler.

package main

import (
	"context"

	"github.com/aws/aws-lambda-go/events"
	"github.com/nguyengg/go-aws-commons/lambda"
	"github.com/nguyengg/go-aws-commons/metrics"
)

func main() {
	// you can use a specific specialisation for your handler like DynamoDB stream event below.
	lambda.StartDynamoDBEventHandleFunc(func(ctx context.Context, event events.DynamoDBEvent) (events.DynamoDBEventResponse, error) {
		m := metrics.Ctx(ctx)
		m.IncrementCount("myMetric")
		return events.DynamoDBEventResponse{}, nil
	})

	// or you can use the generic StartHandlerFunc template if there isn't a specialisation.
	lambda.StartHandlerFunc(func(ctx context.Context, event events.DynamoDBEvent) (events.DynamoDBEventResponse, error) {
		m := metrics.Ctx(ctx)
		m.IncrementCount("myMetric")
		return events.DynamoDBEventResponse{}, nil
	})

	// when your handler returns, the Metrics instance will be logged to standard error stream.
}

Gin adapter for Function URL

A Gin adapter for API Gateway V1 and V2 are already available from github.com/awslabs/aws-lambda-go-api-proxy. The gin-function-url module (named ginadapter) provides an adapter specifically for Function URL events with both BUFFERED (which, technically, is no different from API Gateway V2/HTTP events) and RESPONSE_STREAM mode which uses github.com/aws/aws-lambda-go/lambdaurl.

package main

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/render"
	ginadapter "github.com/nguyengg/go-aws-commons/lambda/gin-function-url"
)

func main() {
	r := gin.Default()
	r.GET("/", func(c *gin.Context) {
		c.Render(http.StatusOK, render.String{
			Format: "hello, world!",
		})
	})

	// start the Lambda handler either in BUFFERED or STREAM_RESPONSE mode.
	ginadapter.StartBuffered(r)
	ginadapter.StartStream(r)
}

GetParameter and GetSecretValue using AWS Parameter and Secrets Lambda extension

When running in Lambda, if you need to retrieve parameters from Parameter Store or secrets from Secrets Manager, you can use the AWS Parameter and Secrets Lambda extension to cache the values. The extension was first described in detail in blog post https://aws.amazon.com/blogs/compute/using-the-aws-parameter-and-secrets-lambda-extension-to-cache-parameters-and-secrets/.

package main

import (
	"context"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/service/secretsmanager"
	"github.com/aws/aws-sdk-go-v2/service/ssm"
	"github.com/nguyengg/go-aws-commons/lambda"
)

func main() {
	// lambda.ParameterSecretsExtensionClient implements GetSecretValue and GetParameter so I can substitute the
	// client to any code that needs it. the zero-value struct is ready for use.
	c := lambda.ParameterSecretsExtensionClient{}

	// in my Lambda handler, instead of invoking Secrets Manager SDK directly, I can use the client from the
	// extension package which makes use of the AWS Parameter and Secrets Lambda extension.
	_, err := c.GetSecretValue(context.Background(), &secretsmanager.GetSecretValueInput{
		SecretId:     aws.String("my-secret"),
		VersionId:    nil,
		VersionStage: nil,
	})

	// I can also use the package-level methods which will use the default client.
	_, err = lambda.GetParameter(context.Background(), &ssm.GetParameterInput{
		Name:           aws.String("my-parameter"),
		WithDecryption: nil,
	})
}

getenv adds abstraction on top of this so that I can easily swap out how the variable is retrieved.

package main

import (
	"context"
	"crypto/hmac"
	"crypto/sha256"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/service/secretsmanager"
	"github.com/aws/aws-sdk-go-v2/service/ssm"
	"github.com/nguyengg/go-aws-commons/lambda/getenv"
)

func main() {
	// while prototyping, you can retrieve from environment variable
	v := getenv.Env("TEST")

	// now you want to retrieve from Parameter Store instead
	v = getenv.ParameterString(&ssm.GetParameterInput{
		Name:           aws.String("my-parameter-name"),
		WithDecryption: aws.Bool(true),
	})

	// in the next example, the key is retrieved and then used as secret key for HMAC verification.
	key := getenv.SecretBinary(&secretsmanager.GetSecretValueInput{
		SecretId:     aws.String("my-secret-id"),
		VersionId:    nil,
		VersionStage: nil,
	})
	h := hmac.New(sha256.New, key.MustGetWithContext(context.Background()))
	h.Write( /* some data */ )
	h.Sum(nil)
}

Documentation

Index

Constants

View Source
const (
	// DebugLogFlags is the flag passed to log.SetFlags by SetUpLogger if IsDebug is true.
	DebugLogFlags = log.Ldate | log.Lmicroseconds | log.LUTC | log.Llongfile | log.Lmsgprefix

	// DefaultLogFlags is the flag passed to log.SetFlags by SetUpLogger if IsDebug is false.
	DefaultLogFlags = DebugLogFlags | log.Lshortfile
)

Variables

View Source
var DefaultParameterSecretsExtensionClient = &ParameterSecretsExtensionClient{Client: http.DefaultClient}

DefaultParameterSecretsExtensionClient is the client used by package-level GetSecretValue and GetParameter.

View Source
var IsDebug bool

IsDebug is true if the "DEBUG" environment have value "1" or "true".

The value of IsDebug is set at startup by way of init(). While many things in the lambda package use this value, nothing will modify it. If you want to use a different environment variable or a different way to toggle DEBUG behaviour, modify this value directly.

Functions

func GetParameter

func GetParameter(ctx context.Context, input *ssm.GetParameterInput) (*ssm.GetParameterOutput, error)

GetParameter is a wrapper around [DefaultClient.GetParameter].

func GetSecretValue

GetSecretValue is a wrapper around [DefaultClient.GetSecretValue].

func JSON added in v0.1.1

func JSON(v interface{}) fmt.Formatter

JSON returns a fmt.Formatter wrapper that returns the JSON representation of the given struct.

If encoding the struct v fails, falls back to original formatter.

Usage:

log.Printf("request=%s", JSON(v))

func JSONIdent added in v0.1.1

func JSONIdent(v interface{}, prefix, indent string) fmt.Formatter

JSONIdent is a variant of JSON that marshals with indentation.

func LoggerWithContext added in v0.1.6

func LoggerWithContext(ctx context.Context) (_ context.Context, l *zerolog.Logger)

LoggerWithContext returns a valid zerolog.Logger for use.

Because zerolog.Ctx may return a disabled (no-op) logger, it's difficult to determine if user is intentionally disabling logging via context, or if the zerolog.DefaultContextLogger has not been set up. As a result, this method may create a new logger if it can determine that one should be created, and the logger will be attached to the new returned context in that case. If zerolog.DefaultContextLogger is not nil then the returned value from zerolog.Ctx is always used.

Furthermore, if a Lambda context is available from lambdacontext.FromContext, the zerolog.Context of the returned logger is updated with a string awsRequestID.

func SetUpGlobalLogger

func SetUpGlobalLogger(ctx context.Context) func()

SetUpGlobalLogger applies sensible default settings to log.Default instance.

Specifically, log.SetFlags is called with DefaultLogFlags, and if lambdacontext.LambdaContext.AwsRequestId is available then it is set as the log prefix with log.SetPrefix.

A function is returned that should be deferred upon to reset the log flags and prefix back to the original values. Use SetUpLogger if you wish to modify a specific log.Logger.

Usage

// this should be the first line in your AWS Lambda handler. many Start methods in this package will do this
// for you by default.
// notice the double ()() to make sure SetUpGlobalLogger executes some function first, then its returned
// function is deferred.
defer logsupport.SetUpGlobalLogger()()

func SetUpLogger

func SetUpLogger(ctx context.Context, logger *log.Logger) func()

SetUpLogger is a variant of SetUpGlobalLogger that targets a specific log.Logger.

func Start added in v0.1.1

func Start[TIn any](handler func(context.Context, TIn) error, options ...lambda.Option)

Start is a variant of StartHandlerFunc for handlers that don't have any explicit returned value.

See StartHandlerFunc for an in-depth explanation on what are available.

func StartCloudWatchEventHandler added in v0.1.1

func StartCloudWatchEventHandler(handler func(context.Context, events.CloudWatchEvent) error)

StartCloudWatchEventHandler logs the CloudWatch event (without Detail attribute) as `event` JSON property.

func StartDynamoDBEventHandleFunc added in v0.1.1

func StartDynamoDBEventHandleFunc(handler func(context.Context, events.DynamoDBEvent) (events.DynamoDBEventResponse, error))

StartDynamoDBEventHandleFunc logs the number of records and the number of batch item failure as `recordCount` and `batchItemFailureCount` counters respectively.

func StartDynamoDBEventHandler added in v0.1.1

func StartDynamoDBEventHandler(handler func(context.Context, events.DynamoDBEvent) error)

StartDynamoDBEventHandler logs the number of records as `recordCount` counter.

func StartHandlerFunc added in v0.1.1

func StartHandlerFunc[TIn any, TOut any](handler func(context.Context, TIn) (TOut, error), options ...lambda.Option)

StartHandlerFunc is a wrapper around lambda.StartHandlerFunc that adds sensible defaults.

What is available out of the box with this wrapper:

  1. SetUpGlobalLogger is used to prefix the AWS Request Id to every log message.
  2. A metrics.Metrics instance is attached to the context with a few default metrics logged at the end of the request such as start and end time, metrics.Metrics.Panicked or metrics.Metrics.Fault if the underlying handler panics or returns an error. The wrapper will not attempt to recover so that the stack trace can propagate. The metrics.Metrics instance can be retrieved via metrics.Ctx.

func StartS3EventHandler added in v0.1.1

func StartS3EventHandler(handler func(context.Context, events.S3Event) error)

StartS3EventHandler logs the number of records as `recordCount` counter.

func StartSNSEventHandler added in v0.1.1

func StartSNSEventHandler(handler func(context.Context, events.SNSEvent) error)

StartSNSEventHandler logs the number of records as `recordCount` counter.

func StartSQSEventHandler added in v0.1.1

func StartSQSEventHandler(handler func(context.Context, events.SQSEvent) error)

StartSQSEventHandler logs the number of records as `recordCount` counter.

func StartSQSEventHandlerFunc added in v0.1.1

func StartSQSEventHandlerFunc(handler func(context.Context, events.SQSEvent) (events.SQSEventResponse, error))

StartSQSEventHandlerFunc logs the number of records and the number of batch item failure as `recordCount` and `batchItemFailureCount` counters respectively.

Types

type GetParameterClient

type GetParameterClient interface {
	GetParameter(ctx context.Context, params *ssm.GetParameterInput, optFns ...func(*ssm.Options)) (*ssm.GetParameterOutput, error)
}

GetParameterClient abstracts the GetParameter API that has an implementation using AWS Parameter and Secrets Lambda extension (ParameterSecretsExtensionClient).

type GetSecretValueClient

type GetSecretValueClient interface {
	GetSecretValue(ctx context.Context, params *secretsmanager.GetSecretValueInput, optFns ...func(*secretsmanager.Options)) (*secretsmanager.GetSecretValueOutput, error)
}

GetSecretValueClient abstracts the GetSecretValue API that has an implementation using AWS Parameter and Secrets Lambda extension (ParameterSecretsExtensionClient).

type ParameterSecretsExtensionClient

type ParameterSecretsExtensionClient struct {
	// Client is the HTTP client to use for making HTTP requests.
	//
	// If nil, http.DefaultClient is used.
	Client *http.Client
	// contains filtered or unexported fields
}

ParameterSecretsExtensionClient implements both GetParameterClient and GetSecretValueClient using the AWS Parameter and Secrets Lambda extension.

See https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets_lambda.html and https://docs.aws.amazon.com/systems-manager/latest/userguide/ps-integration-lambda-extensions.html.

The zero-value DefaultParameterSecretsExtensionClient is ready for use.

func (*ParameterSecretsExtensionClient) GetParameter

func (*ParameterSecretsExtensionClient) GetSecretValue

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL