daemon: Automatically log into $site_path/logs
We now save daemon log files into $site_path/logs, rolling over once per day using the DailyRollingFileAppender class from log4j. Current messages are written to $site_path/logs/error_log until the end of a day is reached in GMT, and then its renamed to an archive file suffixed with the 'yyyy-mm-dd' format. Because the daemon is meant to run in the background and service user requests, the log messages are automatically redirect to the log file by default. An administrator can force us to send log messages to stderr again by using the new option --console-log. Bug: issue 328 Change-Id: I6add1d2ac8faf57c6ca17964a7e88a2afacfb094 Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
parent
22a17f4c64
commit
a9d39fcc9f
|
@ -11,6 +11,7 @@ SYNOPSIS
|
|||
'java' -DGerritServer=PATH -jar gerrit.war 'daemon'
|
||||
[\--enable-httpd | \--disable-httpd]
|
||||
[\--enable-sshd | \--disable-sshd]
|
||||
[\--console-log]
|
||||
[\--slave]
|
||||
|
||||
DESCRIPTION
|
||||
|
@ -47,12 +48,23 @@ OPTIONS
|
|||
+
|
||||
This option automatically implies '\--disable-httpd \--enable-sshd'.
|
||||
|
||||
\--console-log::
|
||||
Send log messages to the console, instead of to the standard
|
||||
log file '$site_path/logs/error_log'.
|
||||
|
||||
CONTEXT
|
||||
-------
|
||||
This command can only be run on a server which has direct
|
||||
connectivity to the metadata database, and local access to the
|
||||
managed Git repositories.
|
||||
|
||||
LOGGING
|
||||
-------
|
||||
Error and warning messages from the server are automatically written
|
||||
to the log file under '$site_path/logs/error_log'. This log file
|
||||
is automatically rotated at 12:00 AM GMT each day, allowing an
|
||||
external log cleaning service to clean up the prior logs.
|
||||
|
||||
KNOWN ISSUES
|
||||
------------
|
||||
Slave daemon caches can quickly become out of date when modifications
|
||||
|
|
|
@ -33,6 +33,11 @@ limitations under the License.
|
|||
</description>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-dbcp</groupId>
|
||||
<artifactId>commons-dbcp</artifactId>
|
||||
|
|
|
@ -63,6 +63,9 @@ public class Daemon extends SiteProgram {
|
|||
@Option(name = "--slave", usage = "Support fetch only; implies --disable-httpd")
|
||||
private boolean slave;
|
||||
|
||||
@Option(name = "--console-log", usage = "Log to console (not $site_path/logs)")
|
||||
private boolean consoleLog;
|
||||
|
||||
private final LifecycleManager manager = new LifecycleManager();
|
||||
private Injector dbInjector;
|
||||
private Injector cfgInjector;
|
||||
|
@ -88,6 +91,11 @@ public class Daemon extends SiteProgram {
|
|||
throw die("--enable-httpd currently requires --enable-sshd");
|
||||
}
|
||||
|
||||
if (consoleLog) {
|
||||
} else {
|
||||
manager.add(ErrorLogFile.start(getSitePath()));
|
||||
}
|
||||
|
||||
dbInjector = createDbInjector();
|
||||
cfgInjector = createCfgInjector();
|
||||
sysInjector = createSysInjector();
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
// Copyright (C) 2009 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;
|
||||
|
||||
import com.google.gerrit.lifecycle.LifecycleListener;
|
||||
|
||||
import org.apache.log4j.Appender;
|
||||
import org.apache.log4j.DailyRollingFileAppender;
|
||||
import org.apache.log4j.Level;
|
||||
import org.apache.log4j.LogManager;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.apache.log4j.PatternLayout;
|
||||
import org.apache.log4j.helpers.OnlyOnceErrorHandler;
|
||||
import org.apache.log4j.spi.ErrorHandler;
|
||||
import org.apache.log4j.spi.LoggingEvent;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class ErrorLogFile {
|
||||
public static LifecycleListener start(final File sitePath) {
|
||||
final File logdir = new File(sitePath, "logs");
|
||||
if (!logdir.exists() && !logdir.mkdirs()) {
|
||||
throw new Die("Cannot create log directory: " + logdir);
|
||||
}
|
||||
|
||||
final PatternLayout layout = new PatternLayout();
|
||||
layout.setConversionPattern("[%d] %-5p %c %x: %m%n");
|
||||
|
||||
final DailyRollingFileAppender dst = new DailyRollingFileAppender();
|
||||
dst.setName("error_log");
|
||||
dst.setLayout(layout);
|
||||
dst.setEncoding("UTF-8");
|
||||
dst.setFile(new File(logdir, "error_log").getAbsolutePath());
|
||||
dst.setImmediateFlush(true);
|
||||
dst.setAppend(true);
|
||||
dst.setThreshold(Level.INFO);
|
||||
dst.setErrorHandler(new DieErrorHandler());
|
||||
dst.activateOptions();
|
||||
dst.setErrorHandler(new OnlyOnceErrorHandler());
|
||||
|
||||
final Logger root = LogManager.getRootLogger();
|
||||
root.removeAllAppenders();
|
||||
root.addAppender(dst);
|
||||
|
||||
return new LifecycleListener() {
|
||||
@Override
|
||||
public void start() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
LogManager.shutdown();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private ErrorLogFile() {
|
||||
}
|
||||
|
||||
private static final class DieErrorHandler implements ErrorHandler {
|
||||
@Override
|
||||
public void error(String message, Exception e, int errorCode,
|
||||
LoggingEvent event) {
|
||||
error(e != null ? e.getMessage() : message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message, Exception e, int errorCode) {
|
||||
error(e != null ? e.getMessage() : message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String message) {
|
||||
throw new Die("Cannot open log file: " + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activateOptions() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAppender(Appender appender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackupAppender(Appender appender) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLogger(Logger logger) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -23,19 +23,27 @@ import org.slf4j.LoggerFactory;
|
|||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/** Tracks and executes registered {@link LifecycleListener}s. */
|
||||
public class LifecycleManager {
|
||||
private final List<Injector> injectors = new ArrayList<Injector>();
|
||||
private LifecycleListener[] listeners;
|
||||
private final LinkedHashMap<LifecycleListener, Boolean> listeners =
|
||||
new LinkedHashMap<LifecycleListener, Boolean>();
|
||||
|
||||
private boolean started;
|
||||
|
||||
/** Add a single listener. */
|
||||
public void add(final LifecycleListener listener) {
|
||||
listeners.put(listener, true);
|
||||
}
|
||||
|
||||
/** Add all {@link LifecycleListener}s registered in the Injector. */
|
||||
public void add(final Injector injector) {
|
||||
if (listeners != null) {
|
||||
if (started) {
|
||||
throw new IllegalStateException("Already started");
|
||||
}
|
||||
injectors.add(injector);
|
||||
for (final Binding<LifecycleListener> binding : get(injector)) {
|
||||
add(binding.getProvider().get());
|
||||
}
|
||||
}
|
||||
|
||||
/** Add all {@link LifecycleListener}s registered in the Injectors. */
|
||||
|
@ -47,10 +55,9 @@ public class LifecycleManager {
|
|||
|
||||
/** Start all listeners, in the order they were registered. */
|
||||
public void start() {
|
||||
if (listeners == null) {
|
||||
listeners = all();
|
||||
|
||||
for (LifecycleListener obj : listeners) {
|
||||
if (!started) {
|
||||
started = true;
|
||||
for (LifecycleListener obj : listeners.keySet()) {
|
||||
obj.start();
|
||||
}
|
||||
}
|
||||
|
@ -58,9 +65,12 @@ public class LifecycleManager {
|
|||
|
||||
/** Stop all listeners, in the reverse order they were registered. */
|
||||
public void stop() {
|
||||
if (listeners != null) {
|
||||
for (int i = listeners.length - 1; 0 <= i; i--) {
|
||||
final LifecycleListener obj = listeners[i];
|
||||
if (started) {
|
||||
final List<LifecycleListener> t =
|
||||
new ArrayList<LifecycleListener>(listeners.keySet());
|
||||
|
||||
for (int i = t.size() - 1; 0 <= i; i--) {
|
||||
final LifecycleListener obj = t.get(i);
|
||||
try {
|
||||
obj.stop();
|
||||
} catch (Throwable err) {
|
||||
|
@ -68,28 +78,10 @@ public class LifecycleManager {
|
|||
}
|
||||
}
|
||||
|
||||
listeners = null;
|
||||
started = false;
|
||||
}
|
||||
}
|
||||
|
||||
private LifecycleListener[] all() {
|
||||
final Map<LifecycleListener, Boolean> found =
|
||||
new LinkedHashMap<LifecycleListener, Boolean>();
|
||||
|
||||
for (final Injector injector : injectors) {
|
||||
if (injector == null) {
|
||||
continue;
|
||||
}
|
||||
for (final Binding<LifecycleListener> binding : get(injector)) {
|
||||
found.put(binding.getProvider().get(), true);
|
||||
}
|
||||
}
|
||||
|
||||
final LifecycleListener[] a = new LifecycleListener[found.size()];
|
||||
found.keySet().toArray(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
private static List<Binding<LifecycleListener>> get(Injector i) {
|
||||
return i.findBindingsByType(new TypeLiteral<LifecycleListener>() {});
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ log4j.rootCategory=DEBUG, stderr
|
|||
log4j.appender.stderr=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stderr.target=System.err
|
||||
log4j.appender.stderr.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stderr.layout.ConversionPattern=%d::%-5p: %c %x - %m%n
|
||||
log4j.appender.stderr.layout.ConversionPattern=[%d] %-5p %c %x: %m%n
|
||||
|
||||
log4j.logger.com.google.gerrit=INFO
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<booleanAttribute key="org.eclipse.jdt.debug.ui.CONSIDER_INHERITED_MAIN" value="true"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.maven.ide.eclipse.launchconfig.classpathProvider"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="Main"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="daemon"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="daemon --console-log"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="gerrit-war"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.maven.ide.eclipse.launchconfig.sourcepathProvider"/>
|
||||
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-Xmx256M -DGerritServer=${resource_loc:/gerrit-parent/GerritServer.properties}"/>
|
||||
|
|
Loading…
Reference in New Issue