gslog

package module
v0.21.0 Latest Latest
Warning

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

Go to latest
Published: Apr 18, 2024 License: Apache-2.0 Imports: 15 Imported by: 0

README

gslog

Go Version Documentation Go Report Card codecov License

A Google Cloud Logging Handler implementation for slog.


This Google Cloud Logging (GCL) slog.Handler implementation directly fills the GCL entry, logging.Entry, with information obtained in the context.Context, slog.Record, and implied context within the Handler itself. The logging.Entry.Payload is filled with a Protobuf structpb.Struct instance, resulting in a jsonPayload with the log message having the key "message". Log records are sent asynchronously. Critical level, or higher, log records will be sent synchronously.

The GCL Handler's options include a number of ways to include information from "outside" frameworks:

  • Labels attached to the context, via gslog.WithLabels(ctx, ...labels), which are added to the GCL entry, logging.Entry, Labels field.
  • OpenTelemetry baggage attached to the context which are added as attributes, slog.Attr, to the logging record, slog.Record. The baggage keys are prefixed with "otel-baggage/" to mitigate collision with other log attributes.
  • OpenTelemetry tracing attached to the context which are added directly to the GCL entry, logging.Entry, tracing fields.
  • Labels from the Kubernetes Downward API podinfo labels file, which are added to the GCL entry, logging.Entry, Labels field. The labels are prefixed with "k8s-pod/" to adhere to the GCL conventions for Kubernetes Pod labels.

Install

go get m4o.io/gslog

Compatibility: go >= 1.21

Example Usage

First create a Google Cloud Logging logging.Client to use throughout your application:

ctx := context.Background()
client, err := logging.NewClient(ctx, "my-project")
if err != nil {
	// TODO: Handle error.
}

Usually, you'll want to add log entries to a buffer to be periodically flushed (automatically and asynchronously) to the Cloud Logging service. Use the logger when creating the new gslog.GcpHandler which is passed to slog.New() to obtain a slog-based logger.

loggger := client.Logger("my-log")

h := gslog.NewGcpHandler(loggger)
l := slog.New(h)

l.Info("How now brown cow?")

Writing critical, or higher, log level entries will be sent synchronously.

l.Log(context.Background(), gslog.LevelCritical, "Danger, Will Robinson!")

Close your client before your program exits, to flush any buffered log entries.

err = client.Close()
if err != nil {
   // TODO: Handle error.
}

Logger Configuration Options

Creating a Google Cloud Logging Handler using gslog.NewGcpHandler(logger, ...options) accepts the following options:

Configuration option Arguments Description
gslog.WithLogLeveler(leveler) slog.Leveler Specifies the slog.Leveler for logging. Explicitly setting the log level here takes precedence over the other options.
gslog.WithLogLevelFromEnvVar(envVar) string Specifies the log level for logging comes from tne environmental variable specified by the key.
gslog.WithDefaultLogLeveler() slog.Leveler Specifies the default slog.Leveler for logging.
gslog.WithSourceAdded() Causes the handler to compute the source code position of the log statement and add a slog.SourceKey attribute to the output.
gslog.WithLabels() Adds any labels found in the context to the logging.Entry's Labels field.
gslog.WithReplaceAttr(mapper) gslog.Mapper Specifies an attribute mapper used to rewrite each non-group attribute before it is logged.
otel.WithOtelBaggage() Directs that the slog.Handler to include OpenTelemetry baggage. The baggage.Baggage is obtained from the context, if available, and added as attributes.
otel.WithOtelTracing() Directs that the slog.Handler to include OpenTelemetry tracing. Tracing information is obtained from the trace.SpanContext stored in the context, if provided.
k8s.WithPodinfoLabels(root) string Directs that the slog.Handler to include labels from the Kubernetes Downward API podinfo labels file. The labels file is expected to be found in the directory specified by root and MUST be named "labels", per the Kubernetes Downward API for Pods.

Design Notes

There's a number of different ways to map the slog.Record to a GCL entry, logging.Entry.

  • a JSON string
  • a value that can be marshaled to a JSON object, like a map[string]interface{} or a struct
  • a Protobuf *anypb.Any

The pros and cons are

Payload type pros cons
JSON string fast and efficient to generate on the slog side logged as a flat unstructured textPayload in GCL
value that can be marshaled to a JSON object logged as a structured jsonPayload in GCL the marshalling effort is complicated and not amortized
Protobuf *anypb.Any not known at the moment not known at the moment

Even though a JSON string can be marshaled to a JSON object, the GCL client merely looks at its Go type and decides to treat it as a flat text message.

If not a string, values that can be marshaled to a JSON object are actually first marshalled into a JSON object, i.e. map[string]interface{}, and then that resulting JSON object is translated into an equivalent structpb.Struct Protobuf message. The GCL logger will redo this marshalling and translating for every message logged.

The reason why the logging.Entry Payload field is set with a Protobuf structpb.Struct when the end result is a jsonPayload GCL logging entry is because that's what Logger.Log(e) does anyway, behind the scenes. When either

Documentation

Overview

Package gslog contains a GCP logging implementation of slog.Handler.

Index

Examples

Constants

View Source
const (
	// LevelNotice means normal but significant events, such as start up,
	// shut down, or configuration.
	LevelNotice = slog.Level(2)
	// LevelCritical means events that cause more severe problems or brief
	// outages.
	LevelCritical = slog.Level(12)
	// LevelAlert means a person must take an action immediately.
	LevelAlert = slog.Level(16)
	// LevelEmergency means one or more systems are unusable.
	LevelEmergency = slog.Level(20)
)
View Source
const (
	// MessageKey is the key used for the message of the log call, per Google
	// Cloud Logging. The associated value is a string.
	MessageKey = "message"
)

Variables

This section is empty.

Functions

func ExtractLabels

func ExtractLabels(ctx context.Context) map[string]string

ExtractLabels extracts labels from the ctx. These labels were associated with the context using WithLabels.

func WithDefaultLogLeveler added in v0.16.0

func WithDefaultLogLeveler(defaultLogLevel slog.Leveler) options.OptionProcessor

WithDefaultLogLeveler returns an option that specifies the default slog.Leveler for logging.

func WithLabels

func WithLabels(ctx context.Context, labels ...LabelPair) context.Context

WithLabels returns a new Context with labels to be used in the GCP log entries produced using that context.

func WithLogLevelFromEnvVar

func WithLogLevelFromEnvVar(key string) options.OptionProcessor

WithLogLevelFromEnvVar returns an option that specifies the log level for logging comes from tne environmental variable specified by the key.

func WithLogLeveler added in v0.16.0

func WithLogLeveler(logLevel slog.Leveler) options.OptionProcessor

WithLogLeveler returns an option that specifies the slog.Leveler for logging. Explicitly setting the log level here takes precedence over the other options.

func WithReplaceAttr

func WithReplaceAttr(replaceAttr AttrMapper) options.OptionProcessor

WithReplaceAttr returns an option that specifies an attribute mapper used to rewrite each non-group attribute before it is logged.

func WithSourceAdded

func WithSourceAdded() options.OptionProcessor

WithSourceAdded returns an option that causes the handler to compute the source code position of the log statement and add a slog.SourceKey attribute to the output.

Types

type AttrMapper

type AttrMapper attr.Mapper

AttrMapper is called to rewrite each non-group attribute before it is logged. The attribute's value has been resolved (see [Value.Resolve]). If replaceAttr returns a zero Attr, the attribute is discarded.

The built-in attribute with key "message" is passed to this function.

The first argument is a list of currently open groups that contain the Attr. It must not be retained or modified. replaceAttr is never called for Group attributes, only their contents. For example, the attribute list

Int("a", 1), Group("g", Int("b", 2)), Int("c", 3)

results in consecutive calls to replaceAttr with the following arguments:

nil, Int("a", 1)
[]string{"g"}, Int("b", 2)
nil, Int("c", 3)

AttrMapper can be used to change the default keys of the built-in attributes, convert types (for example, to replace a `time.Time` with the integer seconds since the Unix epoch), sanitize personal information, or remove attributes from the output.

type GcpHandler

type GcpHandler struct {
	// contains filtered or unexported fields
}

GcpHandler is a Google Cloud Logging backed slog handler.

func NewGcpHandler

func NewGcpHandler(logger Logger, opts ...options.OptionProcessor) *GcpHandler

NewGcpHandler creates a Google Cloud Logging backed log.Logger.

Example

A gslog.GcpHandler is created with a GCP logging.Logger. The handler will map slog.Record records to logging.Entry entries, subsequently passing the resulting entries to its configured logging.Logger instance's Log() method.

package main

import (
	"context"
	"log/slog"

	"cloud.google.com/go/logging"

	"m4o.io/gslog"
)

func main() {
	ctx := context.Background()
	client, err := logging.NewClient(ctx, "my-project")
	if err != nil {
		// TODO: Handle error.
	}

	lg := client.Logger("my-log")

	lg.Flush()

	h := gslog.NewGcpHandler(lg)
	l := slog.New(h)

	l.Info("How now brown cow?")
}
Output:

Example (WithDefaultLogLeveler)

A default log level configured via gslog.WithDefaultLogLeveler().

package main

import (
	"encoding/json"
	"fmt"
	"log/slog"

	"cloud.google.com/go/logging"
	"google.golang.org/protobuf/encoding/protojson"

	spb "google.golang.org/protobuf/types/known/structpb"

	"m4o.io/gslog"
)

// PrintJsonPayload is a gslog.Logger stub that prints the logging.Entry
// Payload field as a JSON string.
func PrintJsonPayload(e logging.Entry) {
	b, _ := protojson.Marshal(e.Payload.(*spb.Struct))

	var j map[string]interface{}
	_ = json.Unmarshal(b, &j)
	b, _ = json.Marshal(j)
	fmt.Println(string(b))
}

func main() {
	const envVar = "FOO_LOG_LEVEL"

	h := gslog.NewGcpHandler(
		gslog.LoggerFunc(PrintJsonPayload),
		gslog.WithLogLevelFromEnvVar(envVar),
		gslog.WithDefaultLogLeveler(slog.LevelError),
	)
	l := slog.New(h)

	l.Info("How now brown cow?")
	l.Error("The rain in Spain lies mainly on the plane.")

}
Output:

{"message":"The rain in Spain lies mainly on the plane."}
Example (WithK8sPodinfo)

When configured via k8s.WithPodinfoLabels(), gslog.GcpHandler will include labels from the configured Kubernetes Downward API podinfo labels file to the logging.Entry's Labels field.

The labels are prefixed with "k8s-pod/" to adhere to the Google Cloud Logging conventions for Kubernetes Pod labels.

package main

import (
	"context"
	"fmt"
	"log/slog"
	"sort"
	"strings"

	"cloud.google.com/go/logging"

	"m4o.io/gslog"
	"m4o.io/gslog/k8s"
)

// PrintLabels is a gslog.Logger stub that prints the logging.Entry's
// Labels field.
func PrintLabels(e logging.Entry) {
	keys := make([]string, 0)
	for k := range e.Labels {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	var sb strings.Builder
	for _, k := range keys {
		if sb.Len() > 0 {
			sb.WriteString(", ")
		}
		sb.WriteString(k + "=" + e.Labels[k])
	}

	fmt.Println(sb.String())
}

func main() {
	h := gslog.NewGcpHandler(gslog.LoggerFunc(PrintLabels), k8s.WithPodinfoLabels("k8s/testdata/etc/podinfo"))
	l := slog.New(h)

	ctx := context.Background()
	ctx = gslog.WithLabels(ctx, gslog.Label("a", "one"), gslog.Label("b", "two"))

	l.Log(ctx, gslog.LevelCritical, "Danger, Will Robinson!")

}
Output:

a=one, b=two, k8s-pod/app=hello-world, k8s-pod/environment=stg, k8s-pod/tier=backend, k8s-pod/track=stable
Example (WithLogLevelFromEnvVar)

When configured via gslog.WithLogLevelFromEnvVar(), gslog.GcpHandler obtains its log level from tne environmental variable specified by the key.

package main

import (
	"encoding/json"
	"fmt"
	"log/slog"
	"os"

	"cloud.google.com/go/logging"
	"google.golang.org/protobuf/encoding/protojson"

	spb "google.golang.org/protobuf/types/known/structpb"

	"m4o.io/gslog"
)

// PrintJsonPayload is a gslog.Logger stub that prints the logging.Entry
// Payload field as a JSON string.
func PrintJsonPayload(e logging.Entry) {
	b, _ := protojson.Marshal(e.Payload.(*spb.Struct))

	var j map[string]interface{}
	_ = json.Unmarshal(b, &j)
	b, _ = json.Marshal(j)
	fmt.Println(string(b))
}

func main() {
	const envVar = "FOO_LOG_LEVEL"
	_ = os.Setenv(envVar, "ERROR")
	defer func() {
		_ = os.Unsetenv(envVar)
	}()

	h := gslog.NewGcpHandler(gslog.LoggerFunc(PrintJsonPayload), gslog.WithLogLevelFromEnvVar(envVar))
	l := slog.New(h)

	l.Info("How now brown cow?")
	l.Error("The rain in Spain lies mainly on the plane.")

}
Output:

{"message":"The rain in Spain lies mainly on the plane."}
Example (WithLogLeveler)

When configured via gslog.WithLogLeveler(), gslog.GcpHandler use the slog.Leveler for logging level enabled checks.

package main

import (
	"encoding/json"
	"fmt"
	"log/slog"

	"cloud.google.com/go/logging"
	"google.golang.org/protobuf/encoding/protojson"

	spb "google.golang.org/protobuf/types/known/structpb"

	"m4o.io/gslog"
)

// PrintJsonPayload is a gslog.Logger stub that prints the logging.Entry
// Payload field as a JSON string.
func PrintJsonPayload(e logging.Entry) {
	b, _ := protojson.Marshal(e.Payload.(*spb.Struct))

	var j map[string]interface{}
	_ = json.Unmarshal(b, &j)
	b, _ = json.Marshal(j)
	fmt.Println(string(b))
}

func main() {
	h := gslog.NewGcpHandler(gslog.LoggerFunc(PrintJsonPayload), gslog.WithLogLeveler(slog.LevelError))
	l := slog.New(h)

	l.Info("How now brown cow?")
	l.Error("The rain in Spain lies mainly on the plane.")

}
Output:

{"message":"The rain in Spain lies mainly on the plane."}
Example (WithOpentelemetryBaggage)

When configured via otel.WithOtelBaggage(), gslog.GcpHandler will include any baggage.Baggage attached to the context as attributes.

The baggage keys are prefixed with "otel-baggage/" to mitigate collision with other log attributes and have precedence over any collisions with preexisting attributes.

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log/slog"

	"cloud.google.com/go/logging"
	"go.opentelemetry.io/otel/baggage"
	"google.golang.org/protobuf/encoding/protojson"

	spb "google.golang.org/protobuf/types/known/structpb"

	"m4o.io/gslog"
	"m4o.io/gslog/otel"
)

// PrintJsonPayload is a gslog.Logger stub that prints the logging.Entry
// Payload field as a JSON string.
func PrintJsonPayload(e logging.Entry) {
	b, _ := protojson.Marshal(e.Payload.(*spb.Struct))

	var j map[string]interface{}
	_ = json.Unmarshal(b, &j)
	b, _ = json.Marshal(j)
	fmt.Println(string(b))
}

func main() {
	h := gslog.NewGcpHandler(gslog.LoggerFunc(PrintJsonPayload), otel.WithOtelBaggage())
	l := slog.New(h)

	ctx := context.Background()
	ctx = baggage.ContextWithBaggage(ctx, otel.MustParse("a=one,b=two;p1;p2=val2"))

	l.Log(ctx, slog.LevelInfo, "How now brown cow?")

}
Output:

{"message":"How now brown cow?","otel-baggage/a":"one","otel-baggage/b":{"properties":{"p1":null,"p2":"val2"},"value":"two"}}
Example (WithOpentelemetryTrace)

When configured via otel.WithOtelTracing(), gslog.GcpHandler will include any OpenTelemetry trace.SpanContext information associated with the context in the logging.Entry's tracing fields.

package main

import (
	"context"
	"fmt"
	"log/slog"
	"strings"

	"cloud.google.com/go/logging"
	"go.opentelemetry.io/otel/trace"

	"m4o.io/gslog"
	"m4o.io/gslog/otel"
)

// PrintTracing is a gslog.Logger stub that prints the logging.Entry's
// tracing fields.
func PrintTracing(e logging.Entry) {
	var sb strings.Builder

	sb.WriteString("trace: ")
	sb.WriteString(e.Trace)
	sb.WriteString(" span: ")
	sb.WriteString(e.SpanID)
	sb.WriteString(" flags: ")
	if e.TraceSampled {
		sb.WriteString("01")
	} else {
		sb.WriteString("00")
	}

	fmt.Println(sb.String())
}

func main() {
	h := gslog.NewGcpHandler(gslog.LoggerFunc(PrintTracing), otel.WithOtelTracing("my-project"))
	l := slog.New(h)

	traceId, _ := trace.TraceIDFromHex("52fc1643a9381fc674742bb0067101e7")
	spanId, _ := trace.SpanIDFromHex("d3e9e8c51cb190df")

	ctx := context.Background()
	ctx = trace.ContextWithRemoteSpanContext(ctx, trace.NewSpanContext(trace.SpanContextConfig{
		TraceID:    traceId,
		SpanID:     spanId,
		TraceFlags: trace.FlagsSampled,
	}))

	l.Log(ctx, slog.LevelInfo, "How now brown cow?")

}
Output:

trace: projects/my-project/traces/52fc1643a9381fc674742bb0067101e7 span: d3e9e8c51cb190df flags: 01
Example (WithReplaceAttr)

When configured via gslog.WithReplaceAttr(), gslog.GcpHandler will apply the supplied gslog.AttrMapper to all non-group attributes before they are logged.

package main

import (
	"encoding/json"
	"fmt"
	"log/slog"
	"strconv"

	"cloud.google.com/go/logging"
	"google.golang.org/protobuf/encoding/protojson"

	spb "google.golang.org/protobuf/types/known/structpb"

	"m4o.io/gslog"
)

var (
	pw           = Password("pass-12334")
	pwObfuscated = slog.StringValue("<secret>")
)

type Manager struct{}

// Password is a specialised type whose fmt.Stringer, json.Marshaler, and
// slog.LogValuer implementations return an obfuscated value.
type Password string

func (p Password) String() string {
	return "<secret>"
}

func (p Password) MarshalJSON() ([]byte, error) {
	return []byte(strconv.Quote("<secret>")), nil
}

func (p Password) LogValue() slog.Value {
	return pwObfuscated
}

type User struct {
	ID        string   `json:"id"`
	FirstName string   `json:"first_name"`
	LastName  string   `json:"last_name"`
	Email     string   `json:"email"`
	Password  Password `json:"password"`
	Age       uint8    `json:"age"`
	Height    float32  `json:"height"`
	Engineer  bool     `json:"engineer"`
	Manager   *Manager `json:"manager"`
}

// PrintJsonPayload is a gslog.Logger stub that prints the logging.Entry
// Payload field as a JSON string.
func PrintJsonPayload(e logging.Entry) {
	b, _ := protojson.Marshal(e.Payload.(*spb.Struct))

	var j map[string]interface{}
	_ = json.Unmarshal(b, &j)
	b, _ = json.Marshal(j)
	fmt.Println(string(b))
}

// RemovePassword is a gslog.AttrMapper that elides password attributes.
func RemovePassword(_ []string, a slog.Attr) slog.Attr {
	if a.Key == "password" {
		return slog.Attr{}
	}
	return a
}

func main() {
	h := gslog.NewGcpHandler(gslog.LoggerFunc(PrintJsonPayload), gslog.WithReplaceAttr(RemovePassword))
	l := slog.New(h)
	l = l.WithGroup("pub")
	l = l.With(slog.String("username", "user-12234"), slog.String("password", string(pw)))

	l.Info("How now brown cow?")

}
Output:

{"message":"How now brown cow?","pub":{"username":"user-12234"}}
Example (WithSourceAdded)

When configured via gslog.WithSourceAdded(), gslog.GcpHandler will include the computationally expensive SourceLocation field in the logging.Entry.

h := gslog.NewGcpHandler(gslog.LoggerFunc(PrintSourceLocation), gslog.WithSourceAdded())
l := slog.New(h)

l.Log(ctx, slog.LevelInfo, "How now brown cow?")
Output:

{"file":"gslog/example_test.go","function":"m4o.io/gslog_test.ExampleNewGcpHandler_withSourceAdded","line":"259"}

func (*GcpHandler) Enabled

func (h *GcpHandler) Enabled(_ context.Context, level slog.Level) bool

Enabled reports whether the handler handles records at the given level. The handler ignores records whose level is lower.

func (*GcpHandler) Flush added in v0.17.0

func (h *GcpHandler) Flush() error

Flush blocks until all currently buffered log entries are sent.

If any errors occurred since the last call to Flush from any Logger, or the creation of the client if this is the first call, then Flush returns a non-nil error with summary information about the errors. This information is unlikely to be actionable. For more accurate error reporting, set Client.OnError.

func (*GcpHandler) Handle

func (h *GcpHandler) Handle(ctx context.Context, record slog.Record) error

Handle will handle a slog.Record, as described in the interface's documentation. It will translate the slog.Record into a logging.Entry that's filled with a *spb.Value as a Entry Payload.

Example (PayloadMapping)

The gslog.GcpHandler maps the slog.Record and the handler's nested group attributes into a JSON object, with the logged message keyed at the root with the key "message".

package main

import (
	"encoding/json"
	"fmt"
	"log/slog"
	"strconv"

	"cloud.google.com/go/logging"
	"google.golang.org/protobuf/encoding/protojson"

	spb "google.golang.org/protobuf/types/known/structpb"

	"m4o.io/gslog"
)

var (
	pw           = Password("pass-12334")
	pwObfuscated = slog.StringValue("<secret>")
	u            = &User{
		ID:        "user-12234",
		FirstName: "Jan",
		LastName:  "Doe",
		Email:     "jan@example.com",
		Password:  pw,
		Age:       32,
		Height:    5.91,
		Engineer:  true,
	}
)

type Manager struct{}

// Password is a specialised type whose fmt.Stringer, json.Marshaler, and
// slog.LogValuer implementations return an obfuscated value.
type Password string

func (p Password) String() string {
	return "<secret>"
}

func (p Password) MarshalJSON() ([]byte, error) {
	return []byte(strconv.Quote("<secret>")), nil
}

func (p Password) LogValue() slog.Value {
	return pwObfuscated
}

type User struct {
	ID        string   `json:"id"`
	FirstName string   `json:"first_name"`
	LastName  string   `json:"last_name"`
	Email     string   `json:"email"`
	Password  Password `json:"password"`
	Age       uint8    `json:"age"`
	Height    float32  `json:"height"`
	Engineer  bool     `json:"engineer"`
	Manager   *Manager `json:"manager"`
}

// PrintJsonPayload is a gslog.Logger stub that prints the logging.Entry
// Payload field as a JSON string.
func PrintJsonPayload(e logging.Entry) {
	b, _ := protojson.Marshal(e.Payload.(*spb.Struct))

	var j map[string]interface{}
	_ = json.Unmarshal(b, &j)
	b, _ = json.Marshal(j)
	fmt.Println(string(b))
}

func main() {
	h := gslog.NewGcpHandler(gslog.LoggerFunc(PrintJsonPayload))
	l := slog.New(h)
	l = l.WithGroup("pub")
	l = l.With(slog.Any("user", u))

	l.Info("How now brown cow?")

}
Output:

{"message":"How now brown cow?","pub":{"user":{"age":32,"email":"jan@example.com","engineer":true,"first_name":"Jan","height":5.91,"id":"user-12234","last_name":"Doe","manager":null,"password":"\u003csecret\u003e"}}}
Example (WithLabels)

The gslog.GcpHandler will add any labels found in the context to the logging.Entry's Labels field.

package main

import (
	"context"
	"fmt"
	"log/slog"
	"sort"
	"strings"

	"cloud.google.com/go/logging"

	"m4o.io/gslog"
)

// PrintLabels is a gslog.Logger stub that prints the logging.Entry's
// Labels field.
func PrintLabels(e logging.Entry) {
	keys := make([]string, 0)
	for k := range e.Labels {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	var sb strings.Builder
	for _, k := range keys {
		if sb.Len() > 0 {
			sb.WriteString(", ")
		}
		sb.WriteString(k + "=" + e.Labels[k])
	}

	fmt.Println(sb.String())
}

func main() {
	h := gslog.NewGcpHandler(gslog.LoggerFunc(PrintLabels))
	l := slog.New(h)

	ctx := context.Background()
	ctx = gslog.WithLabels(ctx, gslog.Label("a", "one"), gslog.Label("b", "two"))

	l.Log(ctx, slog.LevelInfo, "How now brown cow?")

}
Output:

a=one, b=two

func (*GcpHandler) WithAttrs

func (h *GcpHandler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs returns a copy of the handler whose attributes consists of h's attributes followed by attrs.

func (*GcpHandler) WithGroup

func (h *GcpHandler) WithGroup(name string) slog.Handler

WithGroup returns a copy of the handler with the given group appended to the receiver's existing groups.

func (*GcpHandler) WithLeveler added in v0.2.0

func (h *GcpHandler) WithLeveler(leveler slog.Leveler) *GcpHandler

WithLeveler returns a copy of the handler, provisioned with the supplied leveler.

type LabelPair

type LabelPair struct {
	// contains filtered or unexported fields
}

LabelPair represents a key-value string pair.

func Label

func Label(key, value string) LabelPair

Label returns a new LabelPair from a key and a value.

type Log added in v0.5.0

type Log interface {
	// Log buffers the Entry for output to the logging service. It never blocks.
	Log(e logging.Entry)
}

Log wraps the asynchronous buffered logging of records to Google Cloud Logging.

type LogSync added in v0.5.0

type LogSync interface {
	// LogSync logs the Entry synchronously without any buffering. Because LogSync is slow
	// and will block, it is intended primarily for debugging or critical errors.
	// Prefer Log for most uses.
	LogSync(ctx context.Context, e logging.Entry) error
}

LogSync wraps the synchronous logging of records to Google Cloud Logging.

type Logger added in v0.5.0

type Logger interface {
	Log
	LogSync

	// Flush blocks until all currently buffered log entries are sent.
	//
	// If any errors occurred since the last call to Flush from any Logger, or the
	// creation of the client if this is the first call, then Flush returns a non-nil
	// error with summary information about the errors. This information is unlikely to
	// be actionable. For more accurate error reporting, set Client.OnError.
	Flush() error
}

Logger is wraps the set of methods that are used when interacting with a logging.Logger. This interface facilitates stubbing out calls to the Logger for the purposes of testing and benchmarking.

type LoggerFunc added in v0.11.0

type LoggerFunc func(e logging.Entry)

The LoggerFunc type is an adapter to allow the use of ordinary functions as a Logger. If fn is a function with the appropriate signature, LoggerFunc(fn) is a Logger that calls fn.

func (LoggerFunc) Flush added in v0.17.0

func (fn LoggerFunc) Flush() error

Flush implements Logger.Flush.

func (LoggerFunc) Log added in v0.11.0

func (fn LoggerFunc) Log(e logging.Entry)

Log implements Log.Log.

func (LoggerFunc) LogSync added in v0.11.0

func (fn LoggerFunc) LogSync(_ context.Context, e logging.Entry) error

LogSync implements LogSync.LogSync.

type Options

type Options struct {
	options.Options
}

Options holds information needed to construct an instance of GcpHandler.

Directories

Path Synopsis
internal
attr
Package attr contains code that maps slog.Attr attributes to their corresponding structpb.Value values.
Package attr contains code that maps slog.Attr attributes to their corresponding structpb.Value values.
level
Package level contains code that maps slog.Level levels to logging.Severity.
Package level contains code that maps slog.Level levels to logging.Severity.
options
Package options holds the options handling code.
Package options holds the options handling code.
Package k8s contains options for including labels from the Kubernetes Downward API podinfo labels file in logging records.
Package k8s contains options for including labels from the Kubernetes Downward API podinfo labels file in logging records.
Package otel contains options for including OpenTelemetry baggage and tracing in logging records.
Package otel contains options for including OpenTelemetry baggage and tracing in logging records.

Jump to

Keyboard shortcuts

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