Skip to content
EventFabric CQRS Framework

Logger Middleware

The Logger middleware logs HTTP requests and responses with timing information using the EventFabric logger. It optionally integrates with OpenTelemetry for distributed tracing.

An in Depth Example

This guide also has an in depth example of a working application built with EventFabric. Combining DDD, CQRS and Event Sourcing.

Check out the In Depth Example page to learn how everything is connected and works out in a real-world application.

import { Hono } from "hono";
import { correlationId, logger } from "@nimbus-cqrs/hono";

const app = new Hono();

// Use correlationId middleware first to enable correlation ID in logs
app.use(correlationId());
app.use(logger());
OptionTypeDefaultDescription
enableTracingbooleantrueEnable OpenTelemetry tracing for requests
tracerNamestring"nimbus"The name of the tracer for OpenTelemetry
import { logger } from "@nimbus-cqrs/hono";

app.use(
    logger({
        enableTracing: true,
        tracerName: "api",
    })
);

The middleware logs each request and response using the EventFabric logger:

Request log:

[API] INFO :: REQ: [GET] /users/123

Response log (with timing):

[API] INFO :: RES: [GET] /users/123 - 45ms

Both logs include the correlation ID when the correlationId middleware is used.

When enableTracing is set to true, the middleware:

  1. Extracts trace context from incoming traceparent and tracestate headers
  2. Creates a server span for the HTTP request
  3. Records span attributes for observability
  4. Propagates context so child spans can be created in handlers
AttributeDescription
http.methodThe HTTP method (GET, POST, etc.)
url.pathThe request path
http.targetThe full request URL
correlation_idThe correlation ID (if available)
http.status_codeThe response status code
import { Hono } from "hono";
import { correlationId, logger } from "@nimbus-cqrs/hono";

const app = new Hono();

app.use(correlationId());
app.use(
    logger({
        enableTracing: true,
        tracerName: "api",
    })
);

app.get("/users/:id", async (c) => {
    // This handler runs within the HTTP span context
    // Any spans created here will be children of the HTTP span
    const user = await userRepository.findOne({
        filter: { _id: c.req.param("id") },
    });

    return c.json(user);
});

When an error occurs during request handling:

  • The span status is set to ERROR
  • The error message is recorded in the span
  • The exception is recorded for debugging
  • The error is re-thrown for the error handler to process