Enable sshd_log and httpd_log to use log4j config

At the moment log4j configuration is a bit inconsistent: it is
possible to configure error_log and gc_log using file provided
with log4j.configuration system property, however httpd_log and
sshd_log configuration is hard-coded in corresponding classes
(HttpLog and SshLog).

Make logs configuration more consistent by using log4j for all
logs. If log4j.configuration variable is not set, log behavior
remains intact and code-level log configuration will be used.

In case of log4.configuration points to log4j.properties file the
hard-coded configuration will be ommited and log4j.properties will
be used instead.

In addition shouldConfigureLogSystem() call moved from ErrorLogFile
to LogUtil in com.google.gerrit.util package and removed deprecated
reference to log4j LogManager.DEFAULT_CONFIGURATION_KEY so that
gerrit common does not require log4j.

Two inner MyLayout classes (one from SshLog and one from HttpLog)
have been extracted to separate files and renamed accordingly to
enable to use them from log4j.properties file if required. At the
moment those are extracted as is - refactoring will follow.

Change-Id: Icb1a3787b98392a9df9bb2afa4dc857f8cfada3a
Signed-off-by: Eryk Szymanski <eryksz@gmail.com>
This commit is contained in:
Eryk Szymanski
2013-11-06 17:56:49 +01:00
committed by Shawn Pearce
parent 23e1a2e824
commit 66252ed8ea
10 changed files with 356 additions and 269 deletions

View File

@@ -18,11 +18,11 @@ import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.util.TimeUtil;
import com.google.gerrit.util.LogUtil;
import org.apache.log4j.Appender;
import org.apache.log4j.AsyncAppender;
import org.apache.log4j.DailyRollingFileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.ErrorHandler;
@@ -35,45 +35,48 @@ import org.eclipse.jgit.lib.Config;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
/** Writes the {@code httpd_log} file with per-request data. */
class HttpLog extends AbstractLifeCycle implements RequestLog {
private static final Logger log = Logger.getLogger(HttpLog.class);
private static final String LOG_NAME = "httpd_log";
private static final String P_HOST = "Host";
private static final String P_USER = "User";
private static final String P_METHOD = "Method";
private static final String P_RESOURCE = "Resource";
private static final String P_PROTOCOL = "Version";
private static final String P_STATUS = "Status";
private static final String P_CONTENT_LENGTH = "Content-Length";
private static final String P_REFERER = "Referer";
private static final String P_USER_AGENT = "User-Agent";
protected static final String P_HOST = "Host";
protected static final String P_USER = "User";
protected static final String P_METHOD = "Method";
protected static final String P_RESOURCE = "Resource";
protected static final String P_PROTOCOL = "Version";
protected static final String P_STATUS = "Status";
protected static final String P_CONTENT_LENGTH = "Content-Length";
protected static final String P_REFERER = "Referer";
protected static final String P_USER_AGENT = "User-Agent";
private final AsyncAppender async;
HttpLog(final SitePaths site, final Config config) {
final DailyRollingFileAppender dst = new DailyRollingFileAppender();
dst.setName(LOG_NAME);
dst.setLayout(new MyLayout());
dst.setEncoding("UTF-8");
dst.setFile(new File(resolve(site.logs_dir), LOG_NAME).getPath());
dst.setImmediateFlush(true);
dst.setAppend(true);
dst.setThreshold(Level.INFO);
dst.setErrorHandler(new DieErrorHandler());
dst.activateOptions();
dst.setErrorHandler(new LogLogHandler());
async = new AsyncAppender();
async.setBlocking(true);
async.setBufferSize(config.getInt("core", "asyncLoggingBufferSize", 64));
async.setLocationInfo(false);
async.addAppender(dst);
if (LogUtil.shouldConfigureLogSystem()) {
final DailyRollingFileAppender dst = new DailyRollingFileAppender();
dst.setName(LOG_NAME);
dst.setLayout(new HttpLogLayout());
dst.setEncoding("UTF-8");
dst.setFile(new File(resolve(site.logs_dir), LOG_NAME).getPath());
dst.setImmediateFlush(true);
dst.setAppend(true);
dst.setThreshold(Level.INFO);
dst.setErrorHandler(new DieErrorHandler());
dst.activateOptions();
dst.setErrorHandler(new LogLogHandler());
async.addAppender(dst);
} else {
Appender appender = log.getAppender(LOG_NAME);
if (appender != null) {
async.addAppender(appender);
}
}
async.activateOptions();
}
@@ -153,105 +156,6 @@ class HttpLog extends AbstractLifeCycle implements RequestLog {
}
}
private static final class MyLayout extends Layout {
private final SimpleDateFormat dateFormat;
private long lastTimeMillis;
private String lastTimeString;
MyLayout() {
final TimeZone tz = TimeZone.getDefault();
dateFormat = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss Z");
dateFormat.setTimeZone(tz);
lastTimeMillis = TimeUtil.nowMs();
lastTimeString = dateFormat.format(new Date(lastTimeMillis));
}
@Override
public String format(LoggingEvent event) {
final StringBuilder buf = new StringBuilder(128);
opt(buf, event, P_HOST);
buf.append(' ');
buf.append('-'); // identd on client system (never requested)
buf.append(' ');
opt(buf, event, P_USER);
buf.append(' ');
buf.append('[');
formatDate(event.getTimeStamp(), buf);
buf.append(']');
buf.append(' ');
buf.append('"');
buf.append(event.getMDC(P_METHOD));
buf.append(' ');
buf.append(event.getMDC(P_RESOURCE));
buf.append(' ');
buf.append(event.getMDC(P_PROTOCOL));
buf.append('"');
buf.append(' ');
buf.append(event.getMDC(P_STATUS));
buf.append(' ');
opt(buf, event, P_CONTENT_LENGTH);
buf.append(' ');
dq_opt(buf, event, P_REFERER);
buf.append(' ');
dq_opt(buf, event, P_USER_AGENT);
buf.append('\n');
return buf.toString();
}
private void opt(StringBuilder buf, LoggingEvent event, String key) {
String val = (String) event.getMDC(key);
if (val == null) {
buf.append('-');
} else {
buf.append(val);
}
}
private void dq_opt(StringBuilder buf, LoggingEvent event, String key) {
String val = (String) event.getMDC(key);
if (val == null) {
buf.append('-');
} else {
buf.append('"');
buf.append(val);
buf.append('"');
}
}
private void formatDate(final long now, final StringBuilder sbuf) {
final long rounded = now - (int) (now % 1000);
if (rounded != lastTimeMillis) {
synchronized (dateFormat) {
lastTimeMillis = rounded;
lastTimeString = dateFormat.format(new Date(lastTimeMillis));
sbuf.append(lastTimeString);
}
} else {
sbuf.append(lastTimeString);
}
}
@Override
public boolean ignoresThrowable() {
return true;
}
@Override
public void activateOptions() {
}
}
private static final class DieErrorHandler implements ErrorHandler {
@Override
public void error(String message, Exception e, int errorCode,

View File

@@ -0,0 +1,122 @@
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed 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 com.google.gerrit.pgm.http.jetty;
import org.apache.log4j.Layout;
import org.apache.log4j.spi.LoggingEvent;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public final class HttpLogLayout extends Layout {
private final SimpleDateFormat dateFormat;
private long lastTimeMillis;
private String lastTimeString;
HttpLogLayout() {
final TimeZone tz = TimeZone.getDefault();
dateFormat = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss Z");
dateFormat.setTimeZone(tz);
lastTimeMillis = System.currentTimeMillis();
lastTimeString = dateFormat.format(new Date(lastTimeMillis));
}
@Override
public String format(LoggingEvent event) {
final StringBuilder buf = new StringBuilder(128);
opt(buf, event, HttpLog.P_HOST);
buf.append(' ');
buf.append('-'); // identd on client system (never requested)
buf.append(' ');
opt(buf, event, HttpLog.P_USER);
buf.append(' ');
buf.append('[');
formatDate(event.getTimeStamp(), buf);
buf.append(']');
buf.append(' ');
buf.append('"');
buf.append(event.getMDC(HttpLog.P_METHOD));
buf.append(' ');
buf.append(event.getMDC(HttpLog.P_RESOURCE));
buf.append(' ');
buf.append(event.getMDC(HttpLog.P_PROTOCOL));
buf.append('"');
buf.append(' ');
buf.append(event.getMDC(HttpLog.P_STATUS));
buf.append(' ');
opt(buf, event, HttpLog.P_CONTENT_LENGTH);
buf.append(' ');
dq_opt(buf, event, HttpLog.P_REFERER);
buf.append(' ');
dq_opt(buf, event, HttpLog.P_USER_AGENT);
buf.append('\n');
return buf.toString();
}
private void opt(StringBuilder buf, LoggingEvent event, String key) {
String val = (String) event.getMDC(key);
if (val == null) {
buf.append('-');
} else {
buf.append(val);
}
}
private void dq_opt(StringBuilder buf, LoggingEvent event, String key) {
String val = (String) event.getMDC(key);
if (val == null) {
buf.append('-');
} else {
buf.append('"');
buf.append(val);
buf.append('"');
}
}
private void formatDate(final long now, final StringBuilder sbuf) {
final long rounded = now - (int) (now % 1000);
if (rounded != lastTimeMillis) {
synchronized (dateFormat) {
lastTimeMillis = rounded;
lastTimeString = dateFormat.format(new Date(lastTimeMillis));
sbuf.append(lastTimeString);
}
} else {
sbuf.append(lastTimeString);
}
}
@Override
public boolean ignoresThrowable() {
return true;
}
@Override
public void activateOptions() {
}
}

View File

@@ -14,9 +14,9 @@
package com.google.gerrit.pgm.util;
import com.google.common.base.Strings;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.util.LogUtil;
import org.apache.log4j.Appender;
import org.apache.log4j.ConsoleAppender;
@@ -34,8 +34,6 @@ import java.io.FileNotFoundException;
import java.io.IOException;
public class ErrorLogFile {
@SuppressWarnings("deprecation")
private static final String LOG4J_CONFIGURATION = LogManager.DEFAULT_CONFIGURATION_KEY;
static final String LOG_NAME = "error_log";
public static void errorOnlyConsole() {
@@ -60,7 +58,7 @@ public class ErrorLogFile {
if (!logdir.exists() && !logdir.mkdirs()) {
throw new Die("Cannot create log directory: " + logdir);
}
if (shouldConfigureLogSystem()) {
if (LogUtil.shouldConfigureLogSystem()) {
initLogSystem(logdir);
}
@@ -76,10 +74,6 @@ public class ErrorLogFile {
};
}
public static boolean shouldConfigureLogSystem() {
return Strings.isNullOrEmpty(System.getProperty(LOG4J_CONFIGURATION));
}
private static void initLogSystem(final File logdir) {
final PatternLayout layout = new PatternLayout();
layout.setConversionPattern("[%d] %-5p %c %x: %m%n");

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.pgm.util;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GarbageCollection;
import com.google.gerrit.util.LogUtil;
import org.apache.log4j.Appender;
import org.apache.log4j.DailyRollingFileAppender;
@@ -42,7 +43,7 @@ public class GarbageCollectionLogFile {
if (!logdir.exists() && !logdir.mkdirs()) {
throw new Die("Cannot create log directory: " + logdir);
}
if (ErrorLogFile.shouldConfigureLogSystem()) {
if (LogUtil.shouldConfigureLogSystem()) {
initLogSystem(logdir);
}