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

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, the trace.Init function configures OpenTelemetry, while xlog/log.go sets up a logger that automatically pulls trace IDs via tracing.TraceID() and tracing.SpanID().

// 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 returns a middleware that records OpenTelemetry metrics, while dev.Server from xcontext/middleware/dev/middleware.go enriches the context with request headers.

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. This helper constructs a gRPC client with a complete Kratos middleware stack including recovery, metadata, tracing, metrics, and logging.

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

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

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:

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 Logger initialisation; adds trace IDs to logs. xlog/log.go
trace/trace.go Sets up OpenTelemetry tracing (required for logging & metrics). trace/trace.go
metrics/metrics.go Provides Server() and Client() middleware for metrics collection. metrics/metrics.go
xcontext/middleware/dev/middleware.go Development middleware that copies request headers into the Kratos context. xcontext/middleware/dev/middleware.go
router/conn/conn.go Helper for creating gRPC client connections pre-wired with Fabrica-Kit middleware. router/conn/conn.go
router/balancer/*.go Load-balancing strategies used by conn.NewConn. router/balancer
router/routetable/*.go Route-table abstractions for node-aware routing. 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 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) 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →