All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.velocity.runtime.parser.LogContext Maven / Gradle / Ivy

The newest version!
package org.apache.velocity.runtime.parser;

/*
 * 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.
 */

import org.apache.velocity.runtime.parser.node.SimpleNode;
import org.apache.velocity.util.introspection.Info;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;

/**
 * 

Track location in template files during rendering by populating the slf4j MDC tags file, line and column.

*

An MDC-aware logger can then use this info to display the template location in the message

*

For instance with webapp-slf4j-logger, it's enough to use %file, %line and %column in the logger format string.

*

Since this feature can have a performance impact, it has to be enabled in velocity.properties using:

*
runtime.log.track_location = true
*

(typically in a development environment)

* * @author Claude Brisson * @version $Id:$ * @since 2.2 */ public class LogContext { protected static Logger logger = LoggerFactory.getLogger("rendering"); public static final String MDC_FILE = "file"; public static final String MDC_LINE = "line"; public static final String MDC_COLUMN = "column"; private boolean trackLocation; public LogContext(boolean trackLocation) { this.trackLocation = trackLocation; } private static ThreadLocal> contextStack = new ThreadLocal>() { @Override public Deque initialValue() { return new ArrayDeque<>(); } }; private static class StackElement { protected StackElement(SimpleNode src, Info info) { this.src = src; this.info = info; } protected SimpleNode src; protected int count = 1; protected Info info; } public void pushLogContext(SimpleNode src, Info info) { if (!trackLocation) { return; } Deque stack = contextStack.get(); StackElement last = stack.peek(); if (last != null && last.src == src) { ++last.count; } else { stack.push(new StackElement(src, info)); setLogContext(info); } } public void popLogContext() { if (!trackLocation) { return; } Deque stack = contextStack.get(); StackElement last = stack.peek(); if (last == null) { logger.error("log context is already empty"); return; } if (--last.count == 0) { stack.pop(); last = stack.peek(); if (last == null) { clearLogContext(); } else { setLogContext(last.info); } } } private void setLogContext(Info info) { MDC.put(MDC_FILE, info.getTemplateName()); MDC.put(MDC_LINE, String.valueOf(info.getLine())); MDC.put(MDC_COLUMN, String.valueOf(info.getColumn())); } private void clearLogContext() { MDC.remove(MDC_FILE); MDC.remove(MDC_LINE); MDC.remove(MDC_COLUMN); } private static final String STACKTRACE_LINE = " %s at %s[line %d, column %d]"; public String[] getStackTrace() { if (!trackLocation) { return null; } Deque stack = contextStack.get(); List levels = new ArrayList<>(); for (StackElement level : stack) { String line = String.format(STACKTRACE_LINE, level.src.literal(), level.info.getTemplateName(), level.info.getLine(), level.info.getColumn()); levels.add(line); } return levels.size() > 0 ? levels.toArray(new String[levels.size()]) : null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy