Structured Logging in Go: Context-Aware, JSON-Ready, and Production-Proven

Every developer has been there:

You’re on-call, an alert fires at 2 AM, and you’re staring at a wall of logs that look like this:

The Evolution of Logging 🧭

Logging in software has evolved a lot — but not every project has kept…


This content originally appeared on DEV Community and was authored by Kittipat.po

Every developer has been there:

You’re on-call, an alert fires at 2 AM, and you’re staring at a wall of logs that look like this:

Blog Image

The Evolution of Logging 🧭

Logging in software has evolved a lot — but not every project has kept up:

1. Print Statements (the Stone Age): Just fmt.Println(“something happened”). Quick and dirty, but useless at scale.
2. Plain Logs with Timestamps (basic survival): Go’s log.Println gives you a timestamp, but everything else is left to you. Debugging across services? Forget it.
3. Leveled Logging (finding your voice): Tools like INFO, WARN, and ERROR levels made logs less noisy. You could finally filter out debug spam in production. But still no structure.
4. Structured Logging (the turning point): Instead of dumping plain text, logs became key–value pairs in JSON. Now you can query logs like data:
{ “severity”: “error”, “user_id”: 12345, “message”: “login failed” }
5. Context-Aware & Observability-Ready (where we are now): Modern systems aren’t just about logs — they’re about traces, spans, request IDs, and correlating everything in your observability stack. If your logger doesn’t integrate with context.Context, you’re already missing half the picture.

The Problem With Go’s Default Logging

Go’s built-in log package is fine for “hello world” projects, but once you’re in microservices land:

  • It doesn’t support structured fields.
  • It doesn’t know about context.Context.
  • It won’t give you trace IDs, caller info, or stack traces.

That gap inspired me to build something better. 🚀

Introducing the Logger Package 🎉

That’s where my Logger package comes in.

It’s a structured, context-aware logging solution for Go, built on top of Logrus, designed for production environments.

Think of it as logging upgraded for the cloud-native era:

  • JSON logs out of the box.
  • Automatic context propagation (trace_id, span_id).
  • Caller + stack trace included when you need it.
  • Customizable formatters and outputs.
  • Clean API that feels natural in Go.

How It Works ⚙️

The Logger package is designed to feel simple but powerful. Here’s how you can bring it into your project.

1. Install

go get github.com/kittipat1413/go-common/framework/logger

2. Create a Logger
You can start with the default production-ready logger:

log := logger.NewDefaultLogger()
log.Info(context.Background(), "Application started", nil)

Or configure it yourself using the Config struct:

logConfig := logger.Config{
    Level: logger.INFO,
    Formatter: &logger.StructuredJSONFormatter{
        TimestampFormat: time.RFC3339,
        // PrettyPrint
        // - true  = pretty-printed JSON (indented, easier for humans to read)
        // - false = compact JSON (single line, no indentation)
        PrettyPrint:     false,
    },
    Environment: "production",
    ServiceName: "order-service",
}

log, _ := logger.NewLogger(logConfig)

3. Structured JSON Formatter
By default, logs are emitted in structured JSON:

Structured JSON Log

4. Customize Keys and Metadata
Don’t like the default field names in your logs?

You can redefine field names using a FieldKeyFormatter:

formatter := &logger.StructuredJSONFormatter{
    TimestampFormat: time.RFC3339,
    FieldKeyFormatter: func(key string) string {
        switch key {
        case logger.DefaultEnvironmentKey:
            return "env"
        case logger.DefaultServiceNameKey:
            return "service"
        default:
            return key
        }
    },
}

Now your logs use env and service instead of the defaults.

5. Context-Aware Logging
Pass in a context.Context with tracing info, and the logger automatically enriches logs with trace_id and span_id.

ctx, span := tracer.Start(context.Background(), "checkout")
defer span.End()

log.Info(ctx, "Processing checkout request", logger.Fields{
    "user_id": 42,
})

Log output:

Tracing Log

6. Error Logging with Stack Traces
When logging errors, the logger automatically includes stack traces for quick debugging:

err := errors.New("database connection failed")
log.Error(ctx, "Failed to query user", err, logger.Fields{
    "query": "SELECT * FROM users",
})

Log output:

Error Log

Final Thoughts ✨

This logger has already helped me a lot in my own projects — from cleaning up noisy logs to making debugging at 2 AM way less painful. That’s why I decided to share it with the community.

If you give it a try and it makes your life easier too, that’s a win.

And if you have suggestions, ideas, or improvements, I’d love to hear them. Open an issue or drop a comment — feedback is always welcome.

👉 Explore the examples.
👉 Or check out the documentation on pkg.go.dev.


This content originally appeared on DEV Community and was authored by Kittipat.po


Print Share Comment Cite Upload Translate Updates
APA

Kittipat.po | Sciencx (2025-09-15T07:46:26+00:00) Structured Logging in Go: Context-Aware, JSON-Ready, and Production-Proven. Retrieved from https://www.scien.cx/2025/09/15/structured-logging-in-go-context-aware-json-ready-and-production-proven/

MLA
" » Structured Logging in Go: Context-Aware, JSON-Ready, and Production-Proven." Kittipat.po | Sciencx - Monday September 15, 2025, https://www.scien.cx/2025/09/15/structured-logging-in-go-context-aware-json-ready-and-production-proven/
HARVARD
Kittipat.po | Sciencx Monday September 15, 2025 » Structured Logging in Go: Context-Aware, JSON-Ready, and Production-Proven., viewed ,<https://www.scien.cx/2025/09/15/structured-logging-in-go-context-aware-json-ready-and-production-proven/>
VANCOUVER
Kittipat.po | Sciencx - » Structured Logging in Go: Context-Aware, JSON-Ready, and Production-Proven. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/09/15/structured-logging-in-go-context-aware-json-ready-and-production-proven/
CHICAGO
" » Structured Logging in Go: Context-Aware, JSON-Ready, and Production-Proven." Kittipat.po | Sciencx - Accessed . https://www.scien.cx/2025/09/15/structured-logging-in-go-context-aware-json-ready-and-production-proven/
IEEE
" » Structured Logging in Go: Context-Aware, JSON-Ready, and Production-Proven." Kittipat.po | Sciencx [Online]. Available: https://www.scien.cx/2025/09/15/structured-logging-in-go-context-aware-json-ready-and-production-proven/. [Accessed: ]
rf:citation
» Structured Logging in Go: Context-Aware, JSON-Ready, and Production-Proven | Kittipat.po | Sciencx | https://www.scien.cx/2025/09/15/structured-logging-in-go-context-aware-json-ready-and-production-proven/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.