org.neo4j.logging.internal.CappedLogger Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neo4j-logging Show documentation
Show all versions of neo4j-logging Show documentation
Logging interfaces and basic logger implementations.
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.neo4j.logging.internal;
import static java.util.Objects.requireNonNull;
import static org.neo4j.util.Preconditions.requirePositive;
import java.time.Clock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import org.neo4j.logging.InternalLog;
/**
* A CappedLogger will accept log messages, unless they occur "too much", in which case the messages will be ignored
* until some time passes, or the logger is reset.
*
* It is also desirable to be aware that log capping is taking place, so we don't mistakenly lose log output due to
* output capping.
*/
public class CappedLogger {
private static final AtomicLongFieldUpdater LAST_CHECK =
AtomicLongFieldUpdater.newUpdater(CappedLogger.class, "lastCheck");
private final InternalLog delegate;
private final long timeLimitMillis;
private final Clock clock;
// Atomically updated
private volatile long lastCheck;
/**
* Logger with a time based limit to the amount of logging it will accept between resets. With a time limit
* of 1 second, for instance, then the logger will log at most one message per second.
*
* @param time The time amount, must be positive.
* @param unit The time unit.
* @param clock The clock to use for reading the current time when checking this limit.
*/
public CappedLogger(InternalLog delegate, long time, TimeUnit unit, Clock clock) {
this.delegate = requireNonNull(delegate);
this.clock = requireNonNull(clock);
this.timeLimitMillis = unit.toMillis(requirePositive(time));
}
public void debug(String msg) {
if (checkExpiredAndSetLastCheckTime()) {
delegate.debug(msg);
}
}
public void debug(String msg, Throwable cause) {
if (checkExpiredAndSetLastCheckTime()) {
delegate.debug(msg, cause);
}
}
public void info(String msg, Object... arguments) {
if (checkExpiredAndSetLastCheckTime()) {
delegate.info(msg, arguments);
}
}
public void info(String msg, Throwable cause) {
if (checkExpiredAndSetLastCheckTime()) {
delegate.info(msg, cause);
}
}
public void warn(String msg) {
if (checkExpiredAndSetLastCheckTime()) {
delegate.warn(msg);
}
}
public void warn(String msg, Throwable cause) {
if (checkExpiredAndSetLastCheckTime()) {
delegate.warn(msg, cause);
}
}
public void warn(String msg, Object... arguments) {
if (checkExpiredAndSetLastCheckTime()) {
delegate.warn(msg, arguments);
}
}
public void error(String msg) {
if (checkExpiredAndSetLastCheckTime()) {
delegate.error(msg);
}
}
public void error(String msg, Throwable cause) {
if (checkExpiredAndSetLastCheckTime()) {
delegate.error(msg, cause);
}
}
private boolean checkExpiredAndSetLastCheckTime() {
long now = clock.millis();
long check = this.lastCheck;
if (check > now - timeLimitMillis) {
return false;
}
while (!LAST_CHECK.compareAndSet(this, check, now)) {
check = lastCheck;
if (check > now) {
break;
}
}
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy