Skip to content

Logs browser for Golang apps

Version update

The feature described in this post landed in 0.12.0 version.

As of today it is possible to embed Logdy directly into Go codebase with a single line! This opens up whole new possibilities regarding how logs could be treated during software development lifecycle.

With this feature, you can embed Logdy to your application during development environment

go
if localDevelopment == true || os.Getenv("ENV") == "demo" {
    logdy.InitializeLogdy(logdy.Config{})
}

Additionally you can secure access to Logdy UI with a passphrase and expose it on a remote machine.

go
logdy.InitializeLogdy(logdy.Config{
    UiPass: "foobar-1234567"
})

One interesting use case is having Logdy collect log messages on production - always ON. This means, you can have a direct insight into what is happening on your production instance without a bloated real-time observability pipeline.

What about other languages?

You can achieve the same effect by setting up Logdy as a Systemd service and pointing it to log files or opening up a socket.

Full example of implementing Logdy into an existing

The example is pretty self-explanatory, we've created a tiny web service with two endpoints using a standard Go multiplexer. What's interesting in this example is that we've also created a logging middleware and injected Logdy instance into it. This way, we can log every request (excluding the ones made by Logdy UI) and send it directly to Logdy.

go
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"strings"
	"time"

	logdy "github.com/logdyhq/logdy-core/logdy"
)

type Logger struct {
	logdy   logdy.Logdy
	handler http.Handler
}

func (l *Logger) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	start := time.Now()

	l.handler.ServeHTTP(w, r)

	// If this is a request to Logdy backend, ignore it
	if strings.HasPrefix(r.URL.Path, l.logdy.Config().HttpPathPrefix) {
		return
	}

	l.logdy.Log(logdy.Fields{
		"ua":     r.Header.Get("user-agent"),
		"method": r.Method,
		"path":   r.URL.Path,
		"query":  r.URL.RawQuery,
		"time":   time.Since(start),
	})
}

func main() {

	mux := http.NewServeMux()

	mux.HandleFunc("/v1/hello", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello, World!"))
	})

	mux.HandleFunc("/v1/time", func(w http.ResponseWriter, r *http.Request) {
		curTime := time.Now().Format(time.Kitchen)
		w.Write([]byte(fmt.Sprintf("the current time is %v", curTime)))
	})

	logger := logdy.InitializeLogdy(logdy.Config{
		HttpPathPrefix: "/_logdy-ui",
	}, mux)

	addr := ":8082"
	log.Printf("server is listening at %s", addr)
	log.Fatal(http.ListenAndServe(addr, &Logger{logdy: logger, handler: mux}))
}

You can observe the results in the Logdy UI under http://localhost:8082/_logdy-ui