# How to Implement Request/Response Logging Middleware in Gorig: A Complete Guide

> Implement Gorig request response logging middleware efficiently using httpx Logging to track requests, responses, and latency Register it with srv Use on your httpx HTTP instance for detailed insights.

- Repository: [Jom/gorig](https://github.com/jom-io/gorig)
- Tags: how-to-guide
- Published: 2026-03-05

---

**Use `httpx.Logging()` from the `httpx` package to capture request details, response status, and latency by registering it with `srv.Use()` on your `httpx.HTTP` instance.**

The `jom-io/gorig` framework provides a lightweight HTTP layer through the `httpx` package, making it straightforward to implement request/response logging middleware in Gorig services. By leveraging the built-in logging middleware located in [`httpx/mid.logger.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.logger.go), you can automatically capture comprehensive telemetry for every HTTP transaction without writing boilerplate instrumentation code.

## Understanding Gorig's HTTP Middleware Architecture

Gorig's HTTP stack centers around the `httpx.HTTP` struct defined in [`httpx/http.go`](https://github.com/jom-io/gorig/blob/main/httpx/http.go). Middleware follows the standard Go pattern with the signature `func(http.Handler) http.Handler`, allowing seamless composition of cross-cutting concerns. The `httpx.RegisterRouter` helper and the `Use` method attach middleware to the server instance, executing handlers in the order they are registered.

## How the Built-in Logging Middleware Works

The core implementation resides in [`httpx/mid.logger.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.logger.go). This middleware performs four critical operations to ensure complete observability:

1. **Captures request metadata** – Records the HTTP method, URL, headers, remote address, and optionally the request body.
2. **Records start time** – Marks the request entry time to calculate total latency after handler completion.
3. **Wraps the ResponseWriter** – Uses a proxy struct to intercept `WriteHeader` and `Write` calls, capturing the status code and response size since the standard `http.ResponseWriter` does not expose these after transmission.
4. **Defers log emission** – Executes a deferred function that outputs a structured log line containing timestamp, request ID (if available), HTTP method, path, status, size, duration, and optional bodies.

The middleware delegates actual log output to [`utils/logger/logger.go`](https://github.com/jom-io/gorig/blob/main/utils/logger/logger.go), a thin wrapper that defaults to the standard library but accepts pluggable structured loggers.

## Implementing Request/Response Logging in Your Service

### Basic Setup with the Default Logger

To enable logging, initialize the logger and register the middleware when constructing your HTTP server. The `httpx.Logging()` function returns the middleware handler compatible with `srv.Use()`.

```go
package main

import (
	"github.com/jom-io/gorig/httpx"
	"github.com/jom-io/gorig/utils/logger"
)

func main() {
	// Initialize the default logger
	logger.Setup(logger.Config{Level: "info"})

	// Create HTTP server instance
	srv := httpx.NewHTTP()

	// Register the logging middleware
	srv.Use(httpx.Logging())

	// ... register routes and start server
	srv.Start()
}

```

### Registering Multiple Middlewares

Middleware executes in registration order. Place `httpx.Logging()` early in the chain to capture the full request lifecycle, including time spent in subsequent middlewares like authentication or CORS.

```go
func main() {
	logger.Setup(logger.Config{Level: "debug"})
	srv := httpx.NewHTTP()

	// Order matters: logging first captures total latency
	srv.Use(httpx.Logging())      // from httpx/mid.logger.go
	srv.Use(httpx.Recovery())     // panic recovery from httpx/mid.recovery.go
	srv.Use(httpx.CORS())         // CORS headers
	srv.Use(httpx.Sign())         // request signing verification

	// Register business routes using apix helpers
	srv.Handle("/api/v1/hello", apix.Handle(func(c *apix.Context) error {
		return c.JSON(apix.OK, map[string]string{"msg": "hello world"})
	}))

	srv.Start()
}

```

### Using a Custom Logger Implementation

The middleware calls `logger.Infof` from [`utils/logger/logger.go`](https://github.com/jom-io/gorig/blob/main/utils/logger/logger.go). To use a structured logger like Zap or Logrus, replace the global logger functions before starting the server.

```go
package logger

import (
	"github.com/sirupsen/logrus"
)

var log = logrus.New()

func Infof(format string, args ...interface{}) {
	log.Infof(format, args...)
}

func Setup(cfg Config) {
	// Configure logrus level, formatting, etc.
	log.SetLevel(logrus.InfoLevel)
	log.SetFormatter(&logrus.JSONFormatter{})
}

```

## Key Configuration Options and Best Practices

While the built-in middleware captures comprehensive data, consider these optimizations for production workloads:

- **Body Logging Control** – The middleware supports optional request/response body capture, but disable this for large file uploads or in high-throughput scenarios to prevent memory pressure and log bloat.
- **Request ID Correlation** – Place a request-ID middleware before the logger to ensure the `logger.Infof` call includes the correlation ID in the emitted line, enabling distributed tracing.
- **Latency Measurement** – Because the logger defers execution until after the handler completes, it naturally captures total round-trip time including middleware overhead, not just business logic execution.

## Summary

Implementing request/response logging middleware in Gorig requires only a single line of code using `httpx.Logging()`, but understanding the underlying architecture in [`httpx/mid.logger.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.logger.go) helps you customize the behavior. Key takeaways include:

- Register the middleware with `srv.Use(httpx.Logging())` on your `httpx.HTTP` instance
- The middleware wraps `http.ResponseWriter` to capture status codes and response sizes
- Execution order matters—place logging early in the middleware chain to capture total latency
- Replace the default logger in [`utils/logger/logger.go`](https://github.com/jom-io/gorig/blob/main/utils/logger/logger.go) to integrate structured logging libraries like Zap or Logrus

## Frequently Asked Questions

### Where is the logging middleware implemented in Gorig?

The core implementation resides in [`httpx/mid.logger.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.logger.go) within the `jom-io/gorig` repository. This file defines the middleware function that captures request metadata, wraps the `ResponseWriter`, and defers log emission until the handler completes.

### Can I customize the log format when using Gorig's logging middleware?

Yes, by replacing the logger implementation in [`utils/logger/logger.go`](https://github.com/jom-io/gorig/blob/main/utils/logger/logger.go). The middleware only calls `logger.Infof`, so any custom logger that implements this function signature—including structured loggers like Zap, Logrus, or Zerolog—will work seamlessly without modifying the middleware itself.

### How do I capture request and response bodies in the logs?

The built-in middleware in [`httpx/mid.logger.go`](https://github.com/jom-io/gorig/blob/main/httpx/mid.logger.go) supports optional body capture through configuration, though you should use this cautiously to avoid logging sensitive data or overwhelming storage with large payloads. Check the middleware's configuration options or wrap the `http.Request` body with `io.TeeReader` in a custom implementation if you need fine-grained control.

### What is the correct order for registering logging middleware with other middlewares?

Register `httpx.Logging()` early in the chain—typically first or immediately after request-ID middleware—using `srv.Use()`. This placement ensures the logger captures the total request latency including time spent in authentication, CORS, and other downstream middlewares, rather than just the business handler execution.