logs

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Mar 6, 2024 License: GPL-3.0 Imports: 10 Imported by: 1

README

Monitoring: Logging

This repository contains a middleware for gin and gonic using zerolog. It is intended to be used by services that are instrumented with the Open Telemetry framework for Go. This middleware will inject the trace id and span id into the log entry so that the traces and logs can be correlated.

This package will also work as middleware if the project doesn't implement OTel distributed tracing. Neither is gin and gonic required; you can initialize the logging package and use the helper functions to log manually.

Installation


go get -u github.com/twistingmercury/monitoring

👀 Zerolog is currently used for logging since there isn't yet an OTel logging implementation for Go.

Log Collectors and Agents

This has been tested using Vector and the Datadog Agent, with the destination being Datadog. If the destination is a different provider, you may need to change the values for the constant defs TraceIDAttr and SpanIDAttr in the middleware file.

Initialization

io.Writer

Typically you will write to os.Stdout. However, if not containerizing, any io.Writer will work. This can be useful if you want to test the logging.

// if testing, you can use a bytes.Buffer
buffer := &bytes.Buffer{}
logs.Initialize(zerolog.DebugLevel, buildVersion, serviceName, buildDate, buildCommit, env, buffer)


// if not testing, you can use os.Stdout
logs.Initialize(zerolog.DebugLevel, buildVersion, serviceName, buildDate, buildCommit, env, os.Stdout)

This value is passed in with the writer parameter. If you do not provide a value, the application will panic. This is in keeping with the "fail fast" philosophy.

Logging Level

The logging level is set using the zerolog.Level type. This value is passed in with the level parameter. If a value is provide that is not valid, the application will panic. Again, this is in keeping with the "fail fast" philosophy.

Usage

To use the wrappers, you will need to initialize each wrapper you intend to use:

package main

import (
	"github.com/gin-contrib/requestid"
	"github.com/gin-gonic/gin"
	"github.com/rs/zerolog"
	"os"

	"github.com/twistingmercury/monitoring/logs"
...
)

const serviceName = "my-service"

var ( // build info will be set during the build process
	buildDate    = "{not set}"
	buildVersion = "{not set}"
	buildCommit  = "{not set}"
	env           =  os.Getenv("ENVIRONMENT") // or however you want to set this
)

func main(){
	logs.Initialize(zerolog.DebugLevel, buildVersion, serviceName, buildDate, buildCommit, env, os.Stdout)

	// do stuff...start your service, etc.
	r := gin.New()
	r.Use(logs.GinLoggingMiddleware())
	r.GET("/api/v1/ready", func(c *gin.Context) {
		c.JSON(200, gin.H{"ready": true})
	})

	if r.Run(":8080");err != nil {
		log.Fatal()Err(err).Msg( "error encountered in the gin.Engine.run func")
	}
}
Manual Logging

Log entries can be added manually that are correlated with the request. Helper funcs are provided for the various log levels. You must provide the context.Context that contains the trace information, and the message to log. A way to do this is might be:

package logic

import (
	"context"
	"time"
)

func foo(ctx context.Context, args ...interface{}) (err error) {
	logs.Debug(ctx, "starting BusinessLogic", "args", args)
	s := time.Now()

	// do stuff...

	if err != nil {
		return
	}

	l := time.Since(s)
	logs.Debug(ctx, "finished BusinessLogic", "duration", l)
	// do more stuff...
	return
}

...And in the gin handler:

// myApi is a gin handler that is already logged with the gin middleware
func myApi (c *gin.Context){
	// do stuff...
    err := logic.Foo(c.Request.Context(), args...)
    if err != nil {
        // the middleware will log the error, so you don't have to
        c.JSON(500, gin.H{"error": "something went wrong"})
        return
    }
    // do more stuff...
    c.JSON(200, gin.H{"success": true})
}

Access the Logger

You can get a pointer to the logger by calling logs.Logger(). This is useful if you want to log something outside of the middleware or helper functions.


zlogger := logs.Logger()
zlogger.Info().Msg("this is a log entry")

Documentation

Index

Constants

View Source
const (
	TraceIDAttr    = "dd.trace_id"
	SpanIDAttr     = "dd.span_id"
	HttpMethod     = "http.request.method"
	HttpPath       = "http.request.path"
	HttpRemoteAddr = "http.request.remoteAddr"
	HttpStatus     = "http.response.status"
	HttpLatency    = "http.response.latency"
	LogLevel       = "level"
)
View Source
const (
	UserAgentOS             = "http.user_agent.os"
	UserAgentOSVersion      = "http.user_agent.os_version"
	UserAgentDevice         = "http.user_agent.device"
	UserAgentBrowser        = "http.user_agent.browser"
	UserAgentBrowserVersion = "http.user_agent.browser_version"
	BrowserChrome           = "chrome"
	BrowserSafari           = "safari"
	BrowserFirefox          = "firefox"
	BrowserOpera            = "opera"
	BrowserIE               = "ie"
	BrowserEdge             = "edge"
	BrowserTrident          = "Trident"
	QueryString             = "http.query"
)

Variables

This section is empty.

Functions

func Debug

func Debug(ctx context.Context, message string, args map[string]any)

Debug logs a debug message and adds the trace id and span id fount in the ctx. The args are key value pairs and are optional.

func Error

func Error(ctx context.Context, err error, message string, args map[string]any)

Error logs an error message and adds the trace id and span id fount in the ctx.

func Fatal

func Fatal(ctx context.Context, err error, message string, args map[string]any)

Fatal logs a fatal message and adds the trace id and span id fount in the ctx.

func GinLoggingMiddleware

func GinLoggingMiddleware() gin.HandlerFunc

GinLoggingMiddleware logs the incoming request and starts the trace.

func Info

func Info(ctx context.Context, message string, args map[string]any)

Info logs an info message and adds the trace id and span id fount in the ctx. The args are key value pairs and are optional.

func Initialize

func Initialize(level zerolog.Level, ver, apiName, buildDate, commitHash, env string, writer io.Writer)

Initialize initializes the logging system. It returns a logger that can be used to log messages, though it is not required.

func Logger added in v1.0.1

func Logger() *zerolog.Logger

Logger returns a pointer to the logger that is used by the logging system.

func ParseHeaders

func ParseHeaders(headers map[string][]string) (args map[string]any)

ParseHeaders parses the headers and returns a map of attributes.

func ParseUserAgent

func ParseUserAgent(rawUserAgent string) (args map[string]any)

ParseUserAgent parses the user agent string and returns a map of attributes.

func Warn

func Warn(ctx context.Context, message string, args map[string]any)

Warn logs a warning message and adds the trace id and span id fount in the ctx. The args are key value pairs and are optional.

Types

This section is empty.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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