warsaw

module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Jan 29, 2021 License: MIT

README

Warsaw

pkg.go.dev

warsaw is a JSON Logger wrapper around zerolog. Also a http middleware to log HTTP requests (and more) for Go projects. The http request log follows the same format and fields as in Kiev, and you can add more as you wish.

You can find the full api reference on pkg.go.dev or GoDoc

Install

go get -u github.com/blacklane/warsaw

Usage

It log to the standard output (os.Stdout). All the outputs shown below are pretty printed for convenience, warsaw's output is not pretty printed. All examples are in examples

HTTP requests

Add the middleware to your http.Handler:

package main

import (
	"fmt"
	"net/http"

	"github.com/blacklane/warsaw/logger"
)

func pingHandler(w http.ResponseWriter, req *http.Request) {
	log := logger.Get(req.Context())

	log.Event("ping_started").Str("some_field", "value").Int("some_int", 123).Send()

	_, _ = fmt.Fprint(w, "ping")
}

func addLogMiddleware() {
	loggerMiddleware := logger.NewKievRequestLogger("MyAppName")

	http.HandleFunc("/ping", loggerMiddleware(pingHandler))
	if err := http.ListenAndServe(":8080", nil); err != nil {
		panic(err)
	}
}
{
  "level": "info",
  "application": "MyAppName",
  "entry_point": true,
  "host": "localhost",
  "path": "/ping",
  "request_depth": 0,
  "request_id": "85bec38d-1057-4ec6-88af-bed508e98594",
  "route": "ping",
  "tree_path": "T",
  "verb": "GET",
  "timestamp": "2019-11-05T16:24:38+01:00",
  "event": "ping_started",
  "some_field": "value",
  "some_int": 123
}
{
  "level": "info",
  "application": "MyAppName",
  "entry_point": true,
  "host": "localhost",
  "path": "/ping",
  "request_depth": 0,
  "request_id": "85bec38d-1057-4ec6-88af-bed508e98594",
  "route": "ping",
  "tree_path": "T",
  "verb": "GET",
  "timestamp": "2019-11-05T16:24:38+01:00",
  "event": "request_finished",
  "body": "",
  "ip": "::1",
  "params": "",
  "user_agent": "curl/7.54.0",
  "status": 200,
  "request_duration": 0.366895
}
Standalone logger
1. Via DefaultLogger
    logger.Event("myPlainEvent").Msg("log my line")
    logger.Event("myComplexEvent").Str("aString", "field").Int("num", 422).Bool("valid", false).Err(fmt.Errorf("something failed")).Send()
{
  "level": "info",
  "timestamp": "2020-02-11T16:41:36.690388+01:00",
  "event": "mySimpleEvent",
  "message": "log my line"
}
{
  "level": "info",
  "timestamp": "2020-02-11T16:41:36.690518+01:00",
  "event": "myComplexEvent",
  "aString": "field",
  "num": 422,
  "valid": false,
  "error": "something failed",
  "message": "foo failed"
}
2. Standalone logger.

But you need to provide the application name and as a return you will get the logger instance + the context.Context that contains the logger if you would like to pass it to some underlying functions.

func standaloneLogger() {
	log, ctx := logger.New(context.TODO(), "myAppName")
	log.Event("An event").Msg("hello world")

	useLoggerFromContext(ctx)
}

func useLoggerFromContext(ctx context.Context) {
	log := logger.Get(ctx)
	log.Event("useLoggerFromContext").Bool("aTruth", true).Msg("hello :)")
}

Would log something like this:

{
  "level": "info",
  "application": "myAppName",
  "timestamp": "2020-02-11T17:42:27.886908+01:00",
  "event": "An event",
  "message": "hello world"
}
{
  "level": "info",
  "application": "myAppName",
  "timestamp": "2020-02-11T17:55:42.20271+01:00",
  "event": "loggerFromContext",
  "aTruth": true,
  "message": "hello :)"
}
AWS Lambda

For now there is no extra middleware for lambdaHandlers but it can be used with existing setup and simple instruction that builds the logger and registers it in the handler context.

package main

import (
	"context"
	"fmt"

	"github.com/aws/aws-lambda-go/lambda"

	"github.com/blacklane/warsaw/logger"
)

type MyEvent struct {
	Name string `json:"name"`
}

func foo(ctx context.Context) {
	log := logger.Get(ctx)
	log.Event("I'm").Msg("insideMethod")
}

func handleRequest(ctx context.Context, name MyEvent) (string, error) {
	log, ctx := logger.NewLambdaLogger(ctx)
	log.Event("Called").Str("the_name", name.Name).Send()

	foo(ctx)
	return fmt.Sprintf("Hello %s!", name.Name), nil
}

func main() {
	lambda.Start(handleRequest)
}

that would log events as follows:

{
  "level": "info",
  "application": "myTestLambda",
  "entry_point": true,
  "lambda_function_arn": "arn:aws:lambda:eu-central-1:12345678901:function:myTestLambda",
  "lambda_function_version": "$LATEST",
  "lambda_memory_limit_in_mb": 512,
  "request_id": "4303499d-fccf-4cef-850c-26de69030463",
  "timestamp": "2020-01-20T14:47:05.491402536Z",
  "event": "Called",
  "the_name": "value1"
}
{
  "level": "info",
  "application": "myTestLambda",
  "entry_point": true,
  "lambda_function_arn": "arn:aws:lambda:eu-central-1:12345678901:function:myTestLambda",
  "lambda_function_version": "$LATEST",
  "lambda_memory_limit_in_mb": 512,
  "request_id": "4303499d-fccf-4cef-850c-26de69030463",
  "timestamp": "2020-01-20T14:47:05.491476597Z",
  "event": "I'm",
  "message": "insideMethod"
}

Contributing

Open an issue, if the change is small, open the PR as well. If the change is big we commend to open the issue to discuss it first.

And don't forget:

go test ./...
golint ./...
go vet ./...

Licence

Copyright 2019 Blacklane

Licensed under MIT License

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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