DEV Community

Scott
Scott

Posted on • Edited on

6 1

Golang Dynamic Logging for Microservices

Dynamic logging is something I believe should be implemented in any micro-service environment. I suppose I should start with I mean by dynamic logging.. Simply put the following point should be covered.

  • Maintainer should be able to change the log level of the application mid-execution.

Sample Application

Using the go.uber.org/zap library LevelEnablerFunc you should be able to implement the interface using any protocol you want? (Haven't tested this).. That being said, for my sample application I will be using an HTTP interface and so I will use the zap built-in ServeHttp method.

First we need to define our logger and build and build an http router to accept log level changes. This is completed by utilizing the above mentioned ServeHttp function built into the zap.AtomicLevel object.

Setup Logger

config := zap.NewProductionEncoderConfig()
...
encoder := zapcore.NewJSONEncoder(config)
atom := zap.NewAtomicLevel()
    logr := zap.New(zapcore.NewCore(encoder, zapcore.Lock(os.Stdout), atom))
Enter fullscreen mode Exit fullscreen mode

Dynamic log level interface

mux := http.NewServeMux()
mux.Handle("/log_level", atom)
go http.ListenAndServe(":1065", mux)
Enter fullscreen mode Exit fullscreen mode

I am running a simple loop that repeats various logging messages to allow us to see the expected output. After building and running the application we can interact with it via curl.

Change logging levels

curl -X PUT -d '{"level":"debug"}' localhost:1065/log_level
curl -X PUT -d '{"level":"info"}' localhost:1065/log_level
curl -X PUT -d '{"level":"info"}' localhost:1065/  # EXPECTED 404
curl -X GET localhost:1065/log_level
Enter fullscreen mode Exit fullscreen mode

NOTE: GIF seems to be broken again... but clicking the link should show you... ill fix it later 😂

DEMO

Sample Application Code

package main

import (
    "net/http"
    "os"
    "time"

    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
)

func main() {
    undo := initLogger()
    defer undo()

    for {
        zap.S().Info("test_logs")
        zap.S().Debug("test_logs_debug")
        time.Sleep(1000 * time.Millisecond)
    }
}

func initLogger() func() {
    config := zap.NewProductionEncoderConfig()
    config.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
        nanos := t.UnixNano()
        millis := nanos / int64(time.Millisecond)
        enc.AppendInt64(millis)
    }
    encoder := zapcore.NewJSONEncoder(config)
    atom := zap.NewAtomicLevel()
    logr := zap.New(zapcore.NewCore(encoder, zapcore.Lock(os.Stdout), atom))

    mux := http.NewServeMux()
    mux.Handle("/log_level", atom)
    go http.ListenAndServe(":1065", mux)

    return zap.ReplaceGlobals(logr)
}
Enter fullscreen mode Exit fullscreen mode

Do your career a big favor. Join DEV. (The website you're on right now)

It takes one minute, it's free, and is worth it for your career.

Get started

Community matters

Top comments (2)

Collapse
 
rusty_sys_dev profile image
Scott

If anyone can enlighten me as to how to get my gif to work, I would be eternally grateful! 😢 I have it written as the following.

![APP_GIF](https://i.imgur.com/iHNIhOF.gif)

It works when I try it in hackmd..

Collapse
 
rusty_sys_dev profile image
Scott • Edited

seems the gif was too large??? 🤣 🤣
200MP max size, according to the Firefox dev console I was requesting 380MP..
reduced the size by 1% and it seemed to work... 😕

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay