![JAR search and dependency download from the Maven repository](/logo.png)
org.apache.oozie.util.XLogStreamer Maven / Gradle / Ivy
The newest version!
/**
* Copyright (c) 2010 Yahoo! Inc. All rights reserved.
* 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. See accompanying LICENSE file.
*/
package org.apache.oozie.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* XLogStreamer streams the given log file to logWriter after applying the given filter.
*/
public class XLogStreamer {
/**
* Filter that will construct the regular expression that will be used to filter the log statement. And also checks
* if the given log message go through the filter. Filters that can be used are logLevel(Multi values separated by
* "|") jobId appName actionId token
*/
public static class Filter {
private Map logLevels;
private Map filterParams;
private static List parameters = new ArrayList();
private boolean noFilter;
private Pattern filterPattern;
//TODO Patterns to be read from config file
private static final String DEFAULT_REGEX = "[^\\]]*";
public static final String ALLOW_ALL_REGEX = "(.*)";
private static final String TIMESTAMP_REGEX = "(\\d\\d\\d\\d-\\d\\d-\\d\\d \\d\\d:\\d\\d:\\d\\d,\\d\\d\\d)";
private static final String WHITE_SPACE_REGEX = "\\s+";
private static final String LOG_LEVEL_REGEX = "(\\w+)";
private static final String PREFIX_REGEX = TIMESTAMP_REGEX + WHITE_SPACE_REGEX + LOG_LEVEL_REGEX
+ WHITE_SPACE_REGEX;
private static final Pattern SPLITTER_PATTERN = Pattern.compile(PREFIX_REGEX + ALLOW_ALL_REGEX);
public Filter() {
filterParams = new HashMap();
for (int i = 0; i < parameters.size(); i++) {
filterParams.put(parameters.get(i), DEFAULT_REGEX);
}
logLevels = null;
noFilter = true;
filterPattern = null;
}
public void setLogLevel(String logLevel) {
if (logLevel != null && logLevel.trim().length() > 0) {
this.logLevels = new HashMap();
String[] levels = logLevel.split("\\|");
for (int i = 0; i < levels.length; i++) {
String s = levels[i].trim().toUpperCase();
try {
XLog.Level.valueOf(s);
}
catch (Exception ex) {
continue;
}
this.logLevels.put(levels[i].toUpperCase(), 1);
}
}
}
public void setParameter(String filterParam, String value) {
if (filterParams.containsKey(filterParam)) {
noFilter = false;
filterParams.put(filterParam, value);
}
}
public static void defineParameter(String filterParam) {
parameters.add(filterParam);
}
public boolean isFilterPresent() {
if (noFilter && logLevels == null) {
return false;
}
return true;
}
/**
* Checks if the logLevel and logMessage goes through the logFilter.
*
* @param logParts
* @return
*/
public boolean matches(ArrayList logParts) {
String logLevel = logParts.get(0);
String logMessage = logParts.get(1);
if (this.logLevels == null || this.logLevels.containsKey(logLevel.toUpperCase())) {
Matcher logMatcher = filterPattern.matcher(logMessage);
return logMatcher.matches();
}
else {
return false;
}
}
/**
* Splits the log line into timestamp, logLevel and remaining log message. Returns array containing logLevel and
* logMessage if the pattern matches i.e A new log statement, else returns null.
*
* @param logLine
* @return Array containing log level and log message
*/
public ArrayList splitLogMessage(String logLine) {
Matcher splitter = SPLITTER_PATTERN.matcher(logLine);
if (splitter.matches()) {
ArrayList logParts = new ArrayList();
logParts.add(splitter.group(2));// log level
logParts.add(splitter.group(3));// Log Message
return logParts;
}
else {
return null;
}
}
/**
* Constructs the regular expression according to the filter and assigns it to fileterPattarn. ".*" will be
* assigned if no filters are set.
*/
public void constructPattern() {
if (noFilter && logLevels == null) {
filterPattern = Pattern.compile(ALLOW_ALL_REGEX);
return;
}
StringBuilder sb = new StringBuilder();
if (noFilter) {
sb.append("(.*)");
}
else {
sb.append("(.* - ");
for (int i = 0; i < parameters.size(); i++) {
sb.append(parameters.get(i) + "\\[");
sb.append(filterParams.get(parameters.get(i)) + "\\] ");
}
sb.append(".*)");
}
filterPattern = Pattern.compile(sb.toString());
}
public static void reset() {
parameters.clear();
}
}
private String logFile;
private String logPath;
private Filter logFilter;
private Writer logWriter;
private long logRotation;
public XLogStreamer(Filter logFilter, Writer logWriter, String logPath, String logFile, long logRotationSecs) {
this.logWriter = logWriter;
this.logFilter = logFilter;
if (logFile == null) {
logFile = "oozie-app.log";
}
this.logFile = logFile;
this.logPath = logPath;
this.logRotation = logRotationSecs * 1000l;
}
/**
* Gets the files that are modified between startTime and endTime in the given logPath and streams the log after
* applying the filters.
*
* @param startTime
* @param endTime
* @throws IOException
*/
public void streamLog(Date startTime, Date endTime) throws IOException {
long startTimeMillis = 0;
long endTimeMillis;
if (startTime != null) {
startTimeMillis = startTime.getTime();
}
if (endTime == null) {
endTimeMillis = System.currentTimeMillis();
}
else {
endTimeMillis = endTime.getTime();
}
File dir = new File(logPath);
ArrayList fileList = getFileList(dir, startTimeMillis, endTimeMillis, logRotation, logFile);
for (int i = 0; i < fileList.size(); i++) {
InputStream ifs;
ifs = new FileInputStream(fileList.get(i).getFileName());
XLogReader logReader = new XLogReader(ifs, logFilter, logWriter);
logReader.processLog();
}
}
/**
* File name along with the modified time which will be used to sort later.
*/
class FileInfo implements Comparable {
String fileName;
long modTime;
public FileInfo(String fileName, long modTime) {
this.fileName = fileName;
this.modTime = modTime;
}
public String getFileName() {
return fileName;
}
public long getModTime() {
return modTime;
}
public int compareTo(FileInfo fileInfo) {
long diff = this.modTime - fileInfo.modTime;
if(diff > 0) {
return 1;
} else if(diff < 0) {
return -1;
} else {
return 0;
}
}
}
/**
* Gets the file list that will have the logs between startTime and endTime.
*
* @param dir
* @param startTime
* @param endTime
* @param logRotationTime
* @param logFile
* @return List of files to be streamed
*/
private ArrayList getFileList(File dir, long startTime, long endTime, long logRotationTime,
String logFile) {
String[] children = dir.list();
ArrayList fileList = new ArrayList();
if (children == null) {
return fileList;
}
else {
for (int i = 0; i < children.length; i++) {
String filename = children[i];
if (!filename.startsWith(logFile) && !filename.equals(logFile)) {
continue;
}
File file = new File(dir.getAbsolutePath(), filename);
long modTime = file.lastModified();
if (modTime < startTime) {
continue;
}
if (modTime / logRotationTime > (endTime / logRotationTime + 1)) {
continue;
}
fileList.add(new FileInfo(file.getAbsolutePath(), modTime));
}
}
Collections.sort(fileList);
return fileList;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy