/*
* Copyright 2013 Eediom 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 org.araqne.log.api;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class SelectorLogger extends AbstractLogger implements LoggerRegistryEventListener, Reconfigurable {
private static final String OPT_SOURCE_LOGGER = "source_logger";
private static final String OPT_PATTERN = "pattern";
private final org.slf4j.Logger slog = org.slf4j.LoggerFactory.getLogger(SelectorLogger.class.getName());
private LoggerRegistry loggerRegistry;
/**
* full name of data source logger
*/
private String loggerName;
private String pattern;
private Receiver receiver = new Receiver();
private Logger sourceLogger;
public SelectorLogger(LoggerSpecification spec, LoggerFactory factory, LoggerRegistry loggerRegistry) {
super(spec, factory);
this.loggerRegistry = loggerRegistry;
this.loggerRegistry.addListener(this);
Map<String, String> config = spec.getConfig();
this.loggerName = config.get(OPT_SOURCE_LOGGER);
this.pattern = config.get(OPT_PATTERN);
this.sourceLogger = loggerRegistry.getLogger(loggerName);
}
@Override
public void onConfigChange(Map<String, String> oldConfigs, Map<String, String> newConfigs) {
this.loggerName = newConfigs.get(OPT_SOURCE_LOGGER);
this.pattern = newConfigs.get(OPT_PATTERN);
}
@Override
protected void onStart(LoggerStartReason reason) {
Logger captured = sourceLogger;
if (captured != null) {
slog.debug("araqne log api: connect pipe to source logger [{}]", loggerName);
captured.addLogPipe(receiver);
} else
slog.debug("araqne log api: source logger [{}] not found", loggerName);
}
@Override
protected void onStop(LoggerStopReason reason) {
try {
Logger captured = sourceLogger;
if (captured != null) {
slog.debug("araqne log api: disconnect pipe from source logger [{}]", loggerName);
captured.removeLogPipe(receiver);
loggerRegistry.removeListener(this);
}
} catch (RuntimeException e) {
if (!e.getMessage().endsWith("unavailable"))
throw e;
}
}
@Override
public boolean isPassive() {
return true;
}
@Override
protected void runOnce() {
}
@Override
public void loggerAdded(Logger logger) {
if (logger.getFullName().equals(loggerName)) {
slog.debug("araqne log api: source logger [{}] loaded", loggerName);
if (isRunning()) {
slog.debug("araqne log api: connect pipe to source logger [{}]", loggerName);
logger.addLogPipe(receiver);
}
this.sourceLogger = logger;
}
}
@Override
public void loggerRemoved(Logger logger) {
if (logger.getFullName().equals(loggerName)) {
slog.debug("araqne log api: source logger [{}] unloaded", loggerName);
slog.debug("araqne log api: disconnect pipe from source logger [{}]", loggerName);
logger.removeLogPipe(receiver);
this.sourceLogger = null;
}
}
private class Receiver extends AbstractLogPipe {
@Override
public void onLog(Logger logger, Log log) {
String line = (String) log.getParams().get("line");
if (line == null)
return;
if (line.startsWith(pattern)) {
write(new SimpleLog(log.getDate(), getFullName(), log.getParams()));
}
}
@Override
public void onLogBatch(Logger logger, Log[] logs) {
ArrayList<Log> selected = new ArrayList<Log>(logs.length);
for (int i = 0; i < logs.length; i++) {
Log log = logs[i];
if (log == null)
continue;
Map<String, Object> params = log.getParams();
String line = (String) params.get("line");
if (line != null && line.startsWith(pattern)) {
params = new HashMap<String, Object>(params);
selected.add(new SimpleLog(log.getDate(), getFullName(), params));
}
}
writeBatch(selected.toArray(new Log[0]));
}
}
}