srv

package module
v0.0.0-...-cf8a7de Latest Latest
Warning

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

Go to latest
Published: Sep 21, 2023 License: MIT Imports: 36 Imported by: 0

README

srv - a way to do microservices

Health

Startup

srv provides a /startupz route on :8081 that will become active the instant srv.New is called. It will respond with 503 Service Unavailable until srv.Start() has completed instrumentation and starting any jobs. Thereafter it will respond with 200 OK.

Readiness

srv provides a very basic readiness handler at /readyz that will start responding after the call to srv.Start(). The route simply responds with 200 and OK as the response body to every request. It will never explicitly fail, with the reasoning being that if your service is so busy that it can't respond to such a simple request in whatever timeout you deem appropriate then it isn't "ready".

Readiness handlers can cause

TODO

Documentation

Index

Constants

View Source
const (
	LevelDebug = LogLevel(slog.LevelDebug)
	LevelInfo  = LogLevel(slog.LevelInfo)
	LevelWarn  = LogLevel(slog.LevelWarn)
	LevelError = LogLevel(slog.LevelError)
)

Logging Levels

View Source
const (
	// ShowLocation will attach the filename and line number to the logging message
	LogLocation = 1 << iota
	// FullLocation will include the full path of the filename where the logging
	// message ocurred.
	LogFullLocation
	// NoMetrics will prevent the logger from tracking error, warn and info
	// message counts.
	NoMetrics
)
View Source
const (
	CounterMetricSuffix = `_total`
	TimerMetricSuffix   = `_duration_seconds`
)

Variables

This section is empty.

Functions

func AddHealthCheck

func AddHealthCheck(ID string, checkFn JobFn, options ...HealthCheckOption)

AddHealthCheck adds an asynchronous self-reporting health check job whose status will be reported at the /livez route. Checks will be considered failed if they return err != nil or if they take longer than the configured timeout. Checks may have an optional maximum number of failures, allowing them to remain healthy until they fail N number of times in a row.

func AddJob

func AddJob(jobs ...JobFn)

AddJob adds a function to be run at startup as an asynchronous task or as your main loop. The return value is treated as indicating success (nil) or failure (a non-nil error value). A return value of nil is assumed to be the successful completion of a short-running job. If any function returns a non-nil error value, the service will cancel all outstanding contexts, shut down, and will exit with a failure code. If all jobs return nil, the service will shut down, but exit with code 0, assuming success. As long as at least one function is outstanding and no jobs have failed, the service will continue to run.

func AddJobFn

func AddJobFn[T any](fn func(context.Context, *Logger, T) error, arg T)

AddJobFn is the Fn version of AddJob. Allows an edditional argument for injecting dependencies and such.

func AddShutdownHandler

func AddShutdownHandler(handlers ...JobFn)

AddShutdownHandler adds a job that will be run when the service is shut down. Shutdown handlers will be run synchronously, in the order they are defined. If a shutdown handler panics, the rest of the handlers will be skipped.

func Declare

func Declare(serviceInfo ServiceInfo)

func Fatal

func Fatal(msg string, attrs ...any)

Fatal logs a structured message at the error level with the root logger and exits the program immediately.

NOTE: This bypasses any graceful shutdown handling, so its use outside of main() is highly discouraged.

func Fatalf

func Fatalf(format string, args ...any)

Fatalf logs a formatted message at the error level with the root logger and exits the program immediately.

NOTE: This bypasses any graceful shutdown handling, so its use outside of main() is highly discouraged.

func FlagBool

func FlagBool(name string, defaultValue bool, usage string) *bool

FlagBool adds a boolean flag to the configuration.

Returns a *bool that will be set when ParseFlags is called.

func FlagBoolVar

func FlagBoolVar(ptr *bool, name string, defaultValue bool, usage string)

FlagBoolVar adds a boolean flag to the configuration.

Takes a *bool that will be overwritten when ParseFlags is called.

func FlagInt

func FlagInt(name string, defaultValue int, usage string) *int

FlagInt adds an integer flag to the configuration.

Returns an *int that will be set when ParseFlags is called.

func FlagIntVar

func FlagIntVar(ptr *int, name string, defaultValue int, usage string)

FlagIntVar adds an integer flag to the configuration

Takes an *int that will be overwritten when ParseFlags is called.

func FlagString

func FlagString(name string, defaultValue string, usage string) *string

FlagString adds a string flag to the configuration.

Returns a *string that will be set when ParseFlags is called.

func FlagStringList

func FlagStringList(name string, usage string) *[]string

FlagStringList is a flag returning a pointer to a string slice that will be filled with every occurrance of the named flag on the commandline

func FlagStringListVar

func FlagStringListVar(ptr *[]string, name string, usage string)

FlagStringListVar adds a string list to the configuration. takes a string slice pointer that will be overwritten and filled with every occurrance of the named flag on the commandline.

func FlagStringVar

func FlagStringVar(ptr *string, name string, defaultValue string, usage string)

FlagStringVar adds a string flag to the configuration.

Takes a *string that will be overwritten when ParseFlags is called.

func FlagsValue

func FlagsValue[T any](ptr *T, provider FlagsProvider[T])

FlagsValue takes a pointer to a value of type T, provided by the given FlagsProvider. The FlagsProvider will then add the set of flags necessary to instantiate the value to your configuration, and initialize the value when ParseFlags is called.

Example:

var dbClient *database.Client
FlagsValue(&dbClient, database.ClientFlagsProvider)
srv.ParseFlags()

//dbClient is now initialized.
dbClient.Connect(dbURL)

func NewCounter

func NewCounter(name, help string, labelNames ...string) metrics.Counter

NewCounter returns a Prometheus Counter.

NAMING: all counters will be automatically suffixed with _total if not already. NOTE: value cardinality must match label cardinality to use .With().

func NewGauge

func NewGauge(name, help string, labelNames ...string) metrics.Gauge

NewGauge returns a Prometheus Gauge.

NAMING: Gauges should not be suffixed with "_total". NOTE: value cardinality must match label cardinality to use .With().

func NewHistogram

func NewHistogram(name, help string, buckets []float64, labelNames ...string) metrics.Histogram

NewHistogram returns a Prometheus Histogram.

NOTE: value cardinality must match label cardinality to use .With().

func NewLogger

func NewLogger(name string, level LogLevel, flags int) *log.Logger

NewLogger creates a *log.Logger that will attach a "logger" label to its output and metrics with the value of the provided name. If the consumer takes a *slog.Logger, you can call the [Logger.Slogger] method to get it. Loggers will be tracked by srv, allowing for dynamic level modification at runtime via the `/loglevel route`, so multiple subloggers cannot have the same name.

func NewSummary

func NewSummary(name, help string, labelNames ...string) metrics.Histogram

NewSummary returns a Prometheus Summary.

NOTE: value cardinality must match label cardinality to use .With().

func ParseFlags

func ParseFlags() []string

ParseFlags parses all command-line flags and returns the remaining arguments.

func Registry

func Registry() prometheus.Registerer

Registry returns the service prometheus registry for plugins/packages that can use it.

func Serve

func Serve()

Serve serves all endpoints and begins running all tasks. It will block until all tasks have completed or until the service is shut down.

Types

type FlagsProvider

type FlagsProvider[T any] func() (*ff.CoreFlags, func() (T, error))

FlagsProvider is a function providing both a set of flags and a function that will initialize the value of a concrete type from the values those flags provide.

Example:

package database

type Client struct{/*...*/}

func NewClient(url string)(*Client, error){
	/*...*/
}

func ClientFlagsProvider()(*ff.CoreFlags, func()(*Client, error){
	flags := ff.NewFlags("database client")
	dbURL := flags.StringLong("dburl", "", "database URL")
	return flags, func()(*Client, error){
		return NewClient(dbURL)
	}
})

type HealthCheckOption

type HealthCheckOption func(hc *health.HealthCheck) error

func Interval

func Interval(interval time.Duration) HealthCheckOption

Interval sets the health check interval. The job will be scheduled at this interval. Must be greater than the check timeout. Default: 30 seconds.

func MaxFailures

func MaxFailures(maxFailures int) HealthCheckOption

MaxFailures sets the number of acceptable failures before the health check is considered failed. If the check returns nil (success) before this number is reached, the counter will be reset, and the check will remain healthy. Default: 0 (no failures allowed)

func Timeout

func Timeout(timeout time.Duration) HealthCheckOption

Timeout sets the health check timeout. If the job takes longer than this to run, it will be cancelled and considered to have failed. Must be less than the check interval. Default: 10 seconds

type JobFn

type JobFn func(context.Context, *Logger) error

JobFn is a job to be run at startup. The service will run until either a single job has registered an error or until all jobs have completed successfully. A logger will be automatically supplied to your function for logging messages.

func Fn

func Fn[T any](fn func(context.Context, *Logger, T) error, arg T) JobFn

Fn creates a JobFn from a function that takes a context and a *Logger along with an additional argument of any type. This argument is passed as the second argument to Fn.

Example:

func myjob(ctx context.Context, log *srv.Logger input *MyType) error {
  // ...
}

srv.AddJob(srv.Fn(myjob, &MyType{/*...*/}))

func Job

func Job[T any](fn func(context.Context, *Logger, T) error, arg T) JobFn

Job creates a JobFn from a function that takes a context and a *Logger along with an additional argument of any type.

Example:

func myjobFn(ctx context.Context, log *srv.Logger input *MyType) error {
  // ...
}

srv.Start(srv.Job(myjobFn, &MyType{/*...*/}))

type LogLevel

type LogLevel = slog.Level

LogLevel represents a logging level. Aliased from slog.

type Logger

type Logger = log.Logger

Logger is an alias to the log.Logger type, so that you don't need to import the package to define your job functions

type ServiceInfo

type ServiceInfo struct {
	// Name is the name of the service. (REQUIRED)
	Name string
	// System is a name to collate the logs of the service with other, related services. (OPTIONAL)
	System string
	// Version is a valid Semantic Versioning version string. (OPTIONAL)
	Version string
	// About is any extra string data you'd like printed in the output of --help
	About string
}

ServiceInfo is a description for your service. Name is the only required field, and must be of the form

^[a-zA-Z][a-zA-Z0-9._-]*$

System is optional, but can be used to group related services together in an aggregator. It must be of the same form as Name. Version, if provided, is required to be a valid semantic version following the format detailed in the Semantic Versioning 2.0.0 Specification. If you would like to pin the version number at buildtime, please see the docs for the buildinfo package. About is an optional field that will be printed if the service is called with --help.

func (ServiceInfo) LogValue

func (i ServiceInfo) LogValue() slog.Value

LogValue allows the service description to be logged canonically in slog output.

type Timer

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

Timer is a wrapped histogram tailored to measure durations for latency tracking.

Calling *Timer.Span will return a function that, when called, will create an observation of fractional seconds elapsed since the call to Span. This is particularly useful in conjunction with defer to measure the duration of a function call.`

Example:

	 requestTimer := srv.NewTimer(
		"my_route_seconds",
		"time in seconds to run my_route",
     []time.Duration{150*time.Millisecond, 300*time.Millisecond, 500*time.Millisecond, time.Second},
		"method")

		userRoute := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
			defer requestTimer.Span()()
			// route handler code
		})

Following prometheus convention, durations are measured in seconds.

NOTE: value cardinality must match label cardinality to use .With().

func NewTimer

func NewTimer(name, help string, buckets []time.Duration, labelNames ...string) *Timer

NewTimer returns a duration and latency observation metric backed by a histogram. Following Prometheus convention of measuring in base units, all Timers are measured in fractional seconds.

NAMING: Timers will automatically be suffixed with `_duration_seconds`, so there is no need to supply this.

func (*Timer) Span

func (t *Timer) Span(labelValues ...string) TimerSpan

Span returns a function that, when called, will me

type TimerSpan

type TimerSpan func()

TimerSpan is the measurement function returned from *Timer.Span, when called, it will perform the measurement

Directories

Path Synopsis
examples
internal
loghandler/instrumentation
// package instrumentation provides a Handler for incrementing the master error count metric, code // location logging, and advanced error annotation.
// package instrumentation provides a Handler for incrementing the master error count metric, code // location logging, and advanced error annotation.
ui

Jump to

Keyboard shortcuts

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