runhttp

package module
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Apr 26, 2023 License: Apache-2.0 Imports: 13 Imported by: 23

README

runhttp - Prepackaged Runtime Helper For HTTP

GoDoc Build Status codecov.io

Overview

This project is a tool bundle for running an HTTP service written in go. It comes with an opinionated choice of logger, metrics client, and configuration parsing. The benefits are a suite of server metrics built in, a configurable and pluggable shutdown signaling system, and support for restarting the server without exiting the running process.

Quick Start

package main

import (
    "net/http"
    "github.com/asecurityteam/runhttp"
)

func main() {
    // The handler is anything the runtime should serve. This may be a simple
    // handler like this one or any of the many mux/router projects that exist
    // in the go ecosystem.
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
        runhttp.LoggerFromContext(r.Context()) // Get a logger
        runtthp.StatFromContext(r.Context()) // Get a metrics client
    })

    // Create any implementation of the settings.Source interface. Here we
    // use the environment variable source.
    source, err := settings.NewEnvSource(os.Environ())
	if err != nil {
		panic(err.Error())
	}

    // Load the runtime using the Source and Handler.
	rt, err := runhttp.New(context.Background(), source, handler)
	if err != nil {
		panic(err.Error())
	}

    // Run the HTTP server.
    if err := rt.Run(); err != nil {
		panic(err.Error())
	}
}

Details

Configuration

We use our settings project to manage configuration. This makes it possible to load configuration values from environment variables, JSON files, or YAML files. Other configurations sources are possible by implementing the settings.Source interface defined in the settings project.

YAML

If using a YAML file then a configuration would look like:

runtime:
  signals:
    # ([]string) Which signal handlers are installed. Choices are OS.
    installed:
      - "OS"
    os:
      # ([]int) Which signals to listen for.
      signals:
        - 15
        - 2
  stats:
    # (string) Destination stream of the stats. One of NULLSTAT, DATADOG.
    output: "DATADOG"
    datadog:
      # (int) Max packet size to send.
      packetsize: 32768
      # ([]string) Any static tags for all metrics.
      tags:
      # (time.Duration) Frequencing of sending metrics to listener.
      flushinterval: "10s"
      # (string) Listener address to use when sending metrics.
      address: "localhost:8125"
  logger:
    # (string) Destination stream of the logs. One of STDOUT, NULL.
    output: "STDOUT"
    # (string) The minimum level of logs to emit. One of DEBUG, INFO, WARN, ERROR.
    level: "INFO"
  connstate:
    # (time.Duration) Interval on which gauges are reported.
    reportinterval: "5s"
    # (string) Name of the counter metric tracking hijacked clients.
    hijackedcounter: "http.server.connstate.hijacked"
    # (string) Name of the counter metric tracking closed clients.
    closedcounter: "http.server.connstate.closed"
    # (string) Name of the gauge metric tracking idle clients.
    idlegauge: "http.server.connstate.idle.gauge"
    # (string) Name of the counter metric tracking idle clients.
    idlecounter: "http.server.connstate.idle"
    # (string) Name of the gauge metric tracking active clients.
    activegauge: "http.server.connstate.active.gauge"
    # (string) Name of the counter metric tracking active clients.
    activecounter: "http.server.connstate.active"
    # (string) Name of the gauge metric tracking new clients.
    newgauge: "http.server.connstate.new.gauge"
    # (string) Name of the counter metric tracking new clients.
    newcounter: "http.server.connstate.new"
  expvar:
    # (string) Name of the metric tracking allocated bytes
    alloc: "go_expvar.memstats.alloc"
    # (string) Name of the metric tracking number of frees
    frees: "go_expvar.memstats.frees"
    # (string) Name of the metric tracking allocated bytes
    heapalloc: "go_expvar.memstats.heap_alloc"
    # (string) Name of the metric tracking bytes in unused spans
    heapidle: "go_expvar.memstats.heap_idle"
    # (string) Name of the metric tracking bytes in in-use spans
    heapinuse: "go_expvar.memstats.heap_inuse"
    # (string) Name of the metric tracking total number of object allocated"
    heapobject: "go_expvar.memstats.heap_objects"
    # (string) Name of the metric tracking bytes realeased to the OS
    heaprealeased: "go_expvar.memstats.heap_released"
    # (string) Name of the metric tracking bytes obtained from the system
    heapstats: "go_expvar.memstats.heap_sys"
    # (string) Name of the metric tracking number of pointer lookups
    lookups: "go_expvar.memstats.lookups"
    # (string) Name of the metric tracking number of mallocs
    mallocs: "go_expvar.memstats.mallocs"
    # (string) Name of the metric tracking number of garbage collections
    numgc: "go_expvar.memstats.num_gc"
    # (string) Name of the metric tracking duration of GC pauses
    pausens: "go_expvar.memstats.pause_ns"
    # (string) Name of the metric tracking total GC pause duration over lifetime process
    pausetotalns: "go_expvar.memstats.pause_total_ns"
    # (string) Name of the metric tracking allocated bytes (even if freed)
    totalalloc: "go_expvar.memstats.total_alloc"
    # (string) Name of the metric tracking number of active go routines
    goroutinesexists: "go_expvar.goroutines.exists"
    # (time.Duration) Interval on which metrics are reported
    reportinterval: "5s"
  httpserver:
    # (string) The listening address of the server.
    address: ":8080"

ENV

If using the environment variable loader then a configuration would look like:

# (string) The listening address of the server.
RUNTIME_HTTPSERVER_ADDRESS=":8080"
# (time.Duration) Interval on which gauges are reported.
RUNTIME_CONNSTATE_REPORTINTERVAL="5s"
# (string) Name of the counter metric tracking hijacked clients.
RUNTIME_CONNSTATE_HIJACKEDCOUNTER="http.server.connstate.hijacked"
# (string) Name of the counter metric tracking closed clients.
RUNTIME_CONNSTATE_CLOSEDCOUNTER="http.server.connstate.closed"
# (string) Name of the gauge metric tracking idle clients.
RUNTIME_CONNSTATE_IDLEGAUGE="http.server.connstate.idle.gauge"
# (string) Name of the counter metric tracking idle clients.
RUNTIME_CONNSTATE_IDLECOUNTER="http.server.connstate.idle"
# (string) Name of the gauge metric tracking active clients.
RUNTIME_CONNSTATE_ACTIVEGAUGE="http.server.connstate.active.gauge"
# (string) Name of the counter metric tracking active clients.
RUNTIME_CONNSTATE_ACTIVECOUNTER="http.server.connstate.active"
# (string) Name of the gauge metric tracking new clients.
RUNTIME_CONNSTATE_NEWGAUGE="http.server.connstate.new.gauge"
# (string) Name of the counter metric tracking new clients.
RUNTIME_CONNSTATE_NEWCOUNTER="http.server.connstate.new"
# (string) Name of the metric tracking allocated bytes
RUNTIME_EXPVAR_ALLOC: "go_expvar.memstats.alloc"
# (string) Name of the metric tracking number of frees
RUNTIME_EXPVAR_FREES: "go_expvar.memstats.frees"
# (string) Name of the metric tracking allocated bytes
RUNTIME_EXPVAR_HEAPALLOC: "go_expvar.memstats.heap_alloc"
# (string) Name of the metric tracking bytes in unused spans
RUNTIME_EXPVAR_HEAPIDLE: "go_expvar.memstats.heap_idle"
# (string) Name of the metric tracking bytes in in-use spans
RUNTIME_EXPVAR_HEAPINUSE: "go_expvar.memstats.heap_inuse"
# (string) Name of the metric tracking total number of object allocated"
RUNTIME_EXPVAR_HEAPOBJECT: "go_expvar.memstats.heap_objects"
# (string) Name of the metric tracking bytes realeased to the OS
RUNTIME_EXPVAR_HEAPREALEASED: "go_expvar.memstats.heap_released"
# (string) Name of the metric tracking bytes obtained from the system
RUNTIME_EXPVAR_HEAPSTATS: "go_expvar.memstats.heap_sys"
# (string) Name of the metric tracking number of pointer lookups
RUNTIME_EXPVAR_LOOKUPS: "go_expvar.memstats.lookups"
# (string) Name of the metric tracking number of mallocs
RUNTIME_EXPVAR_MALLOCS: "go_expvar.memstats.mallocs"
# (string) Name of the metric tracking number of garbage collections
RUNTIME_EXPVAR_NUMGC: "go_expvar.memstats.num_gc"
# (string) Name of the metric tracking duration of GC pauses
RUNTIME_EXPVAR_PAUSENS: "go_expvar.memstats.pause_ns"
# (string) Name of the metric tracking total GC pause duration over lifetime process
RUNTIME_EXPVAR_PAUSETOTALNS: "go_expvar.memstats.pause_total_ns"
# (string) Name of the metric tracking allocated bytes (even if freed)
RUNTIME_EXPVAR_TOTALALLOC: "go_expvar.memstats.total_alloc"
# (string) Name of the metric tracking number of active go routines
RUNTIME_EXPVAR_GOROUTINESEXISTS: "go_expvar.goroutines.exists"
# (time.Duration) Interval on which metrics are reported
RUNTIME_EXPVAR_REPORTINTERVAL: "5s"
# (string) Destination stream of the logs. One of STDOUT, NULL.
RUNTIME_LOGGER_OUTPUT="STDOUT"
# (string) The minimum level of logs to emit. One of DEBUG, INFO, WARN, ERROR.
RUNTIME_LOGGER_LEVEL="INFO"
# (string) Destination stream of the stats. One of NULLSTAT, DATADOG.
RUNTIME_STATS_OUTPUT="DATADOG"
# (int) Max packet size to send.
RUNTIME_STATS_DATADOG_PACKETSIZE="32768"
# ([]string) Any static tags for all metrics.
RUNTIME_STATS_DATADOG_TAGS=""
# (time.Duration) Frequencing of sending metrics to listener.
RUNTIME_STATS_DATADOG_FLUSHINTERVAL="10s"
# (string) Listener address to use when sending metrics.
RUNTIME_STATS_DATADOG_ADDRESS="localhost:8125"
# ([]string) Which signal handlers are installed. Choices are OS.
RUNTIME_SIGNALS_INSTALLED="OS"
# ([]int) Which signals to listen for.
RUNTIME_SIGNALS_OS_SIGNALS="15 2"

Logging

This project will install a logevent instance in the context. From within an HTTP handler the logger should be accessed using runhttp.LoggerFromContext(r.Context()).

Metrics

This project will install an xstats instance in the context. Custom metrics may be emitted by extracting the client using runhttp.StatFromContext(r.Context()).

In addition, the server will emit counters for new, active, idle, closed, and hijacked connections. Note that hijacked in this case refers to a Go behavior defined here. The server emits gauges on an interval for new, active, and idle connections.

Go runtime metrics are also emitted. These values are extracted on a specified polling interval from the runtime package. The table here illustrates how we expect to see these values as metrics.

Status

This project is in incubation which means we are not yet operating this tool in production and the interfaces are subject to change.

Contributing

Building And Testing

We publish a docker image called SDCLI that bundles all of our build dependencies. It is used by the included Makefile to help make building and testing a bit easier. The following actions are available through the Makefile:

  • make dep

    Install the project dependencies into a vendor directory

  • make lint

    Run our static analysis suite

  • make test

    Run unit tests and generate a coverage artifact

  • make integration

    Run integration tests and generate a coverage artifact

  • make coverage

    Report the combined coverage for unit and integration tests

License

This project is licensed under Apache 2.0. See LICENSE.txt for details.

Contributing Agreement

Atlassian requires signing a contributor's agreement before we can accept a patch. If you are an individual you can fill out the individual CLA. If you are contributing on behalf of your company then please fill out the corporate CLA.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var LoggerFromContext = logevent.FromContext

LoggerFromContext is the concrete implementation of LogFn that should be used at runtime.

View Source
var StatFromContext = xstats.FromContext

StatFromContext is the concrete implementation of StatFn that should be used at runtime.

Functions

func NewDefaultRouter added in v0.4.0

func NewDefaultRouter(conf *RouterConfig) *chi.Mux

NewDefaultRouter generates a mux. This version returns a mux from the chi project as a convenience for cases where custom middleware or additional routes need to be configured.

Types

type Component

type Component struct {
	HTTP      *HTTPComponent
	Connstate *connstate.Component
	Expvar    *expvar.Component
	Logger    *log.Component
	Stats     *stat.Component
	Signal    *signals.Component
	Handler   http.Handler
}

Component implements the settings.Component interface for an HTTP runtime.

func NewComponent

func NewComponent() *Component

NewComponent populates the component with some default values.

func (*Component) New

func (c *Component) New(ctx context.Context, conf *Config) (*Runtime, error)

New produces a configured runtime.

func (*Component) Settings

func (c *Component) Settings() *Config

Settings generates a configuration object with all defaults set.

func (*Component) WithHandler

func (c *Component) WithHandler(h http.Handler) *Component

WithHandler returns a copy of the component bound to the given handler.

type Config

type Config struct {
	HTTP      *HTTPConfig
	ConnState *connstate.Config
	Expvar    *expvar.Config
	Logger    *log.Config
	Stats     *stat.Config
	Signal    *signals.Config
}

Config is the top-level configuration container for a runtime.

func (*Config) Name

func (*Config) Name() string

Name returns the configuration root as it would appear in a config file.

type HTTPComponent

type HTTPComponent struct{}

HTTPComponent implements the settings.Component interface for the HTTP server.

func (*HTTPComponent) New

New produces a ServerFn bound to the given configuration.

func (*HTTPComponent) Settings

func (*HTTPComponent) Settings() *HTTPConfig

Settings returns a configuration with all defaults set.

type HTTPConfig

type HTTPConfig struct {
	Address string `description:"The listening address of the server."`
}

HTTPConfig is the container for HTTP server configuration settings.

func (*HTTPConfig) Description

func (*HTTPConfig) Description() string

Description returns the help information for the configuration root.

func (*HTTPConfig) Name

func (*HTTPConfig) Name() string

Name returns the configuration root as it would appear in a config file.

type HealthCheckHandler added in v0.4.0

type HealthCheckHandler struct {
}

HealthCheckHandler responds with a 200

func (*HealthCheckHandler) Handle added in v0.4.0

Handle responds with a 200 by default

type LogFn

type LogFn func(context.Context) Logger

LogFn is the type that should be accepted by components that intend to log content using the context logger.

type Logger

type Logger = logevent.Logger

Logger is the project logging client interface. It is currently an alias to the logevent project.

type RouterConfig added in v0.4.0

type RouterConfig struct {
}

RouterConfig is used as a simple default for NewDefaultRouter

type Runtime

type Runtime struct {
	Logger    Logger
	Stats     Stat
	ConnState *connstate.ConnState
	Expvar    *expvar.Expvar
	Exit      signals.Signal
	Server    *http.Server
	Handler   http.Handler
}

Runtime is the container for a restarting HTTP service. It will inject the given Logger and Stat into each request context, exit the Run method on each signal received from the output of the SignalFn, and use the ServerFn to regenerate a working server on subsequent Run calls.

func New

New uses the given source to generate a configured Runtime instace.

func (*Runtime) Run

func (r *Runtime) Run() error

Run the server until a signal is received.

type ServerFn

type ServerFn func() *http.Server

ServerFn is a constructor for *http.Server instances that will be hosted by the runtime.

type SignalFn

type SignalFn func() chan error

SignalFn is a constructor for a shutdown signal. Signals are expected to be channels that emit an error that may be nil if the signal is expected.

type Stat

type Stat = xstats.XStater

Stat is the project metrics client interface. it is currently an alias for xstats.XStater.

type StatFn

type StatFn func(context.Context) Stat

StatFn is the type that should be accepted by components that intend to emit custom metrics using the context stat client.

Jump to

Keyboard shortcuts

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