# How to Integrate Fabrica-Kit with go-kratos Middleware: A Complete Guide

> Integrate Fabrica-Kit with go-kratos middleware for structured logging, metrics, tracing, and context enrichment. This guide makes adding Kratos middleware simple.

- Repository: [Pantheon/fabrica-kit](https://github.com/go-pantheon/fabrica-kit)
- Tags: how-to-guide
- Published: 2026-03-02

---

**Fabrica-Kit provides ready-to-use go-kratos middleware components that implement the standard `middleware.Middleware` signature, allowing you to drop in structured logging, metrics, tracing, and context enrichment directly into any Kratos server or client configuration.**

The `go-pantheon/fabrica-kit` repository offers a comprehensive toolkit for building production-ready microservices in Go. When you integrate fabrica-kit with go-kratos middleware, you gain access to pre-built observability and context management components that seamlessly plug into the Kratos ecosystem using standard middleware interfaces.

## Understanding the Integration Architecture

Fabrica-Kit ships with middleware that conforms to the Kratos `middleware.Middleware` type (`func(handler middleware.Handler) middleware.Handler`). These components can be composed with any standard Kratos middleware.

| Fabrica-Kit feature | Kratos integration point | What it does |
|---------------------|--------------------------|--------------|
| **Structured logging & tracing** | `xlog.Init` & `trace.Init` (used before server creation) | Configures a logger that automatically injects trace IDs (`tracing.TraceID()`, `tracing.SpanID()`) into every log entry. |
| **Metrics collection** | `metrics.Server()` & `metrics.Client()` | Wraps the request handling pipeline and records request counters & latency histograms via OpenTelemetry. |
| **Context enrichment** | `xcontext/middleware/dev.Server` | Copies request headers (defined in `xcontext.Keys`) into the Kratos context so downstream code can retrieve them. |
| **gRPC client connection** | `router/conn.NewConn` | Creates a gRPC client with Kratos‑style middleware chain (recovery, metadata, tracing, metrics, logging). |

## Step-by-Step Integration Guide

### Initialize Tracing and Logging

Before creating any Kratos server, you must initialize the telemetry infrastructure. In [`trace/trace.go`](https://github.com/go-pantheon/fabrica-kit/blob/main/trace/trace.go), the `trace.Init` function configures OpenTelemetry, while [`xlog/log.go`](https://github.com/go-pantheon/fabrica-kit/blob/main/xlog/log.go) sets up a logger that automatically pulls trace IDs via `tracing.TraceID()` and `tracing.SpanID()`.

```go
// Initialize OpenTelemetry tracing (required for logger & metrics)
if err := trace.Init(
    "http://localhost:4318/v1/traces", // OTLP endpoint
    "my-service",                      // service name
    "dev",                             // environment profile
    "blue",                            // colour tag (optional)
); err != nil {
    panic(err)
}

// Initialize structured logger – trace IDs are automatically added
logger := xlog.Init(
    "zap",        // log implementation
    "info",       // level
    "dev",        // profile
    "blue",       // colour
    "my-service", // service name
    "v1.0.0",     // version
    "node-1",     // node name
)

```

### Configure Server-Side Middleware

Add Fabrica-Kit middleware to your Kratos server using the standard `grpc.Middleware` option. The `metrics.Server()` function from [`metrics/metrics.go`](https://github.com/go-pantheon/fabrica-kit/blob/main/metrics/metrics.go) returns a middleware that records OpenTelemetry metrics, while `dev.Server` from [`xcontext/middleware/dev/middleware.go`](https://github.com/go-pantheon/fabrica-kit/blob/main/xcontext/middleware/dev/middleware.go) enriches the context with request headers.

```go
srv := grpc.NewServer(
    grpc.Middleware(
        // Metrics collection for every RPC
        metrics.Server(),
        // Enrich context with request headers (optional)
        dev.Server(logger),
        // Add any other Kratos middleware you need, e.g. recovery
    ),
)

```

### Set Up Client Connections

For client-side integration, use `router/conn.NewConn` from [`router/conn/conn.go`](https://github.com/go-pantheon/fabrica-kit/blob/main/router/conn/conn.go). This helper constructs a gRPC client with a complete Kratos middleware stack including recovery, metadata, tracing, metrics, and logging.

```go
c, err := conn.NewConn(
    "my-service",          // target service name in service discovery
    balancer.TypeMaster,   // balancer type (Master or Reader)
    logger,                // logger used by the logging middleware
    rt,                    // route table for node filtering
    discovery,             // service discovery mechanism
)
if err != nil {
    panic(err)
}
defer c.Close()

```

## Complete Implementation Examples

### Full Server Setup with Fabrica-Kit Middleware

```go
package main

import (
	"github.com/go-kratos/kratos/v2"
	"github.com/go-kratos/kratos/v2/transport/grpc"

	"github.com/go-pantheon/fabrica-kit/trace"
	"github.com/go-pantheon/fabrica-kit/xlog"
	"github.com/go-pantheon/fabrica-kit/metrics"
	"github.com/go-pantheon/fabrica-kit/xcontext/dev"
)

func main() {
	// 1️⃣ Initialise OpenTelemetry tracing (required for logger & metrics)
	if err := trace.Init(
		"http://localhost:4318/v1/traces", // OTLP endpoint
		"my-service",                      // service name
		"dev",                             // environment profile
		"blue",                            // colour tag (optional)
	); err != nil {
		panic(err)
	}

	// 2️⃣ Initialise structured logger – trace IDs are automatically added
	logger := xlog.Init(
		"zap",        // log implementation
		"info",       // level
		"dev",        // profile
		"blue",       // colour
		"my-service", // service name
		"v1.0.0",     // version
		"node-1",     // node name
	)

	// 3️⃣ Build a Kratos gRPC server with Fabrica‑Kit middleware
	srv := grpc.NewServer(
		grpc.Middleware(
			// Metrics collection for every RPC
			metrics.Server(),
			// Enrich context with request headers (optional)
			dev.Server(logger),
			// Add any other Kratos middleware you need, e.g. recovery
		),
	)

	// 4️⃣ Assemble the Kratos application
	app := kratos.New(
		kratos.Name("my-service"),
		kratos.Version("v1.0.0"),
		kratos.Logger(logger),
		kratos.Server(srv),
	)

	// 5️⃣ Run the service
	if err := app.Run(); err != nil {
		logger.Error("application stopped", "error", err)
	}
}

```

### Creating a gRPC Client with Fabrica-Kit Middleware

```go
package main

import (
	"github.com/go-kratos/kratos/v2/log"
	"github.com/go-kratos/kratos/v2/registry"

	"github.com/go-pantheon/fabrica-kit/router/conn"
	"github.com/go-pantheon/fabrica-kit/router/balancer"
	"github.com/go-pantheon/fabrica-kit/router/routetable"
	"github.com/go-pantheon/fabrica-kit/metrics"
)

func main() {
	// Assume we already have a logger (e.g. from xlog.Init)
	var logger log.Logger // ← obtain from your logger init

	// A route table instance that implements routetable.ReadOnlyRouteTable.
	// In a real service you would use the concrete implementation from the router package.
	var rt routetable.ReadOnlyRouteTable // ← initialise according to your deployment

	// Service discovery (Kratos registry). For example, etcd:
	var discovery registry.Discovery // ← initialise your registry implementation

	// Build a gRPC client connection.
	// The returned *conn.Conn implements google.golang.org/grpc.ClientConnInterface.
	c, err := conn.NewConn(
		"my-service",          // target service name in service discovery
		balancer.TypeMaster,   // balancer type (Master or Reader)
		logger,                // logger used by the logging middleware
		rt,                    // route table for node filtering
		discovery,             // service discovery mechanism
	)
	if err != nil {
		panic(err)
	}
	defer c.Close()

	// The client now has the following middleware baked in:
	//   - recovery.Recovery()
	//   - metadata.Client()
	//   - tracing.Client()
	//   - metrics.Client()    ← records request metrics
	//   - logging.Client(logger) ← logs each RPC with trace IDs
	//
	// Use the connection to create your generated gRPC client stub:
	// mypb.NewMyServiceClient(c.ClientConnInterface)
}

```

### Adding Custom Middleware Alongside Fabrica-Kit

Fabrica-Kit's middleware can be mixed with any other Kratos middleware. Example with a custom authentication middleware:

```go
func AuthMiddleware() middleware.Middleware {
    return func(next middleware.Handler) middleware.Handler {
        return func(ctx context.Context, req any) (any, error) {
            // custom auth logic …
            return next(ctx, req)
        }
    }
}

// In server set-up:
srv := grpc.NewServer(
    grpc.Middleware(
        metrics.Server(),
        dev.Server(logger),
        AuthMiddleware(),      // custom middleware
        // … more Kratos middleware
    ),
)

```

## Key Files Reference

| File | Purpose | Link |
|------|---------|------|
| [`xlog/log.go`](https://github.com/go-pantheon/fabrica-kit/blob/main/xlog/log.go) | Logger initialisation; adds trace IDs to logs. | [xlog/log.go](https://github.com/go-pantheon/fabrica-kit/blob/main/xlog/log.go) |
| [`trace/trace.go`](https://github.com/go-pantheon/fabrica-kit/blob/main/trace/trace.go) | Sets up OpenTelemetry tracing (required for logging & metrics). | [trace/trace.go](https://github.com/go-pantheon/fabrica-kit/blob/main/trace/trace.go) |
| [`metrics/metrics.go`](https://github.com/go-pantheon/fabrica-kit/blob/main/metrics/metrics.go) | Provides `Server()` and `Client()` middleware for metrics collection. | [metrics/metrics.go](https://github.com/go-pantheon/fabrica-kit/blob/main/metrics/metrics.go) |
| [`xcontext/middleware/dev/middleware.go`](https://github.com/go-pantheon/fabrica-kit/blob/main/xcontext/middleware/dev/middleware.go) | Development middleware that copies request headers into the Kratos context. | [xcontext/middleware/dev/middleware.go](https://github.com/go-pantheon/fabrica-kit/blob/main/xcontext/middleware/dev/middleware.go) |
| [`router/conn/conn.go`](https://github.com/go-pantheon/fabrica-kit/blob/main/router/conn/conn.go) | Helper for creating gRPC client connections pre-wired with Fabrica-Kit middleware. | [router/conn/conn.go](https://github.com/go-pantheon/fabrica-kit/blob/main/router/conn/conn.go) |
| `router/balancer/*.go` | Load-balancing strategies used by `conn.NewConn`. | [router/balancer](https://github.com/go-pantheon/fabrica-kit/tree/main/router/balancer) |
| `router/routetable/*.go` | Route-table abstractions for node-aware routing. | [router/routetable](https://github.com/go-pantheon/fabrica-kit/tree/main/router/routetable) |

## Summary

- **Fabrica-Kit** provides drop-in Kratos middleware for logging, metrics, tracing, and context enrichment that implement the standard `middleware.Middleware` signature.
- **Initialization order matters**: call `trace.Init` before `xlog.Init` so the logger can automatically inject trace IDs (`tracing.TraceID()`, `tracing.SpanID()`) into every log entry.
- **Server-side**: add `metrics.Server()` and optionally `dev.Server(logger)` to your `grpc.Middleware` stack to collect OpenTelemetry metrics and enrich context with request headers.
- **Client-side**: use `router/conn.NewConn` to create gRPC clients that come pre-configured with the full Kratos middleware chain including recovery, metadata, tracing, metrics, and logging.
- **Extensibility**: Fabrica-Kit middleware can be composed with any custom Kratos middleware (such as authentication) by adding them to the same middleware chain.

## Frequently Asked Questions

### What is the correct order for initializing tracing and logging?

You must initialize tracing with `trace.Init` **before** calling `xlog.Init`. This sequence is required because the logger initialization in [`xlog/log.go`](https://github.com/go-pantheon/fabrica-kit/blob/main/xlog/log.go) relies on the global trace provider to inject `tracing.TraceID()` and `tracing.SpanID()` into every log entry. If tracing is not initialized first, the logger will not be able to capture distributed trace context.

### Can I use fabrica-kit middleware with custom Kratos middleware?

Yes. Fabrica-Kit middleware implements the standard Kratos `middleware.Middleware` type (`func(handler middleware.Handler) middleware.Handler`), so it composes naturally with any custom middleware. You can add your own authentication, authorization, or business logic middleware alongside `metrics.Server()` and `dev.Server()` in the `grpc.Middleware` call, and they will execute in the order specified.

### How does fabrica-kit handle metrics collection?

Fabrica-Kit uses OpenTelemetry for metrics collection. The `metrics.Server()` function (defined in [`metrics/metrics.go`](https://github.com/go-pantheon/fabrica-kit/blob/main/metrics/metrics.go)) returns a Kratos middleware that wraps the request handler to record request counters and latency histograms. Similarly, `metrics.Client()` provides client-side metrics. These metrics are automatically exported via the OpenTelemetry pipeline initialized by `trace.Init`, requiring no additional configuration beyond adding the middleware to your server or client.

### Is fabrica-kit compatible with all Kratos transport types?

While the examples focus on gRPC (using `grpc.NewServer` and `router/conn.NewConn`), Fabrica-Kit's middleware implements the transport-agnostic `middleware.Middleware` interface defined by Kratos. This means `metrics.Server()` and context enrichment middleware can be used with HTTP servers (`http.NewServer`) as well, provided you import the appropriate Kratos transport package. The `router/conn` helper is specifically designed for gRPC client connections.