/* * Copyright 2014 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.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexSelectorLogger extends AbstractLogger implements LoggerRegistryEventListener, LogPipe, Reconfigurable { private static final String OPT_SOURCE_LOGGER = "source_logger"; private static final String OPT_PATTERN = "pattern"; private static final String OPT_INVERT = "invert"; private final org.slf4j.Logger slog = org.slf4j.LoggerFactory.getLogger(RegexSelectorLogger.class.getName()); private LoggerRegistry loggerRegistry; /** * full name of data source logger */ private String loggerName; private String pattern; private boolean invert; /** * cached pattern matchers per thread */ private ThreadLocal<Matcher> matchers = new ThreadLocal<Matcher>(); public RegexSelectorLogger(LoggerSpecification spec, LoggerFactory factory, LoggerRegistry loggerRegistry) { super(spec, factory); this.loggerRegistry = loggerRegistry; Map<String, String> config = spec.getConfig(); loggerName = config.get(OPT_SOURCE_LOGGER); pattern = config.get(OPT_PATTERN); invert = config.get(OPT_INVERT) != null && Boolean.parseBoolean(config.get(OPT_INVERT)); } @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); if (!oldConfigs.get(OPT_PATTERN).equals(newConfigs.get(OPT_PATTERN))) matchers.remove(); this.invert = newConfigs.get(OPT_INVERT) != null && Boolean.parseBoolean(newConfigs.get(OPT_INVERT)); } @Override protected void onStart(LoggerStartReason reason) { loggerRegistry.addListener(this); Logger logger = loggerRegistry.getLogger(loggerName); if (logger != null) { slog.debug("araqne log api: connect pipe to source logger [{}]", loggerName); logger.addLogPipe(this); } else slog.debug("araqne log api: source logger [{}] not found", loggerName); } @Override protected void onStop(LoggerStopReason reason) { try { if (loggerRegistry != null) { Logger logger = loggerRegistry.getLogger(loggerName); if (logger != null) { slog.debug("araqne log api: disconnect pipe from source logger [{}]", loggerName); logger.removeLogPipe(this); } 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); logger.addLogPipe(this); } } @Override public void loggerRemoved(Logger logger) { if (logger.getFullName().equals(loggerName)) { slog.debug("araqne log api: source logger [{}] unloaded", loggerName); logger.removeLogPipe(this); } } @Override public void onLog(Logger logger, Log log) { String line = (String) log.getParams().get("line"); if (line == null) return; Matcher matcher = matchers.get(); if (matcher == null) { matcher = Pattern.compile(pattern).matcher(line); matchers.set(matcher); } else { matcher.reset(line); } boolean select = matcher.find(); if (invert) select = !select; if (select) write(new SimpleLog(log.getDate(), getFullName(), log.getParams())); } @Override public void onLogBatch(Logger logger, Log[] logs) { for (Log log : logs) if (log != null) onLog(logger, log); } }