logtracing

package
v0.0.0-...-81c75b8 Latest Latest
Warning

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

Go to latest
Published: Apr 21, 2024 License: MIT Imports: 22 Imported by: 0

README

logtracing

This package is a toolkit for log-based tracing. It provides several APIs for adding traces for the application and logging them in a standard format.

Usage

Import the package

import 'github.com/theplant/appkit/logtracing'

Inside a function, you can use these three APIs to track it:

  • StartSpan(context.Context, string) to start a span
  • EndSpan(context.Context, error) to end the span, also log it in an agreed format
  • RecordPanic(context.Context) to record the panic into the span
func DoWork(ctx context.Context) err error {
	ctx, _ := logtracing.StartSpan(ctx, "<span.context>")
	defer func() { logtracing.EndSpan(ctx, err) }()
	defer RecordPanic(ctx)
}

It will create a new span, record the error, and log the span with the logger in context.

You can append key-values to an active span with AppendSpanKvs:

func DoWork(ctx context.Context) err error {
	ctx, _ := logtracing.StartSpan(ctx, "<span.context>")
	defer func() { logtracing.EndSpan(ctx, err) }()
	defer RecordPanic(ctx)

	logtracing.AppendSpanKVs(ctx,
		"service", "greeter",
	)
}

If you want to append key-values to all spans, you can append the key-values to the context with ContextWithKVs:

func DoWork(ctx context.Context) err error {
	// all the spans within this context will contain `"key": "value"`
	ctx = logtracing.ContextWithKVs(ctx, "key", "value")

	ctx, _ = logtracing.StartSpan(ctx, "test")
	defer func() { logtracing.EndSpan(ctx, err) }()
	defer RecordPanic(ctx)
}

For flexibility, the package provides the following APIs to manipulate the span directly:

  • (*span).AppendKVs(...interface{})
  • (*span).RecordError(err error)
  • (*span).RecordPanic(panic interface{}})
  • (*span).End()
  • LogSpan(ctx context, s *span)

Key-values

Common

With logtracing.StartSpan and logtracing.EndSpan, these are automatically added to the span:

  • ts
  • msg
  • trace.id
  • span.id
  • span.context
  • span.dur_ms
  • span.parent_id

If the span records an error, these key-values will be added:

  • span.err
  • span.err_type
  • span.with_err
Reference
  • span.type: This usually describes "how" the span is sent/received, what kind of underlying API or network transport is used, eg http, sql, grpc, dns, aws.<service>
  • span.role: This describes what role this span plays in an interaction with another service, eg for HTTP a client makes a request to a server. Or in a queue, a producer adds work to the queue, that is consumed by a consumer.

Data that is for specific types should use the type as a prefix when adding supplementary keys-values, For example:

  • With span.type=http, the HTTP method would be logged as http.method, the response status would be logged as http.status=200.

  • AWS S3 API calls (span.type=aws.s3), use s3 or aws.s3 as a prefix, an object used in the API call could be logged as s3.object=<object key> (or aws.s3.object=<object key>)

XMLRPC
  • span.type: xmlrpc
  • span.role: client
  • xmlrpc.method: the service method
  • http.method: post
  • http.url: the server URL
  • xmlrpc.fault_string: only exists when getting a fault error
GRPC
  • span.type: grpc
  • span.role: client or server
  • grpc.service: gRPC service name
  • grpc.method: gRPC method name
  • grpc.code: gRPC response status code

The package provides server and client interceptors to log these key-values automatically.

HTTP

For the client requests:

  • span.type: http
  • span.role: client
  • http.url: the request full URL
  • http.method: the request method
  • http.status: the response status, only exists when getting the response successfully

For the server requests:

  • span.type: http
  • span.role: server
  • http.path: the request path
  • http.method: the request method
  • http.user_agent: the request user agent
  • http.client_ip: the request client IP
  • http.status: the response status
Queue
  • span.type: queue
  • span.role: consumer or producer
Function

For internal functions:

  • span.role: internal

Export span data

You can export span data to an expected destination such as Honeycomb by registering an exporter.

  1. Implement the Exporter interface:
    type Exporter interface {
    	ExportSpan(s *SpanData)
    }
    
  2. Initialize and register your exporter:
    exporter := <your exporter>
    logtracing.RegisterExporter(exporter)
    

When you register exporters, logtracing will pass sampled spans to the exporters after logging.

Honeycomb exporter

You can use this exporter to send spans to Honeycomb. The sent events are in the same format as the logged events.

  1. Import the package:
    import github.com/theplant/appkit/logtracing/exporters/honeycomb
    
  2. Initialize the exporter:
    exporter, err := honeycomb.NewExporter(libhoney.Config{
    	WriteKey:     "mock",
    	Dataset:      "mock",
    	Transmission: mockSender,
    })
    ```
    
  3. Register the exporter:
    logtracing.RegisterExporter(expoter)
    

How to migrate from util/trace.go

  1. Use logtracing.TraceFunc to replace util.Lt
  2. Use logtracing.AppendSpanKVs to replace util.AppendKVs
  3. Use logtracing.TraceHTTPRequest to replace util.LtRequest
  4. Use logtracing.HTTPTransport to replace util.LtTransport
  5. Use logtracing.XMLRPCClientKVs to replace util.XMLRpcKVs

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrMissingValue = errors.New("(MISSING)")

Functions

func AppendSpanKVs

func AppendSpanKVs(ctx context.Context, keyvals ...interface{})

func ApplyConfig

func ApplyConfig(cfg Config)

func ContextWithKVs

func ContextWithKVs(ctx context.Context, keyvals ...interface{}) context.Context

func EndSpan

func EndSpan(ctx context.Context, err error)

func ExportSpan

func ExportSpan(s *span)

func GRPCClientKVs

func GRPCClientKVs(service, method string) []interface{}

func GRPCServerKVs

func GRPCServerKVs(service, method string) []interface{}

func HTTPClientKVs

func HTTPClientKVs(req *http.Request) []interface{}

func HTTPServerKVs

func HTTPServerKVs(req *http.Request) []interface{}

func HTTPServerResponseKVs

func HTTPServerResponseKVs(status string) []interface{}

func InternalFuncKVs

func InternalFuncKVs() []interface{}

func KVsFromContext

func KVsFromContext(ctx context.Context) []interface{}

func LogSpan

func LogSpan(ctx context.Context, s *span)

func QueueConsumerKVs

func QueueConsumerKVs() []interface{}

func QueueProducerKVs

func QueueProducerKVs() []interface{}

func RecordPanic

func RecordPanic(ctx context.Context)

If this method is called while panicing, function will record the panic into the span, and the panic is continued. 1. The function should be called before `EndSpan(ctx context.Context, err error)` or `(*span).End()`. 2. The function call should be deferred.

func RegisterExporter

func RegisterExporter(e Exporter)

RegisterExporter adds to the list of Exporters that will receive sampled trace spans.

func SpanFromContext

func SpanFromContext(ctx context.Context) *span

func StartSpan

func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *span)

func StreamClientInterceptor

func StreamClientInterceptor() grpc.StreamClientInterceptor

func StreamServerInterceptor

func StreamServerInterceptor() grpc.StreamServerInterceptor

func TraceFunc

func TraceFunc(ctx context.Context, name string, f func(context.Context) error) (err error)

func TraceHTTPRequest

func TraceHTTPRequest(do func(*http.Request) (*http.Response, error), baseName string, req *http.Request) (resp *http.Response, err error)

func UnaryClientInterceptor

func UnaryClientInterceptor() grpc.UnaryClientInterceptor

func UnaryServerInterceptor

func UnaryServerInterceptor() grpc.UnaryServerInterceptor

func UnregisterExporter

func UnregisterExporter(e Exporter)

UnregisterExporter removes from the list of Exporters the Exporter that was registered with the given name.

func XMLRPCClientKVs

func XMLRPCClientKVs(method, serverURL string, err error) []interface{}

Types

type Config

type Config struct {
	DefaultSampler Sampler
	IDGenerator    IDGenerator
}

Config represents the global tracing configuration.

type Exporter

type Exporter interface {
	ExportSpan(s *SpanData)
}

type FaultError

type FaultError struct {
	Code   string
	String string
}

func AssertFaultError

func AssertFaultError(err error) (*FaultError, bool)

type HTTPTransport

type HTTPTransport struct {
	BaseName     string
	RoundTripper http.RoundTripper
}

func (*HTTPTransport) RoundTrip

func (tr *HTTPTransport) RoundTrip(req *http.Request) (resp *http.Response, err error)

type IDGenerator

type IDGenerator interface {
	NewTraceID() TraceID
	NewSpanID() SpanID
}

type Sampler

type Sampler func(SamplingParameters) bool

func AlwaysSample

func AlwaysSample() Sampler

func NeverSample

func NeverSample() Sampler

func ProbabilitySampler

func ProbabilitySampler(fraction float64) Sampler

type SamplingParameters

type SamplingParameters struct {
	ParentMeta spanMeta
	TraceID    TraceID
	SpanID     SpanID
	Name       string
}

type SpanData

type SpanData struct {
	ParentSpanID SpanID

	TraceID
	SpanID
	Name      string
	IsSampled bool

	StartTime time.Time
	EndTime   time.Time

	Err   error
	Panic interface{}

	Keyvals []interface{}
}

SpanData contains all the information collected by a Span.

type SpanID

type SpanID [8]byte

SpanID is a unique identity of a span in a trace.

func (SpanID) IsValid

func (s SpanID) IsValid() bool

IsValid checks whether the SpanID is valid. A valid SpanID does not consist of zeros only.

func (SpanID) MarshalJSON

func (s SpanID) MarshalJSON() ([]byte, error)

MarshalJSON implements a custom marshal function to encode SpanID as a hex string.

func (SpanID) String

func (s SpanID) String() string

String returns the hex string representation form of a SpanID

type StartOption

type StartOption func(*StartOptions)

func WithSampler

func WithSampler(sampler Sampler) StartOption

func WithStartTime

func WithStartTime(t time.Time) StartOption

type StartOptions

type StartOptions struct {
	Sampler   Sampler
	StartTime time.Time
}

type TraceID

type TraceID [16]byte

TraceID is a unique identity of a trace. nolint:revive // revive complains about stutter of `trace.TraceID`.

func (TraceID) IsValid

func (t TraceID) IsValid() bool

IsValid checks whether the trace TraceID is valid. A valid trace ID does not consist of zeros only.

func (TraceID) MarshalJSON

func (t TraceID) MarshalJSON() ([]byte, error)

MarshalJSON implements a custom marshal function to encode TraceID as a hex string.

func (TraceID) String

func (t TraceID) String() string

String returns the hex string representation form of a TraceID

Directories

Path Synopsis
exporters

Jump to

Keyboard shortcuts

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