All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.logstash.logback.argument.StructuredArguments Maven / Gradle / Ivy

/*
 * Copyright 2013-2022 the original author or authors.
 *
 * 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 net.logstash.logback.argument;

import java.util.Arrays;
import java.util.Map;
import java.util.function.Supplier;

import net.logstash.logback.marker.MapEntriesAppendingMarker;
import net.logstash.logback.marker.ObjectAppendingMarker;
import net.logstash.logback.marker.ObjectFieldsAppendingMarker;
import net.logstash.logback.marker.RawJsonAppendingMarker;

import ch.qos.logback.core.Context;
import ch.qos.logback.core.status.StatusManager;
import ch.qos.logback.core.status.WarnStatus;
import org.slf4j.ILoggerFactory;
import org.slf4j.LoggerFactory;

/**
 * Factory for creating {@link StructuredArgument}s.
 */
public class StructuredArguments {

    /**
     * The default message format used when writing key value pairs to the log message.
     */
    public static final String DEFAULT_KEY_VALUE_MESSAGE_FORMAT_PATTERN = "{0}={1}";

    /**
     * A message format pattern that will only write
     * the argument value to a log message (i.e. it won't write the key).
     */
    public static final String VALUE_ONLY_MESSAGE_FORMAT_PATTERN = "{1}";

    private StructuredArguments() {
    }

    /**
     * Convenience method for calling {@link #keyValue(String, Object, String)}
     * using the {@link #DEFAULT_KEY_VALUE_MESSAGE_FORMAT_PATTERN}.
     * 

* Basically, adds "key":"value" to the JSON event AND * name=value to the formatted message. * * @param key the key (field name) * @param value the value * @return a pre-populated {@link StructuredArgument} instance * * @see ObjectAppendingMarker * @see #keyValue(String, Object, String) * @see #DEFAULT_KEY_VALUE_MESSAGE_FORMAT_PATTERN */ public static StructuredArgument keyValue(String key, Object value) { return keyValue(key, value, DEFAULT_KEY_VALUE_MESSAGE_FORMAT_PATTERN); } /** * Abbreviated convenience method for calling {@link #keyValue(String, Object)}. * * @param key the key (field name) * @param value the value * @return a pre-populated {@link StructuredArgument} instance * * @see #keyValue(String, Object) */ public static StructuredArgument kv(String key, Object value) { return keyValue(key, value); } /** * Adds "key":"value" to the JSON event AND * name/value to the formatted message using the given messageFormatPattern. * * @param key the key (field name) * @param value the value * @param messageFormatPattern the pattern used to concatenate the key and the value * @return a pre-populated {@link StructuredArgument} instance * * @see ObjectAppendingMarker */ public static StructuredArgument keyValue(String key, Object value, String messageFormatPattern) { return new ObjectAppendingMarker(key, value, messageFormatPattern); } /** * Abbreviated convenience method for calling {@link #keyValue(String, Object, String)}. * * @param key the key (field name) * @param value the value * @param messageFormatPattern the pattern used to concatenate the key and the value * @return a pre-populated {@link StructuredArgument} instance * * @see #keyValue(String, Object, String) */ public static StructuredArgument kv(String key, Object value, String messageFormatPattern) { return keyValue(key, value, messageFormatPattern); } /** * Adds "key":"value" to the JSON event AND * value to the formatted message (without the key). * * @param key the key (field name) * @param value the value * @return a pre-populated {@link StructuredArgument} instance * * @see #keyValue(String, Object, String) * @see #VALUE_ONLY_MESSAGE_FORMAT_PATTERN */ public static StructuredArgument value(String key, Object value) { return keyValue(key, value, VALUE_ONLY_MESSAGE_FORMAT_PATTERN); } /** * Abbreviated convenience method for calling {@link #value(String, Object)}. * * @param key the key (field name) * @param value the value * @return a pre-populated {@link StructuredArgument} instance * * @see #value(String, Object) */ public static StructuredArgument v(String key, Object value) { return value(key, value); } /** * Adds a "key":"value" entry for each Map entry to the JSON event AND * {@code map.toString()} to the formatted message. * * @param map {@link Map} holding the key/value pairs * @return a pre-populated {@link StructuredArgument} instance * * @see MapEntriesAppendingMarker */ public static StructuredArgument entries(Map map) { return new MapEntriesAppendingMarker(map); } /** * Abbreviated convenience method for calling {@link #entries(Map)}. * * @param map {@link Map} holding the key/value pairs * @return a pre-populated {@link StructuredArgument} instance * * @see #entries(Map) */ public static StructuredArgument e(Map map) { return entries(map); } /** * Adds a "key":"value" entry for each field in the given object to the JSON event AND * {@code object.toString()} to the formatted message. * * @param object the object to write fields from * @return a pre-populated {@link StructuredArgument} instance * * @see ObjectFieldsAppendingMarker */ public static StructuredArgument fields(Object object) { return new ObjectFieldsAppendingMarker(object); } /** * Abbreviated convenience method for calling {@link #fields(Object)}. * * @param object the object to write fields from * @return a pre-populated {@link StructuredArgument} instance * * @see #fields(Object) */ public static StructuredArgument f(Object object) { return fields(object); } /** * Adds a field to the JSON event whose key is {@code fieldName} and whose value * is a JSON array of objects AND a string version of the array to the formatted message. * * @param fieldName field name * @param objects elements of the array to write under the {@code fieldName} key * @return a pre-populated {@link StructuredArgument} instance * * @see ObjectAppendingMarker */ public static StructuredArgument array(String fieldName, Object... objects) { return new ObjectAppendingMarker(fieldName, objects); } /** * Abbreviated convenience method for calling {@link #array(String, Object...)}. * * @param fieldName field name * @param objects elements of the array to write under the {@code fieldName} key * @return a pre-populated {@link StructuredArgument} instance * * @see #array(String, Object...) */ public static StructuredArgument a(String fieldName, Object... objects) { return array(fieldName, objects); } /** * Adds the {@code rawJsonValue} to the JSON event AND * the {@code rawJsonValue} to the formatted message. * * @param fieldName field name * @param rawJsonValue the raw JSON value * @return a pre-populated {@link StructuredArgument} instance * * @see RawJsonAppendingMarker */ public static StructuredArgument raw(String fieldName, String rawJsonValue) { return new RawJsonAppendingMarker(fieldName, rawJsonValue); } /** * Abbreviated convenience method for calling {@link #raw(String, String)}. * * @param fieldName field name * @param rawJsonValue the raw JSON value * @return a pre-populated {@link StructuredArgument} instance * * @see #raw(String, String) */ public static StructuredArgument r(String fieldName, String rawJsonValue) { return raw(fieldName, rawJsonValue); } /** * Defer the evaluation of the argument until actually required. * * @param structuredArgumentSupplier a supplier for the argument value * @return a pre-populated {@link StructuredArgument} instance * * @see DeferredStructuredArgument */ public static StructuredArgument defer(Supplier structuredArgumentSupplier) { return new DeferredStructuredArgument(structuredArgumentSupplier); } /** * Format the argument into a string. * * This method mimics the slf4j behavior: * array objects are formatted as array using {@link Arrays#toString}, * non array object using {@link String#valueOf}. * *

See org.slf4j.helpers.MessageFormatter#deeplyAppendParameter(StringBuilder, Object, Map)} * * @param arg the argument to format * @return formatted string version of the argument */ public static String toString(Object arg) { if (arg == null) { return "null"; } Class argClass = arg.getClass(); try { if (!argClass.isArray()) { return String.valueOf(arg); } else { if (argClass == byte[].class) { return Arrays.toString((byte[]) arg); } else if (argClass == short[].class) { return Arrays.toString((short[]) arg); } else if (argClass == int[].class) { return Arrays.toString((int[]) arg); } else if (argClass == long[].class) { return Arrays.toString((long[]) arg); } else if (argClass == char[].class) { return Arrays.toString((char[]) arg); } else if (argClass == float[].class) { return Arrays.toString((float[]) arg); } else if (argClass == double[].class) { return Arrays.toString((double[]) arg); } else if (argClass == boolean[].class) { return Arrays.toString((boolean[]) arg); } else { return Arrays.deepToString((Object[]) arg); } } } catch (Exception e) { ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory(); if (loggerFactory instanceof Context) { Context context = (Context) loggerFactory; StatusManager statusManager = context.getStatusManager(); statusManager.add(new WarnStatus( "Failed toString() invocation on an object of type [" + argClass.getName() + "]", StructuredArguments.class, e)); } else { System.err.println("Failed toString() invocation on an object of type [" + argClass.getName() + "]"); e.printStackTrace(); } return "[FAILED toString()]"; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy