| //// |
| 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 |
| |
| https://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. |
| //// |
| = Log4j 2 API |
| Ralph Goers <rgoers@apache.org> |
| |
| [#Markers] |
| == Markers |
| |
| One of the primary purpose of a logging framework is to provide the |
| means to generate debugging and diagnostic information only when it is |
| needed, and to allow filtering of that information so that it does not |
| overwhelm the system or the individuals who need to make use of it. As |
| an example, an application desires to log its entry, exit and other |
| operations separately from SQL statements being executed, and wishes to |
| be able to log queries separate from updates. One way to accomplish this |
| is shown below: |
| |
| [source,java] |
| ---- |
| import org.apache.logging.log4j.Logger; |
| import org.apache.logging.log4j.LogManager; |
| import org.apache.logging.log4j.MarkerManager; |
| import java.util.Map; |
| |
| public class MyApp { |
| |
| private Logger logger = LogManager.getLogger(MyApp.class.getName()); |
| private static final Marker SQL_MARKER = MarkerManager.getMarker("SQL"); |
| private static final Marker UPDATE_MARKER = MarkerManager.getMarker("SQL_UPDATE").setParents(SQL_MARKER); |
| private static final Marker QUERY_MARKER = MarkerManager.getMarker("SQL_QUERY").setParents(SQL_MARKER); |
| |
| public String doQuery(String table) { |
| logger.traceEntry(); |
| |
| logger.debug(QUERY_MARKER, "SELECT * FROM {}", table); |
| |
| String result = ... |
| |
| return logger.traceExit(result); |
| } |
| |
| public String doUpdate(String table, Map<String, String> params) { |
| logger.traceEntry(); |
| |
| if (logger.isDebugEnabled()) { |
| logger.debug(UPDATE_MARKER, "UPDATE {} SET {}", table, formatCols()); |
| } |
| |
| String result = ... |
| |
| return logger.traceExit(result); |
| } |
| |
| private String formatCols(Map<String, String> cols) { |
| StringBuilder sb = new StringBuilder(); |
| boolean first = true; |
| for (Map.Entry<String, String> entry : cols.entrySet()) { |
| if (!first) { |
| sb.append(", "); |
| } |
| sb.append(entry.getKey()).append("=").append(entry.getValue()); |
| first = false; |
| } |
| return sb.toString(); |
| } |
| } |
| ---- |
| |
| In the example above it is now possible to add MarkerFilters to only |
| allow SQL update operations to be logged, all SQL updates to be logged |
| or to log everything in MyApp. |
| |
| Some important rules about Markers must be considered when using them. |
| |
| 1. Markers must be unique. They are permanently registered by name so |
| care should be taken to insure that Markers used in your application are |
| distinct from those in the application's dependencies, unless that is |
| what is desired. |
| 2. Parent Markers can be added or removed dynamically. However, this is |
| fairly expensive to do. Instead, it is recommended that the parents be |
| identified when obtaining the Marker the first time as shown in the |
| examples above. Specifically, the set method replaces all the markers in |
| a single operation while add and remove act on only a single Marker at a |
| time. |
| 3. Evaluating Markers with multiple ancestors is much more expensive |
| than Markers with no parents. For example, in one set of tests to |
| evaluate whether a Marker matched its grandparent took 3 times longer |
| than evaluating the Marker itself. Even then though, evaluating Markers |
| is inexpensive compared to resolving the callers class name or line |
| number. |