monitoring

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: 18 Imported by: 0

README

Appkit monitoring

This package provides a basic interface for monitoring request times and other arbitrary data, and recording data into InfluxDB.

Configuration for InfluxDB

Include a field of type monitoring.InfluxMonitorConfig in your app config:

type AppConfig struct {
	// ...

	InfluxDB monitor.InfluxMonitorConfig
}

And configure this field with a value like: https://<username>:<password>@<influxDB host>/<database>.

Create an InfluxDB monitor in main.go:

if monitor, err := monitoring.NewInfluxdbMonitor(appConfig.InfluxDB, l); err != nil {
	// handle the error...
	l.Info().Log(
		"err", err,
		"msg", fmt.Sprintf("error configuring influxdb monitor: %v", err),
	)
}

Middleware

Use included middleware in your stack:

func Routes(monitor monitoring.Monitor, ...) http.Handler {
    // ...

	middleware := server.Compose(
		// ... other middleware
    	monitoring.WithMonitor(monitor),
    	// ... more middleware
    )

    // ...
}

Now request data including request path, method, HTTP response status code, request duration, and request trace ID, will be sent to your InfluxDB instance in the request measurement.

Path scrubbing

The middleware will convert any sequences of 1 or more digits into :id. Eg. GET /api/users/123/comments/456 will be tagged with path of /api/users/:id/comments/:id.

Recording other metrics

To record other metrics, eg counting subscriptions, measuring time of API calls to other services, retrieve the metric from the context with monitoring.ForceContext, and then call methods on the interface:

type Monitor interface {
	InsertRecord(measurement string, value interface{}, tags map[string]string, fields map[string]interface{}, time time.Time)
	Count(measurement string, value float64, tags map[string]string, fields map[string]interface{})
	CountError(measurement string, value float64, err error)
	CountSimple(measurement string, value float64)
}

For example, to count logins:

func Login(w http.ResponseWriter, r *http.Request) {
    monitor := monitoring.ForceContext(r.Context())
    if err := doLogin(); err == nil {
        // ... handle success case
        monitor.CountSimple("login_success", 1)
    } else {
        monitor.CountError("login_error", 1, err)
    }
}

TODO

  • Make metrics counted via the context monitor include request tags eg. request ID

  • Provide simple wrapper API for context-based metrics:

    func InsertRecord(context.Context, string, interface{}, map[string]string, time.Time)
    func Count(context.Context, measurement string, value float64, tags map[string]string)
    
  • Make path-scrubbing more flexible. Eg. scrub out product names: /products/blue-winter-coat -> /products/:product_code.

Documentation

Overview

Package monitoring is a monitor "provider" that provides a way for monitoring. It uses influxdb monitor by default.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Context

func Context(c context.Context, m Monitor) context.Context

Context installs a given Monitor in the returned context

func WithMonitor

func WithMonitor(m Monitor) func(h http.Handler) http.Handler

WithMonitor wraps the given http.Handler to: 1. instrument requests via a Monitor 2. install monitor in request context for use by later handlers

Types

type InfluxMonitorConfig

type InfluxMonitorConfig string

InfluxMonitorConfig type for configuration of Monitor that sinks to InfluxDB

type Monitor

type Monitor interface {
	InsertRecord(measurement string, value interface{}, tags map[string]string, fields map[string]interface{}, time time.Time)
	Count(measurement string, value float64, tags map[string]string, fields map[string]interface{})
	CountError(measurement string, value float64, err error)
	CountSimple(measurement string, value float64)
}

Monitor defines an interface for inserting record.

func ForceContext

func ForceContext(ctx context.Context) Monitor

ForceContext extracts a Monitor from a (possibly nil) context, or returns a NewLogMonitor using a log from the context or log.Default()

func NewInfluxdbMonitor

func NewInfluxdbMonitor(config InfluxMonitorConfig, logger log.Logger) (Monitor, func(), error)

NewInfluxdbMonitor creates new monitoring influxdb client. config URL syntax is `https://<username>:<password>@<influxDB host>/<database>?batch-write-interval=timeDuration&buffer-size=number&max-buffer-size=number&service-name=name` batch-write-interval is optional, default is 60s, valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".

exec batch write when we haven't sent data since batch-write-interval ago

buffer-size is optional, default is 5000.

if buffered size reach buffer size then exec batch write.

max-buffer-size is optional, default is 10000, it must > buffer-size,

if the batch write fails and buffered size reach max-buffer-size then clean up the buffer (mean the data is lost).

service-name is optional

if set then all points will add tag service=service-name.

The second return value is a function that will cause the batching goroutine to write buffered points, then terminate. This function will block until one attempt to flush the buffer completes (either success or failure).

The third return value will be non-nil if monitorURL is invalid or not absolute.

This function will not return error if InfluxDB is unavailable, but the returned Monitor will log errors if it cannot push metrics into InfluxDB.

func NewInfluxdbMonitorWithClient

func NewInfluxdbMonitorWithClient(config InfluxMonitorConfig, logger log.Logger, client influxdb.Client) (Monitor, func(), error)

func NewLogMonitor

func NewLogMonitor(l log.Logger) Monitor

NewLogMonitor creates Monitor that logs metrics to passed log.Logger

Jump to

Keyboard shortcuts

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