![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.juneau.rest.logger.CallLoggerRule Maven / Gradle / Ivy
// ***************************************************************************************************************************
// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file *
// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file *
// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance *
// * with the License. You may obtain a copy of the License at *
// * *
// * http://www.apache.org/licenses/LICENSE-2.0 *
// * *
// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an *
// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the *
// * specific language governing permissions and limitations under the License. *
// ***************************************************************************************************************************
package org.apache.juneau.rest.logger;
import static org.apache.juneau.collections.JsonMap.*;
import java.util.function.*;
import java.util.logging.*;
import jakarta.servlet.http.*;
import org.apache.juneau.*;
import org.apache.juneau.cp.*;
import org.apache.juneau.internal.*;
/**
* Represents a logging rule used by {@link CallLogger}.
*
* See Also:
*/
public class CallLoggerRule {
//-----------------------------------------------------------------------------------------------------------------
// Static
//-----------------------------------------------------------------------------------------------------------------
/**
* Static creator.
*
* @param beanStore The bean store to use for creating beans.
* @return A new builder for this object.
*/
public static Builder create(BeanStore beanStore) {
return new Builder(beanStore);
}
//-----------------------------------------------------------------------------------------------------------------
// Builder
//-----------------------------------------------------------------------------------------------------------------
/**
* Builder class.
*/
@FluentSetters
public static class Builder extends BeanBuilder {
Predicate statusFilter;
Predicate requestFilter;
Predicate responseFilter;
Predicate exceptionFilter;
Enablement enabled;
Predicate enabledTest;
Level level;
CallLoggingDetail requestDetail, responseDetail;
boolean logStackTrace;
/**
* Constructor.
*
* @param beanStore The bean store to use for creating beans.
*/
protected Builder(BeanStore beanStore) {
super(CallLoggerRule.class, beanStore);
}
@Override /* BeanBuilder */
protected CallLoggerRule buildDefault() {
return new CallLoggerRule(this);
}
//-------------------------------------------------------------------------------------------------------------
// Properties
//-------------------------------------------------------------------------------------------------------------
/**
* Apply a status-based predicate check for this rule to match against.
*
* Example:
*
* // Create a logger rule that only matches if the status code is greater than or equal to 500.
* RestLogger
* .createRule ()
* .statusFilter(x -> x >= 500)
* .build();
*
*
* @param value
* The predicate check, or null to not use any filtering based on status code.
* @return This object.
*/
public Builder statusFilter(Predicate value) {
this.statusFilter = value;
return this;
}
/**
* Apply a throwable-based predicate check for this rule to match against.
*
* Example:
*
* // Create a logger rule that only matches if a NotFound exception was thrown.
* RestLogger
* .createRule ()
* .exceptionFilter(x -> x instanceof NotFound)
* .build();
*
*
*
* This check is only performed if an actual throwable was thrown. Therefore it's not necessary to perform a
* null check in the predicate.
*
* @param value
* The predicate check, or null to not use any filtering based on exceptions.
* @return This object.
*/
public Builder exceptionFilter(Predicate value) {
this.exceptionFilter = value;
return this;
}
/**
* Apply a request-based predicate check for this rule to match against.
*
* Example:
*
* // Create a logger rule that only matches if the servlet path contains "foobar".
* RestLogger
* .createRule ()
* .requestFilter(x -> x .getServletPath().contains("foobar" ))
* .build();
*
*
* @param value
* The predicate check, or null to not use any filtering based on the request.
* @return This object.
*/
public Builder requestFilter(Predicate value) {
this.requestFilter = value;
return this;
}
/**
* Apply a response-based predicate check for this rule to match against.
*
* Example:
*
* // Create a logger rule that only matches if the servlet path contains "foobar".
* RestLogger
* .createRule ()
* .responseFilter(x -> x .getStatus() >= 500)
* .build();
*
*
*
* Note that the {@link #statusFilter(Predicate)} and {@link #exceptionFilter(Predicate)} methods are simply
* convenience response filters.
*
* @param value
* The predicate check, or null to not use any filtering based on the response.
* @return This object.
*/
public Builder responseFilter(Predicate value) {
this.responseFilter = value;
return this;
}
/**
* Specifies whether logging is enabled when using this rule.
*
* Example:
*
* // Create a logger rule where logging is only enabled if the query string contains "foobar".
* RestLogger
* .createRule ()
* .enabled(CONDITIONALLY )
* .enabledPredicate(x -> x .getQueryString().contains("foobar" ))
* .build();
*
*
*
* - {@link Enablement#ALWAYS ALWAYS} - Logging is enabled.
*
- {@link Enablement#NEVER NEVER} - Logging is disabled.
*
- {@link Enablement#CONDITIONAL CONDITIONALLY} - Logging is enabled if it passes the {@link #enabledPredicate(Predicate)} test.
*
*
* @param value
* The enablement flag value, or null to inherit from the call logger whose default value is {@link Enablement#ALWAYS ALWAYS}
* unless overridden via a "juneau.restCallLogger.enabled" system property or "JUNEAU_RESTCALLLOGGER_ENABLED" environment variable.
* @return This object.
*/
public Builder enabled(Enablement value) {
this.enabled = value;
return this;
}
/**
* Specifies the predicate test to use when the enabled setting is set to {@link Enablement#CONDITIONAL CONDITIONALLY}.
*
*
* This setting has no effect if the enablement value is not {@link Enablement#CONDITIONAL CONDITIONALLY}.
*
*
Example:
*
* // Create a logger rule where logging is only enabled if the query string contains "foobar".
* RestLogger
* .createRule ()
* .enabled(CONDITIONALLY )
* .enabledPredicate(x -> x .getQueryString().contains("foobar" ))
* .build();
*
*
* @param value
* The enablement predicate test, or null to inherit from the call logger whose default value is x -> false .
* @return This object.
*/
public Builder enabledPredicate(Predicate value) {
this.enabledTest = value;
return this;
}
/**
* Shortcut for calling enabled(NEVER ) .
*
* @return This object.
*/
public Builder disabled() {
return this.enabled(Enablement.NEVER);
}
/**
* The level of detail to log on a request.
*
*
* - {@link CallLoggingDetail#STATUS_LINE STATUS_LINE} - Log only the status line.
*
- {@link CallLoggingDetail#HEADER HEADER} - Log the status line and headers.
*
- {@link CallLoggingDetail#ENTITY ENTITY} - Log the status line and headers and content if available.
*
*
* @param value
* The new value for this property, or null to inherit from the call logger.
* @return This object.
*/
public Builder requestDetail(CallLoggingDetail value) {
this.requestDetail = value;
return this;
}
/**
* The level of detail to log on a response.
*
*
* - {@link CallLoggingDetail#STATUS_LINE STATUS_LINE} - Log only the status line.
*
- {@link CallLoggingDetail#HEADER HEADER} - Log the status line and headers.
*
- {@link CallLoggingDetail#ENTITY ENTITY} - Log the status line and headers and content if available.
*
*
* @param value
* The new value for this property, or null to inherit from the call logger.
* @return This object.
*/
public Builder responseDetail(CallLoggingDetail value) {
this.responseDetail = value;
return this;
}
/**
* The logging level to use for logging the request/response.
*
*
* The default value is {@link Level#INFO}.
*
* @param value
* The new value for this property, or null to inherit from the call logger.
* @return This object.
*/
public Builder level(Level value) {
this.level = value;
return this;
}
/**
* Log a stack trace as part of the log entry.
*
*
* The default value is false .
*
* @return This object.
*/
public Builder logStackTrace() {
this.logStackTrace = true;
return this;
}
//
@Override /* GENERATED - org.apache.juneau.BeanBuilder */
public Builder impl(Object value) {
super.impl(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.BeanBuilder */
public Builder type(Class> value) {
super.type(value);
return this;
}
//
}
//-----------------------------------------------------------------------------------------------------------------
// Instance
//-----------------------------------------------------------------------------------------------------------------
private final Predicate statusFilter;
private final Predicate requestFilter;
private final Predicate responseFilter;
private final Predicate exceptionFilter;
private final Level level;
private final Enablement enabled;
private final Predicate enabledTest;
private final CallLoggingDetail requestDetail, responseDetail;
/**
* Constructor.
*
* @param b Builder
*/
CallLoggerRule(Builder b) {
this.statusFilter = b.statusFilter;
this.exceptionFilter = b.exceptionFilter;
this.requestFilter = b.requestFilter;
this.responseFilter = b.responseFilter;
this.level = b.level;
this.enabled = b.enabled;
this.enabledTest = b.enabledTest;
this.requestDetail = b.requestDetail;
this.responseDetail = b.responseDetail;
}
/**
* Returns true if this rule matches the specified parameters.
*
* @param req The HTTP request being logged. Never null .
* @param res The HTTP response being logged. Never null .
* @return true if this rule matches the specified parameters.
*/
public boolean matches(HttpServletRequest req, HttpServletResponse res) {
if ((requestFilter != null && ! requestFilter.test(req)) || (responseFilter != null && ! responseFilter.test(res)))
return false;
if (statusFilter != null && ! statusFilter.test(res.getStatus()))
return false;
Throwable e = (Throwable)req.getAttribute("Exception");
if (e != null && exceptionFilter != null && ! exceptionFilter.test(e))
return false;
return true;
}
/**
* Returns the detail level for HTTP requests.
*
* @return the detail level for HTTP requests, or null if it's not set.
*/
public CallLoggingDetail getRequestDetail() {
return requestDetail;
}
/**
* Returns the detail level for HTTP responses.
*
* @return the detail level for HTTP responses, or null if it's not set.
*/
public CallLoggingDetail getResponseDetail() {
return responseDetail;
}
/**
* Returns the log level on this rule.
*
* @return The log level on this rule, or null if it's not set.
*/
public Level getLevel() {
return level;
}
/**
* Returns the enablement flag value on this rule.
*
* @return The enablement flag value on this rule, or null if it's not set.
*/
public Enablement getEnabled() {
return enabled;
}
/**
* Returns the enablement predicate test on this rule.
*
* @return The enablement predicate test on this rule, or null if it's not set.
*/
public Predicate getEnabledTest() {
return enabledTest;
}
@Override /* Object */
public String toString() {
return filteredMap()
.append("codeFilter", statusFilter)
.append("exceptionFilter", exceptionFilter)
.append("requestFilter", requestFilter)
.append("responseFilter", responseFilter)
.append("level", level)
.append("requestDetail", requestDetail)
.append("responseDetail", responseDetail)
.append("enabled", enabled)
.append("enabledTest", enabledTest)
.asReadableString();
}
}