io.airlift.http.server.DelimitedRequestLog Maven / Gradle / Ivy
/*
* Copyright 2010 Proofpoint, Inc.
*
* 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 io.airlift.http.server;
import ch.qos.logback.core.ContextBase;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP;
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy;
import io.airlift.event.client.EventClient;
import io.airlift.log.Logger;
import io.airlift.tracetoken.TraceTokenManager;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Response;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import static io.airlift.http.server.HttpRequestEvent.createHttpRequestEvent;
class DelimitedRequestLog
implements RequestLog
{
private static final Logger log = Logger.get(DelimitedRequestLog.class);
private static final String TEMP_FILE_EXTENSION = ".tmp";
private static final String LOG_FILE_EXTENSION = ".log";
// Tab-separated
// Time, ip, method, url, user, agent, response code, request length, response length, response time
private final TraceTokenManager traceTokenManager;
private final EventClient eventClient;
private final CurrentTimeMillisProvider currentTimeMillisProvider;
private final RollingFileAppender fileAppender;
public DelimitedRequestLog(String filename, int retainDays, TraceTokenManager traceTokenManager, EventClient eventClient)
throws IOException
{
this(filename, retainDays, traceTokenManager, eventClient, new SystemCurrentTimeMillisProvider());
}
public DelimitedRequestLog(String filename,
int retainDays,
TraceTokenManager traceTokenManager,
EventClient eventClient,
CurrentTimeMillisProvider currentTimeMillisProvider)
throws IOException
{
this.traceTokenManager = traceTokenManager;
this.eventClient = eventClient;
this.currentTimeMillisProvider = currentTimeMillisProvider;
ContextBase context = new ContextBase();
HttpLogLayout httpLogLayout = new HttpLogLayout();
recoverTempFiles(filename);
fileAppender = new RollingFileAppender<>();
SizeAndTimeBasedFNATP triggeringPolicy = new SizeAndTimeBasedFNATP<>();
TimeBasedRollingPolicy rollingPolicy = new TimeBasedRollingPolicy<>();
rollingPolicy.setContext(context);
rollingPolicy.setFileNamePattern(filename + "-%d{yyyy-MM-dd}.%i.log.gz");
rollingPolicy.setMaxHistory(retainDays);
rollingPolicy.setTimeBasedFileNamingAndTriggeringPolicy(triggeringPolicy);
rollingPolicy.setParent(fileAppender);
rollingPolicy.start();
triggeringPolicy.setContext(context);
triggeringPolicy.setTimeBasedRollingPolicy(rollingPolicy);
triggeringPolicy.setMaxFileSize(String.valueOf(Long.MAX_VALUE));
triggeringPolicy.start();
fileAppender.setContext(context);
fileAppender.setFile(filename);
fileAppender.setAppend(true);
fileAppender.setLayout(httpLogLayout);
fileAppender.setRollingPolicy(rollingPolicy);
fileAppender.start();
}
public void log(Request request, Response response)
{
long currentTime = currentTimeMillisProvider.getCurrentTimeMillis();
HttpRequestEvent event = createHttpRequestEvent(request, response, traceTokenManager, currentTime);
fileAppender.doAppend(event);
eventClient.post(event);
}
public void start()
throws Exception
{
}
public void stop()
throws Exception
{
fileAppender.stop();
}
public boolean isRunning()
{
return true;
}
public boolean isStarted()
{
return true;
}
public boolean isStarting()
{
return false;
}
public boolean isStopping()
{
return false;
}
public boolean isStopped()
{
return false;
}
public boolean isFailed()
{
return false;
}
public void addLifeCycleListener(Listener listener)
{
}
public void removeLifeCycleListener(Listener listener)
{
}
private static void recoverTempFiles(String logPath)
{
// logback has a tendency to leave around temp files if it is interrupted
// these .tmp files are log files that are about to be compressed.
// This method recovers them so that they aren't orphaned
File logPathFile = new File(logPath).getParentFile();
File[] tempFiles = logPathFile.listFiles(new FilenameFilter()
{
@Override
public boolean accept(File dir, String name)
{
return name.endsWith(TEMP_FILE_EXTENSION);
}
});
if (tempFiles != null) {
for (File tempFile : tempFiles) {
String newName = tempFile.getName().substring(0, tempFile.getName().length() - TEMP_FILE_EXTENSION.length());
File newFile = new File(tempFile.getParent(), newName + LOG_FILE_EXTENSION);
if (tempFile.renameTo(newFile)) {
log.info("Recovered temp file: %s", tempFile);
}
else {
log.warn("Could not rename temp file [%s] to [%s]", tempFile, newFile);
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy