- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 java 1.7 中使用 log4j2 (beta9)。
我完整的 log4j2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Properties>
<Property name="projectPrefix">Tts</Property>
<Property name="rawPattern">%d %-5p [%t] %C{2} (%F:%L) - %m%n</Property>
<Property name="coloredPattern">%d %highlight{%-5p}{FATAL=bright red, ERROR=red, WARN=yellow, INFO=cyan, DEBUG=green, TRACE=bright blue} %style{[%t] %C{2} (%F:%L) -}{bright,black} %m%n</Property>
<Property name="fileName">Log/${projectPrefix}.log</Property>
<Property name="filePattern">Log/${projectPrefix}-%i.log</Property>
</Properties>
<Appenders>
<Console name="Stdout" target="SYSTEM_OUT">
<PatternLayout pattern="${coloredPattern}"/>
</Console>
<RollingFile name="Logfile" fileName="${fileName}" filePattern="${filePattern}">
<PatternLayout pattern="${rawPattern}"/>
<Policies>
<SizeBasedTriggeringPolicy size="16 MB"/>
</Policies>
<DefaultRolloverStrategy fileIndex="min" max="16"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Stdout"/>
<AppenderRef ref="Logfile"/>
</Root>
</Loggers>
</Configuration>
我想在每个日志文件的顶部添加一些自定义信息,例如我的应用程序的版本字符串、应用程序正常运行时间和系统正常运行时间。甚至在刚刚关闭的日志文件的底部写一些 »bye, bye/eof« 也可以。
当 RollingFileAppander 创建了一个新文件时,是否有类似钩子(Hook)或回调的东西来得到通知,以便我可以首先将我的东西放入这些新日志文件(或任何其他建议)?
最佳答案
好的,通过像 here 中描述的那样扩展 DefaultRolloverStrategy,可以解决这个问题。 .但是
要让log4j2调用我们的工厂方法,log4j2.xml的根标签必须带有我们类的包属性,例如:
<Configuration packages="de.jme.toolbox.logging">
...
</Configuration>
在我们自己的 RolloverStrategy 中,我们必须处理 @Plugin
和 @PluginFactory
,如 here 所述.
最后是我完整的 log4j2.xml(您不需要所有这些属性 - 这正是我喜欢的配置日志记录的方式):
<?xml version="1.0" encoding="UTF-8"?>
<Configuration packages="de.jme.toolbox.logging">
<Properties>
<Property name="projectPrefix">Tts</Property>
<Property name="rawPattern">%d %-5p [%t] %C{2} (%F:%L) - %m%n</Property>
<Property name="coloredPattern">%d %highlight{%-5p}{FATAL=bright red, ERROR=red, WARN=yellow, INFO=cyan, DEBUG=green, TRACE=bright blue} %style{[%t] %C{2} (%F:%L) -}{bright,black} %m%n</Property>
<Property name="coloredShortPattern">%d %highlight{%-5p}{FATAL=bright red, ERROR=red, WARN=yellow, INFO=cyan, DEBUG=green, TRACE=bright blue} %style{[%t] -}{bright,black} %m%n</Property>
<Property name="fileName">Log/${projectPrefix}.log</Property>
<Property name="filePattern">Log/${projectPrefix}-%i.log</Property>
</Properties>
<Appenders>
<Console name="Stdout" target="SYSTEM_OUT">
<PatternLayout pattern="${coloredPattern}"/>
</Console>
<RollingFile name="Logfile" fileName="${fileName}" filePattern="${filePattern}">
<PatternLayout pattern="${rawPattern}"/>
<Policies>
<SizeBasedTriggeringPolicy size="1 MB"/>
</Policies>
<MyRolloverStrategy fileIndex="min" max="16"/>
</RollingFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Stdout"/>
<AppenderRef ref="Logfile"/>
</Root>
</Loggers>
</Configuration>
这里是 MyRolloverStrategy.java:
package de.jme.toolbox.logging;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.zip.Deflater;
import org.apache.logging.log4j.core.appender.rolling.DefaultRolloverStrategy;
import org.apache.logging.log4j.core.appender.rolling.RollingFileManager;
import org.apache.logging.log4j.core.appender.rolling.RolloverDescription;
import org.apache.logging.log4j.core.appender.rolling.helper.Action;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginConfiguration;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
import org.apache.logging.log4j.core.helpers.Integers;
import org.apache.logging.log4j.core.lookup.StrSubstitutor;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.status.StatusLogger;
/**
* Own RolloverStrategy to hook the DefaultRolloverStrategy's rollover events
*
* Siehe auch:
* - https://issues.apache.org/jira/browse/LOG4J2-486
* - http://apache-logging.6191.n7.nabble.com/log4j2-getting-started-amp-rolling-files-tt8406.html#a42402
* - http://stackoverflow.com/questions/20819376/log4j2-rollingfile-appender-add-custom-info-at-the-start-of-each-logfile
*
* @author Joe Merten
*/
@org.apache.logging.log4j.core.config.plugins.Plugin(name="MyRolloverStrategy", category="Core", printObject=true)
public class MyRolloverStrategy extends DefaultRolloverStrategy {
protected static final Logger logger = StatusLogger.getLogger();
// ==============================
// ↓↓↓ Some stuff copied from ↓↓↓
// https://svn.apache.org/repos/asf/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java r1556050
// Just changed »DefaultRolloverStrategy« to »MyRolloverStrategy«
private static final int MIN_WINDOW_SIZE = 1;
private static final int DEFAULT_WINDOW_SIZE = 7;
@PluginFactory
public static MyRolloverStrategy createStrategy(
@PluginAttribute("max") final String max,
@PluginAttribute("min") final String min,
@PluginAttribute("fileIndex") final String fileIndex,
@PluginAttribute("compressionLevel") final String compressionLevelStr,
@PluginConfiguration final Configuration config) {
final boolean useMax = fileIndex == null ? true : fileIndex.equalsIgnoreCase("max");
int minIndex;
if (min != null) {
minIndex = Integer.parseInt(min);
if (minIndex < 1) {
LOGGER.error("Minimum window size too small. Limited to " + MIN_WINDOW_SIZE);
minIndex = MIN_WINDOW_SIZE;
}
} else {
minIndex = MIN_WINDOW_SIZE;
}
int maxIndex;
if (max != null) {
maxIndex = Integer.parseInt(max);
if (maxIndex < minIndex) {
maxIndex = minIndex < DEFAULT_WINDOW_SIZE ? DEFAULT_WINDOW_SIZE : minIndex;
LOGGER.error("Maximum window size must be greater than the minimum windows size. Set to " + maxIndex);
}
} else {
maxIndex = DEFAULT_WINDOW_SIZE;
}
final int compressionLevel = Integers.parseInt(compressionLevelStr, Deflater.DEFAULT_COMPRESSION);
return new MyRolloverStrategy(minIndex, maxIndex, useMax, compressionLevel, config.getStrSubstitutor());
}
// ↑↑↑ Some stuff copied from ↑↑↑
// ==============================
protected MyRolloverStrategy(int minIndex, int maxIndex, boolean useMax, int compressionLevel, StrSubstitutor subst) {
super(minIndex, maxIndex, useMax, compressionLevel, subst);
}
// Wrapper class only for setting a hook to execute()
static class MyAction implements Action {
final Action delegate;
final String fileName;
public MyAction(final Action delegate, final String fileName) {
this.delegate = delegate;
this.fileName = fileName;
}
@Override public void run() {
delegate.run();
}
@Override public boolean execute() throws IOException {
try {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(new File(fileName), true));
writer.write("****************************\n");
writer.write("*** Bye, bye old logfile ***\n");
writer.write("****************************\n");
} finally {
if (writer != null)
writer.close();
}
} catch (Throwable e) {
logger.error("Writing to bottom of old logfile \"" + fileName + "\" with", e);
}
boolean ret = delegate.execute();
try {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(new File(fileName), true));
writer.write("*************************\n");
writer.write("*** Hello new logfile ***\n");
writer.write("*************************\n");
} finally {
if (writer != null)
writer.close();
}
} catch (Throwable e) {
logger.error("Writing to top of new logfile \"" + fileName + "\" with", e);
}
return ret;
}
@Override public void close() {
delegate.close();
}
@Override public boolean isComplete() {
return delegate.isComplete();
}
}
// Wrapper class only for setting a hook to getSynchronous().execute()
static class MyRolloverDescription implements RolloverDescription {
final RolloverDescription delegate;
public MyRolloverDescription(final RolloverDescription delegate) {
this.delegate = delegate;
}
@Override public String getActiveFileName() {
return delegate.getActiveFileName();
}
@Override public boolean getAppend() {
//return delegate.getAppend();
// As long as we already put some data to the top of the new logfile, subsequent writes should be performed with "append".
return true;
}
// The synchronous action is for renaming, here we want to hook
@Override public Action getSynchronous() {
Action delegateAction = delegate.getSynchronous();
if (delegateAction == null) return null;
return new MyAction(delegateAction, delegate.getActiveFileName());
}
// The asynchronous action is for compressing, we don't need to hook here
@Override public Action getAsynchronous() {
return delegate.getAsynchronous();
}
}
public RolloverDescription rollover(final RollingFileManager manager) {
RolloverDescription ret = super.rollover(manager);
return new MyRolloverDescription(ret);
}
}
如果我发布了 feature request,那么在 log4j2 的 future 版本中解决这个要求可能会更容易将实现。
关于java - Log4j2 RollingFile Appender - 在每个日志文件的开头添加自定义信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20819376/
2种参数:尺寸和价格。目前,我只能单击选择/突出显示尺寸列中的一个,也只能单击选择/突出显示价格列中的一个,而不会影响另一个列中的一个。 当我点击尺寸时,会添加一个 URL 参数“#size=4”。单
在css命名约定中,有什么原因,一些object最好以前缀o-和component开头> 以 c- 开头? 我知道 o- 代表 object 而 c- 代表 component,但为什么不呢?难道我们
这就很迷惑了,一下子,下面的代码就不行了。尝试让我的 Android 很好地显示网页已经显示的内容: HttpClient httpclient = new DefaultHttpClient();
我正在将我的网站发布到我无法控制的 IIS 服务器,我想从代码隐藏中了解它的 URL 是否以“http”或“https”开头。 首先,我在本地尝试了这两种解决方案,都返回了正确的值(“http”):
如果我运行: sbin/start-dfs.sh 然后它实际上并没有启动一个名称节点尽管打印: Starting namenodes on [0.0.0.0] 0.0.0.0: starting na
我正在开发一个包含一些数组的模块。现在我的数组包含: $omearray = array ( '#title' = 'title', 0 = array ( 'another array',
对于 PMD,我希望有一个规则来警告我那些以 my 开头的丑陋变量。 这意味着我必须接受所有不以my开头的变量。 所以,我需要一个正则表达式(re),其行为如下: re.match('myVar')
出于某种奇怪的原因,当我尝试使用 URLConnection 获取网页源时,我在输出中得到“null”。有人可以解释一下吗? 我的方法: public String getPageSource()
如何批量检查某个字符串(记录文本文件中的行)是否以特定单词开头? 我知道如何检查句子/行(字符串)中是否存在单词(子字符串),但我如何检查天气是否以这个词开头? 谢谢:) 最佳答案 这可以通过 FIN
我有一个列表,其中包含多个网址和一些字符串,例如#skipsideNav、#content。我正在从这些字符串中分离出 url if link.startswith('/'): local_u
我有以下 html 标记: 我想选择类 bubble bubble_white 和 bubble bubble_black。我正在考虑下面的代码,但它不起作用: $(".bubbl
我有一个用于文件名验证的正则表达式。在这里: /^[0-9a-zA-Z\^\&\'\@\{\}\[\]\,\$\=\!\-\#\(\)\.\%\+\~\_; ]+$/ 如何更改它以检查文件名不是以
我正在构建一个自动填充函数,它接受一个字符串输入并返回一个字符串建议列表。 Sequelize 的 iLike:query返回出现查询字符串的每个字符串。我想支持查询是前缀的字符串。例如当query=
我首先知道这可能是有史以来看起来最糟糕的正则表达式,但这里是。 我有这个正则表达式 (?:http://)?(?:www.)?youtu(?:be)?.(?:[a-z]){2,3}(?:[a-z/?=
尝试读取文件并根据行创建字典,跳过以#符号开头的行 文件示例: param1=val1 # here is comment 我的功能: def readFromFile(name): conf
我的程序正在读取文本文件并根据文本执行操作。但是文本的第一行是有问题的。显然它以“”开头。这弄乱了我的 startsWith() 检查。 为了理解这个问题,我使用了这段代码: System.ou
我的印象是变量名只能以字母和 _ 开头,但是在测试时,我还发现变量名可以以 $ 开头,如下所示: 代码 #include int main() { int myvar=13; int
我试过这个... Dim myMatches As String() = System.Text.RegularExpressions.Regex.Split(postRow.Item("Post")
开头
我正在使用CKEditor,默认情况下在内容的开头添加了。 即使将enterMode设置为,它也只会影响Enter键的作用,并保留开始的。 我遇到的问题是,如果文本以标记开头,它将围绕它包装,并且图像
我有一个List ,其中有五个字符串: abc def ghi jkl mno 我还有另一个字符串“pq”,我需要知道列表中的每个字符串是否都不以“pq”开头-我将如何使用LINQ(.NET 4.0)
我是一名优秀的程序员,十分优秀!