You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Describe alternatives you've considered
I have written a helper class to work-around this but it makes my applications not be able to use the slf4j.Logger interface.
packageutilimportorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importorg.slf4j.MDC;
importorg.slf4j.event.Level;
importorg.springframework.lang.NonNull;
importorg.springframework.lang.Nullable;
importjava.util.LinkedHashMap;
importjava.util.Map;
importjava.util.Objects;
/** * Thread-safe structured logging utility that integrates with Google Cloud Logging. * Provides a builder pattern API for constructing log entries with MDC context. * * @author Luke Mauldin ([email protected]) - KidStrong, Inc. */publicclassStructuredLogger {
privatefinalLoggerlogger;
/** * Creates a new StructuredLogger instance for the specified class. * * @param clazz The class to create the logger for * @throws IllegalArgumentException if clazz is null */publicStructuredLogger(@NonNullClass<?> clazz) {
Objects.requireNonNull(clazz, "Class cannot be null");
this.logger = LoggerFactory.getLogger(clazz);
}
/** * Creates a new log entry builder. * * @return A new LogBuilder instance */publicLogBuilderlog() {
returnnewLogBuilder();
}
/** * Builder class for constructing structured log entries. */publicclassLogBuilder {
privatefinalMap<String, String> fields;
privateLevellevel;
privateStringmessage;
privateThrowablethrowable;
privateLogBuilder() {
this.fields = newLinkedHashMap<>();
this.level = Level.INFO;
}
/** * Sets the log level to INFO. * * @return this builder */publicLogBuilderinfo() {
this.level = Level.INFO;
returnthis;
}
/** * Sets the log level to ERROR. * * @return this builder */publicLogBuildererror() {
this.level = Level.ERROR;
returnthis;
}
/** * Sets the log level to WARN. * * @return this builder */publicLogBuilderwarn() {
this.level = Level.WARN;
returnthis;
}
/** * Sets the log level to DEBUG. * * @return this builder */publicLogBuilderdebug() {
this.level = Level.DEBUG;
returnthis;
}
/** * Adds a field to the log entry. * * @param key The field key * @param value The field value * @return this builder * @throws IllegalArgumentException if key is null */publicLogBuilderaddField(@NonNullStringkey, @NullableObjectvalue) {
Objects.requireNonNull(key, "Field key cannot be null");
fields.put(key, value != null ? value.toString() : "null");
returnthis;
}
/** * Adds multiple fields to the log entry. * * @param fields Map of fields to add * @return this builder * @throws IllegalArgumentException if fields is null */publicLogBuilderaddFields(@NonNullMap<String, Object> fields) {
Objects.requireNonNull(fields, "Fields map cannot be null");
fields.forEach(this::addField);
returnthis;
}
/** * Sets the log message. * * @param message The log message * @return this builder */publicLogBuildermessage(@NullableStringmessage) {
this.message = message;
returnthis;
}
/** * Adds an exception to the log entry. * * @param throwable The exception to log * @return this builder */publicLogBuilderexception(@NullableThrowablethrowable) {
this.throwable = throwable;
if (throwable != null) {
addField("error_type", throwable.getClass().getName());
addField("error_message", throwable.getMessage());
}
returnthis;
}
/** * Builds and writes the log entry. */publicvoidwrite() {
Map<String, String> oldContext = null;
try {
// Backup existing MDC contextoldContext = MDC.getCopyOfContextMap();
// Add all fields to MDCfields.forEach(MDC::put);
// Log at the appropriate levelswitch (level) {
caseERROR -> logger.error(message, throwable);
caseWARN -> logger.warn(message, throwable);
caseDEBUG -> logger.debug(message, throwable);
default -> logger.info(message);
}
} finally {
// Clean up MDCfields.keySet().forEach(MDC::remove);
// Restore original MDC contextif (oldContext != null) {
MDC.setContextMap(oldContext);
} else {
MDC.clear();
}
}
}
}
}
The text was updated successfully, but these errors were encountered:
Is your feature request related to a problem? Please describe.
I would like for structured logging with slf4j facade to have first class support.
Describe the solution you'd like
I would like code like this to be able to send
jsonPayload
with the fieldsorderId
,amount
, etc...Describe alternatives you've considered
I have written a helper class to work-around this but it makes my applications not be able to use the
slf4j.Logger
interface.The text was updated successfully, but these errors were encountered: