Skip to main content
Entwickler Themen
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

2.4. Quarkus

Quarkus ist ein Java-Framework für Cloud- und Container-Anwendungen. Es setzt auf schnellen Start, geringen Speicherbedarf und Jakarta EE / MicroProfile APIs (REST, CDI, Config). Die folgenden Notizen sind keine Einführung, sondern Dinge, die ich selbst gebraucht habe.

Header-Logging kann Secrets mitloggen (Authorization, Cookies). In Produktivsystemen Header filtern oder nur Namen protokollieren.

Logging aller ausgehenden Requests

Alle ausgehenden Web-Requests lassen sich über einen RequestFilter loggen.

package de.neitzel.quarkus.util;

import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.client.ClientRequestFilter;
import jakarta.ws.rs.ext.Provider;
import org.jboss.logging.Logger;

@Provider
public class LoggingRequestFilter implements ClientRequestFilter {

  private static final Logger LOG = Logger.getLogger(LoggingRequestFilter.class);

  @Override
  public void filter(ClientRequestContext requestContext) {
    LOG.infof("➡️  Calling %s %s", requestContext.getMethod(), requestContext.getUri());
    requestContext.getHeaders().forEach((k, v) -> LOG.infof("Header %s: %s", k, v));
  }
}

Logging aller eingehenden Requests

Request-Bodies werden hier nicht gelesen, weil das den Stream verbrauchen kann.

Logging von Quarkus konfigurieren

quarkus:
  http:
    access-log:
      enabled: true
      # pattern: common | combined | eigener Pattern-String
      pattern: combined
      # optional: ins File statt nur im Log
      # log-to-file: true
      # base-file-name: access
      # log-directory: log

Deckt jede Anfrage ab (auch 404/405/Static/Extensions).

„combined“ enthält Methode, Pfad, Status, Größe, Referer, User-Agent.

Für Feinschliff lässt sich ein eigenes Pattern setzen.

JAX-RS-Filter (REST Layer)

ContainerRequestFilter mit @PreMatching

package de.neitzel.quarkus.util;

import jakarta.annotation.Priority;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.container.PreMatching;
import jakarta.ws.rs.ext.Provider;
import org.jboss.logging.Logger;

@Provider
@PreMatching                       // läuft vor dem Routing/Matching
@Priority(Priorities.USER)
public class IncomingRequestFilter implements ContainerRequestFilter {
  private static final Logger LOG = Logger.getLogger(IncomingRequestFilter.class);

  @Override
  public void filter(ContainerRequestContext ctx) {
    LOG.infof("⬅️  %s %s", ctx.getMethod(), ctx.getUriInfo().getRequestUri());
    ctx.getHeaders().forEach((k, v) -> LOG.infof("Header %s: %s", k, v));
  }
}

RESTeasy reactive “spezial”

package de.neitzel.quarkus.util;

import org.jboss.resteasy.reactive.server.ServerRequestFilter;
import org.jboss.resteasy.reactive.server.ServerResponseFilter;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import org.jboss.logging.Logger;

public class RequestAndResponseLoggingFilters {
  private static final Logger LOG = Logger.getLogger(RequestAndResponseLoggingFilters.class);

  @ServerRequestFilter
  public void logReq(HttpServerRequest req) {
    LOG.infof("⬅️  %s %s", req.method(), req.uri());
  }

  @ServerResponseFilter
  public void logRes(HttpServerResponse res) {
    LOG.infof("➡️  Status %d", res.getStatusCode());
  }
}

Vert.x Ebene (läuft vor allen Routen)

package de.neitzel.quarkus.util;

import io.quarkus.vertx.web.RouteFilter;
import io.vertx.ext.web.RoutingContext;
import org.jboss.logging.Logger;

public class GlobalRouteLogging {
  private static final Logger LOG = Logger.getLogger(GlobalRouteLogging.class);

  // kleinere Zahl = höhere Priorität
  @RouteFilter(100)
  void logAll(RoutingContext rc) {
    LOG.infof("⬅️  %s %s", rc.request().method(), rc.request().uri());
    rc.request().headers().forEach(h -> LOG.infof("Header %s: %s", h.getKey(), h.getValue()));
    rc.next(); // wichtig: weiterreichen
  }
}