为WSO2 Microgateway添加日志拦截器实现独立日志记录的最优方案
Great question! When you need to split access and security-related logs into their own files in WSO2 Microgateway (which uses SLF4J bound to Java Util Logging/JUL), here's the most effective approach aligned with MGW's native logging setup:
MGW relies on JUL under the hood, so we'll extend its configuration to route specific logs to separate files. Here's how:
- Create a custom
logging.propertiesfile (you can base it on the default one in<MGW_HOME>/conf/logging.properties). - Add dedicated file handlers for access and security logs:
# Base handlers + custom log handlers handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler, org.wso2.mgw.handlers.AccessFileHandler, org.wso2.mgw.handlers.SecurityFileHandler # Access Log Handler Configuration org.wso2.mgw.handlers.AccessFileHandler.level=FINE org.wso2.mgw.handlers.AccessFileHandler.formatter=java.util.logging.SimpleFormatter org.wso2.mgw.handlers.AccessFileHandler.pattern=${carbon.home}/logs/mgw-access.log org.wso2.mgw.handlers.AccessFileHandler.append=true # Security Log Handler Configuration org.wso2.mgw.handlers.SecurityFileHandler.level=FINE org.wso2.mgw.handlers.SecurityFileHandler.formatter=java.util.logging.SimpleFormatter org.wso2.mgw.handlers.SecurityFileHandler.pattern=${carbon.home}/logs/mgw-security.log org.wso2.mgw.handlers.SecurityFileHandler.append=true
- Define dedicated loggers for your interceptor and MGW's built-in security components, and map them to the handlers (set
additivity=falseto avoid duplicate logs inmicrogateway.log):
# Custom Access Logger (for your interceptor) logger.access.name=org.wso2.mgw.custom.interceptors.AccessLogger logger.access.level=FINE logger.access.handlers=org.wso2.mgw.handlers.AccessFileHandler logger.access.additivity=false # Security Logger (covers MGW auth events) logger.security.name=org.wso2.carbon.security logger.security.level=FINE logger.security.handlers=org.wso2.mgw.handlers.SecurityFileHandler logger.security.additivity=false
- Update MGW's startup script to use this custom config by adding
-Djava.util.logging.config.file=<path-to-your-custom-logging.properties>to the JVM arguments.
Create a Java interceptor that captures access events and uses the dedicated logger we defined. Extend AbstractGatewayInterceptor and override relevant methods:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.wso2.micro.gateway.interceptor.AbstractGatewayInterceptor; import org.wso2.micro.gateway.interceptor.InterceptorContext; public class AccessLoggingInterceptor extends AbstractGatewayInterceptor { // Use the dedicated access logger we configured private static final Logger accessLogger = LoggerFactory.getLogger("org.wso2.mgw.custom.interceptors.AccessLogger"); @Override public boolean preProcess(InterceptorContext context) { // Capture request details for access log String method = context.getRequest().getMethod(); String path = context.getRequest().getPath(); String clientIp = context.getRequest().getRemoteAddr(); long timestamp = System.currentTimeMillis(); accessLogger.info("ACCESS_EVENT | Timestamp: {} | ClientIP: {} | Method: {} | Path: {}", timestamp, clientIp, method, path); return true; } @Override public boolean postProcess(InterceptorContext context) { // Capture response status in access log int statusCode = context.getResponse().getStatusCode(); String method = context.getRequest().getMethod(); String path = context.getRequest().getPath(); accessLogger.info("RESPONSE_EVENT | Method: {} | Path: {} | StatusCode: {}", method, path, statusCode); return true; } @Override public boolean handleAuthFailure(InterceptorContext context) { // Capture auth failure events using the security logger Logger securityLogger = LoggerFactory.getLogger("org.wso2.carbon.security"); String clientIp = context.getRequest().getRemoteAddr(); String errorMsg = context.getErrorResponse().getMessage(); securityLogger.error("AUTH_FAILURE | ClientIP: {} | Error: {}", clientIp, errorMsg); return true; } @Override public boolean handleAuthSuccess(InterceptorContext context) { // Capture auth success events using the security logger String username = context.getAuthenticatedUser().getUsername(); String clientIp = context.getRequest().getRemoteAddr(); LoggerFactory.getLogger("org.wso2.carbon.security") .info("AUTH_SUCCESS | Username: {} | ClientIP: {}", username, clientIp); return true; } }
This interceptor captures key access events (request/response) and authentication success/failure events, routing them to our dedicated loggers as configured.
- Package your interceptor class into a JAR file (SLF4J is already provided by MGW, so no need to include it as a dependency).
- Copy the JAR to
<MGW_HOME>/repository/components/libor<MGW_HOME>/extensions/interceptors(depending on your MGW version). - Configure the interceptor to apply to your APIs by updating the
api.yamlfile of your API project:
openapi: 3.0.1 info: title: Your Target API version: 1.0.0 x-wso2-interceptors: - name: AccessLoggingInterceptor class: org.wso2.mgw.custom.interceptors.AccessLoggingInterceptor priority: 1
- Repackage your API project and redeploy it to MGW.
- Avoid Duplicate Logs: Setting
additivity=falsein the logger config ensures logs don't appear in both your custom files and the defaultmicrogateway.log. - Formatter Customization: You can create a custom JUL formatter (extending
java.util.logging.Formatter) to format logs in a structured format (like JSON) for easier parsing and analysis. - Version Compatibility: Ensure your interceptor uses the correct MGW interceptor API version (match it to your MGW release's dependency versions).
内容的提问来源于stack exchange,提问作者Raja Kumar Thiruvasagam

