app

package module
v1.0.3 Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2019 License: MIT Imports: 19 Imported by: 3

README

Go App Build Status Coverage

A library to provide application level context, config reloading and log configuration. This is a companion to golangs context. It also tries to provide an extensible way for adding log hooks without requiring to download all of github.

This package is one of those tools you won't always need, but when you need it you'll know you need it.

Depends on

Includes

Config providers

By default the the application will look for config files in order of precedence:

  • $HOME/.config/$APP_NAME
  • /etc/$APP_NAME
  • etc
  • $CWD

You can customize those search paths through setting the environment variable: CONFIG_PATH eg. export CONFIG_PATH=/etc/my-app:etc

For the remote config providers you need to set a URL for the remote provider. You can optionally set a keyring, when present the remote configuration is expected to be encrypted with the public key of the gpg keyring.

To configure the url you need to set the CONFIG_REMOTE_URL environment variable:

export CONFIG_REMOTE_URL="etcd://localhost:2379/[app-name]/config.[type]"
export CONFIG_REMOTE_URL="consul://localhost:8500/[app-name]/config.[type]"

The extension of the file path is used to determine the content type for the key.

When you make a change to the config in the remote provider or in the local file the system will reload the loggers, and trigger the appropriate hook of registered modules.

Tracer

Using the tracer requires that you put a line a the top of a method:

var tracer = NewTracer("", nil, nil)

func TraceThis() {
  defer tracer.Trace()()

  // do work here
}

func FunctionWithUglyName() {
  defer tracer.Trace("PrettyName")()

  // do work here
}

You will then be able to get information about timings for methods. When you don't specify a key, the package will walk the stack to find out the method name you want to trace. If you think this is dirty, you can just pass a name to the trace method which will make you not incur that cost.

When used with the github.com/alexwbaule/middlewares package you can get a JSON document with the report from $baseurl/audit/metrics.

Modular initialization

Implements a very simple application context that does allows for modular initialization with a deterministic init order.

A module has a simple 4 phase lifecycle: Init, Start, Reload and Stop. You can enable or disable a feature in the config. This hooks into the watching infrastructure, so you can also enable or disable modules by just editing config or changing a remote value.

Name Description
Init Called on initial creation of the module
Start Called when the module is started, or enabled at runtime
Reload Called when the config has changed and the module needs to reconfigure itself
Stop Called when the module is stopped, or disabled at runtime

Each module is identified by a unique name, this defaults to its package name,

Usage

To use it, a package that serves as a module needs to export a method or variable that implements the Module interface.

package orders

import "github.com/alexwbaule/go-app"

var Module = app.MakeModule(
  app.Init(func(app app.Application) error {
    orders := new(ordersService)
    app.Set("ordersService", orders)
    orders.app = app
    return nil
  }),
  app.Reload(func(app app.Application) error {
    // you can reconfigure the services that belong to this module here
    return nil
  })
)

type Order struct {
  ID      int64
  Product int64
}

type odersService struct {
  app app.Application
}

func (o *ordersService) Create(o *Order) error {
  var db OrdersStore
  o.app.Get("ordersDb", &db)
  return db.Save(o)
}

In the main package you would then write a main function that could look like this:

func main() {
  app := app.New("")
  app.Add(orders.Module)

  if err := app.Init(); err != nil {
    app.Logger().Fatalln(err)
  }

  app.Logger().Infoln("application initialized, starting...")

  if err := app.Start(); err != nil {
    app.Logger().Fatalln(err)
  }

  app.Logger().Infoln("application initialized, starting...")
  // do a blocking operation here, like run a http server

  if err := app.Stop(); err != nil {
    app.Logger().Fatalln(err)
  }
}

Logger Configuration

The configuration can be expressed in JSON, YAML, TOML or HCL.

example:

logging {
  root {
    level = "debug"
    hooks = [
      { name = "journald" }
    ]

    child1 {
      level = "info"
      hooks = [
        {
          name = "file"
          path = "./app.log"
        },
        {
          name     = "syslog"
          network  = "udp"
          host     = "localhost:514"
          priority = "info"
        }
      ]
    }
  }

  alerts {
    level  = "error"
    writer = "stderr"
  }
}

or the more concise yaml:

logging:
  root:
    level: Debug
    hooks:
      - name: journald
    writer: stderr
    child1:
      level: Info
      hooks:
        - name: file
          path: ./app.log
        - name: syslog
          network: udp
          host: localhost:514
          priority: info
  alerts:
    level: error
    writer: stderr

Documentation

Overview

Package app provides an application level context

This provides you with a logger, a tracer and a viper config.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrModuleUnknown returned when no module can be found for the specified key
	ErrModuleUnknown error

	// Version of the application
	Version string
)

Functions

This section is empty.

Types

type Application

type Application interface {
	// Add modules to the application context
	Add(...Module) error

	// Get the module at the specified key, thread-safe
	Get(Key) interface{}

	// Get the module at the specified key, thread-safe
	GetOK(Key) (interface{}, bool)

	// Set the module at the specified key, this should be safe across multiple threads
	Set(Key, interface{}) error

	// Logger gets the root logger for this application
	Logger() logrus.FieldLogger

	// NewLogger creates a new named logger for this application
	NewLogger(string, logrus.Fields) logrus.FieldLogger

	// Tracer returns the root
	Tracer() tracing.Tracer

	// Config returns the viper config for this application
	Config() *viper.Viper

	// Info returns the app info object for this application
	Info() cjm.AppInfo

	// Init the application and its modules with the config.
	Init() error

	// Start the application an its enabled modules
	Start() error

	// Stop the application an its enabled modules
	Stop() error
}

Application is an application level context package It can be used as a kind of dependency injection container

func New

func New(nme string) (Application, error)

New application with the specified name, at the specified basepath

func NewWithConfig

func NewWithConfig(nme string, configPath string) (Application, error)

NewWithConfig application with the specified name, with a specific config file path

type Init

type Init func(Application) error

Init is an initializer for an initalization function

func (Init) Call

func (fn Init) Call(app Application) error

Call implements the callback interface

type Key

type Key string

A Key represents a key for a module. Users of this package can define their own keys, this is just the type definition.

type LifecycleCallback

type LifecycleCallback interface {
	Call(Application) error
}

LifecycleCallback function definition

type Module

type Module interface {
	Init(Application) error
	Start(Application) error
	Stop(Application) error
	Reload(Application) error
}

A Module is a component that has a specific lifecycle

func MakeModule

func MakeModule(callbacks ...LifecycleCallback) Module

MakeModule by passing the callback functions. You can pass multiple callback functions of the same type if you want

type Reload

type Reload func(Application) error

Reload is an initalizater for a reload function

func (Reload) Call

func (fn Reload) Call(app Application) error

Call implements the callback interface

type Start

type Start func(Application) error

Start is an initializer for a start function

func (Start) Call

func (fn Start) Call(app Application) error

Call implements the callback interface

type Stop

type Stop func(Application) error

Stop is an initializer for a stop function

func (Stop) Call

func (fn Stop) Call(app Application) error

Call implements the callback interface

Directories

Path Synopsis
Package logging provides a configuration model for logrus.
Package logging provides a configuration model for logrus.
Package tracing implements a super simple tracer/profiler based on go-metrics.
Package tracing implements a super simple tracer/profiler based on go-metrics.

Jump to

Keyboard shortcuts

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