Skip to content

Commit

Permalink
Emergency logger + needed dependencies added (#8680)
Browse files Browse the repository at this point in the history
Signed-off-by: Hendrik Ebbers <[email protected]>
Co-authored-by: Cody Littley <[email protected]>
  • Loading branch information
hendrikebbers and cody-littley authored Sep 20, 2023
1 parent a64a659 commit bb0e078
Show file tree
Hide file tree
Showing 15 changed files with 1,043 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2023 Hedera Hashgraph, LLC
*
* 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 com.swirlds.logging.v2;

import com.swirlds.logging.v2.extensions.emergency.EmergencyLogger;
import com.swirlds.logging.v2.extensions.emergency.EmergencyLoggerProvider;
import edu.umd.cs.findbugs.annotations.NonNull;

/**
* The level of a log message
*/
public enum Level {
ERROR(10),
WARN(20),
INFO(30),
DEBUG(40),
TRACE(100);

/**
* The emergency logger
*/
private static final EmergencyLogger EMERGENCY_LOGGER = EmergencyLoggerProvider.getEmergencyLogger();

/**
* The ordinal of the level
*/
private final int levelOrdinal;

/**
* Constructs a level
*
* @param levelOrdinal the ordinal of the level
*/
Level(final int levelOrdinal) {
this.levelOrdinal = levelOrdinal;
}

/**
* Returns true if the logging of the given level is enabled
* @param level the level
* @return true if the logging of the given level is enabled
*/
public boolean enabledLoggingOfLevel(@NonNull final Level level) {
if (level == null) {
EMERGENCY_LOGGER.logNPE("level");
return true;
}
return this.levelOrdinal >= level.levelOrdinal;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Copyright (C) 2023 Hedera Hashgraph, LLC
*
* 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 com.swirlds.logging.v2;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.Objects;

/**
* A marker is a named reference to a location / package / context in the code. It can be used to filter log messages at
* runtime
*
* @param name the name of the marker
* @param parent the parent marker (if present)
*/
public record Marker(@NonNull String name, @Nullable Marker parent) {

public Marker {
Objects.requireNonNull(name, "name must not be null");
}

public Marker(@NonNull final String name) {
this(name, null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2023 Hedera Hashgraph, LLC
*
* 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 com.swirlds.logging.v2.extensions.emergency;

import com.swirlds.logging.v2.Level;
import com.swirlds.logging.v2.extensions.event.LogEvent;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;

/**
* This interface is used to log emergency events. It is used in the logger api to log events. An implementation must
* not be dependend on any other logging system and must be directly usable in the logger api. Next to that an
* implementation must be bullet proof and must not throw any exceptions.
*/
public interface EmergencyLogger {

/**
* Logs a null pointer exception.
*
* @param nameOfNullParam the name of the null parameter
*/
void logNPE(@NonNull String nameOfNullParam);

/**
* Logs an event.
*
* @param event the event to log
*/
void log(@NonNull LogEvent event);

/**
* Logs a message.
*
* @param level the level of the message
* @param message the message to log
*/
default void log(@NonNull final Level level, @NonNull final String message) {
log(level, message, null);
}

/**
* Logs a message with a throwable.
*
* @param level the level of the message
* @param message the message to log
* @param thrown the throwable to log
*/
void log(@NonNull Level level, @NonNull String message, @Nullable Throwable thrown);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2023 Hedera Hashgraph, LLC
*
* 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 com.swirlds.logging.v2.extensions.emergency;

import com.swirlds.logging.v2.internal.emergency.EmergencyLoggerImpl;
import edu.umd.cs.findbugs.annotations.NonNull;

/**
* This class is used to get an instance of the emergency logger.
*/
public final class EmergencyLoggerProvider {

/**
* Private constructor to prevent instantiation.
*/
private EmergencyLoggerProvider() {}

/**
* Gets an instance of the emergency logger.
*
* @return an instance of the emergency logger
*/
@NonNull
public static EmergencyLogger getEmergencyLogger() {
return EmergencyLoggerImpl.getInstance();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* This package contains the API of the emergency logger. The emergency logger should be used in the logging api (and
* extensions of the logging api) for logging. The emergency logger does not depend on the logging API and is defined in
* a bulletproof way.
*/
package com.swirlds.logging.v2.extensions.emergency;
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright (C) 2023 Hedera Hashgraph, LLC
*
* 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 com.swirlds.logging.v2.extensions.event;

import com.swirlds.logging.v2.Level;
import com.swirlds.logging.v2.Marker;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.time.Instant;
import java.util.Map;

/**
* A log event that is passed to the {@link LogEventConsumer} for processing.
*
* @param level The log level
* @param loggerName The name of the logger
* @param threadName The name of the thread
* @param timestamp The timestamp of the log event
* @param message The log message (this is not a String since the message can be parameterized. See
* {@link LogMessage} for more details).
* @param throwable The throwable
* @param marker The marker
* @param context The context
*/
public record LogEvent(
@NonNull Level level,
@NonNull String loggerName,
@NonNull String threadName,
@NonNull Instant timestamp,
@NonNull LogMessage message,
@Nullable Throwable throwable,
@Nullable Marker marker,
@NonNull Map<String, String> context) {

public LogEvent(
@NonNull final Level level,
@NonNull final String loggerName,
@NonNull final String threadName,
@NonNull final Instant timestamp,
@NonNull final String message,
@Nullable final Throwable throwable,
@Nullable final Marker marker,
@NonNull final Map<String, String> context) {
this(level, loggerName, threadName, timestamp, new SimpleLogMessage(message), throwable, marker, context);
}

public LogEvent(@NonNull final Level level, @NonNull final String loggerName, @NonNull final String message) {
this(level, loggerName, message, null);
}

public LogEvent(
@NonNull final Level level,
@NonNull final String loggerName,
@NonNull final String message,
@Nullable final Throwable throwable) {
this(
level,
loggerName,
Thread.currentThread().getName(),
Instant.now(),
new SimpleLogMessage(message),
throwable,
null,
Map.of());
}

/**
* Creates a new {@link LogEvent} that has all parameters of the given logEvent but a different context.
*
* @param logEvent the logEvent that should be copied (excluding the context)
* @param context the new context
* @return the new copy of the event
*/
@NonNull
public static LogEvent createCopyWithDifferentContext(
@NonNull final LogEvent logEvent, @NonNull final Map<String, String> context) {
return new LogEvent(
logEvent.level,
logEvent.loggerName,
logEvent.threadName,
logEvent.timestamp,
logEvent.message,
logEvent.throwable,
logEvent.marker,
context);
}

/**
* Creates a new {@link LogEvent} that has all parameters of the given logEvent but a different loggerName.
*
* @param logEvent the logEvent that should be copied (excluding the loggerName)
* @param loggerName the new logger name
* @return the new copy of the event
*/
@NonNull
public static LogEvent createCopyWithDifferentName(
@NonNull final LogEvent logEvent, @NonNull final String loggerName) {
return new LogEvent(
logEvent.level,
loggerName,
logEvent.threadName,
logEvent.timestamp,
logEvent.message,
logEvent.throwable,
logEvent.marker,
logEvent.context);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright (C) 2023 Hedera Hashgraph, LLC
*
* 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 com.swirlds.logging.v2.extensions.event;

import com.swirlds.logging.v2.Level;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.function.Consumer;

/**
* A consumer that consumes log events.
*/
public interface LogEventConsumer extends Consumer<LogEvent> {

/**
* Checks if the consumer is enabled for the given name and level.
*
* @param name the name
* @param level the level
* @return true if the consumer is enabled, false otherwise
*/
boolean isEnabled(@NonNull String name, @NonNull Level level);
}
Loading

0 comments on commit bb0e078

Please sign in to comment.