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

org.elasticsearch.common.logging.DeprecationLogger Maven / Gradle / Ivy

There is a newer version: 8.14.1
Show newest version
/*
 * Licensed to Elasticsearch under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch licenses this file to you 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.elasticsearch.common.logging;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.elasticsearch.common.SuppressLoggerChecks;
import org.elasticsearch.common.util.concurrent.ThreadContext;

import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * A logger that logs deprecation notices.
 */
public class DeprecationLogger {

    private final Logger logger;

    /**
     * The "Warning" Header comes from RFC-7234. As the RFC describes, it's generally used for caching purposes, but it can be
     * used for any warning.
     *
     * https://tools.ietf.org/html/rfc7234#section-5.5
     */
    public static final String DEPRECATION_HEADER = "Warning";

    /**
     * This is set once by the {@code Node} constructor, but it uses {@link CopyOnWriteArraySet} to ensure that tests can run in parallel.
     * 

* Integration tests will create separate nodes within the same classloader, thus leading to a shared, {@code static} state. * In order for all tests to appropriately be handled, this must be able to remember all {@link ThreadContext}s that it is * given in a thread safe manner. *

* For actual usage, multiple nodes do not share the same JVM and therefore this will only be set once in practice. */ private static final CopyOnWriteArraySet THREAD_CONTEXT = new CopyOnWriteArraySet<>(); /** * Set the {@link ThreadContext} used to add deprecation headers to network responses. *

* This is expected to only be invoked by the {@code Node}'s constructor (therefore once outside of tests). * * @param threadContext The thread context owned by the {@code ThreadPool} (and implicitly a {@code Node}) * @throws IllegalStateException if this {@code threadContext} has already been set */ public static void setThreadContext(ThreadContext threadContext) { assert threadContext != null; // add returning false means it _did_ have it already if (THREAD_CONTEXT.add(threadContext) == false) { throw new IllegalStateException("Double-setting ThreadContext not allowed!"); } } /** * Remove the {@link ThreadContext} used to add deprecation headers to network responses. *

* This is expected to only be invoked by the {@code Node}'s {@code close} method (therefore once outside of tests). * * @param threadContext The thread context owned by the {@code ThreadPool} (and implicitly a {@code Node}) * @throws IllegalStateException if this {@code threadContext} is unknown (and presumably already unset before) */ public static void removeThreadContext(ThreadContext threadContext) { assert threadContext != null; // remove returning false means it did not have it already if (THREAD_CONTEXT.remove(threadContext) == false) { throw new IllegalStateException("Removing unknown ThreadContext not allowed!"); } } /** * Creates a new deprecation logger based on the parent logger. Automatically * prefixes the logger name with "deprecation", if it starts with "org.elasticsearch.", * it replaces "org.elasticsearch" with "org.elasticsearch.deprecation" to maintain * the "org.elasticsearch" namespace. */ public DeprecationLogger(Logger parentLogger) { String name = parentLogger.getName(); if (name.startsWith("org.elasticsearch")) { name = name.replace("org.elasticsearch.", "org.elasticsearch.deprecation."); } else { name = "deprecation." + name; } this.logger = LogManager.getLogger(name); } /** * Logs a deprecated message. */ public void deprecated(String msg, Object... params) { deprecated(THREAD_CONTEXT, msg, params); } /** * Logs a deprecated message to the deprecation log, as well as to the local {@link ThreadContext}. * * @param threadContexts The node's {@link ThreadContext} (outside of concurrent tests, this should only ever have one context). * @param message The deprecation message. * @param params The parameters used to fill in the message, if any exist. */ @SuppressLoggerChecks(reason = "safely delegates to logger") void deprecated(Set threadContexts, String message, Object... params) { Iterator iterator = threadContexts.iterator(); if (iterator.hasNext()) { final String formattedMessage = LoggerMessageFormat.format(message, params); while (iterator.hasNext()) { try { iterator.next().addResponseHeader(DEPRECATION_HEADER, formattedMessage); } catch (IllegalStateException e) { // ignored; it should be removed shortly } } logger.warn(formattedMessage); } else { logger.warn(message, params); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy