Infra for deprecation logging

Add support for a specific deprecation logging that can be used to turn
on in order to notify users of a specific feature, flag, setting,
parameter, ... being deprecated.

The deprecation logger logs with a "deprecation." prefix logge
(or "org.elasticsearch.deprecation." if full name is used), and outputs
the logging to a dedicated deprecation log file.

Deprecation logging are logged under the DEBUG category. The idea is not to
enabled them by default (under WARN or ERROR) when running embedded in
another application.

By default they are turned off (INFO), in order to turn it on, the
"deprecation" category need to be set to DEBUG. This can be set in the
logging file or using the cluster update settings API, see the documentation

Closes #11033
This commit is contained in:
Alexander Reelsen 2015-05-26 17:44:52 +02:00
parent 9d1f6f7615
commit 045f01c085
10 changed files with 121 additions and 8 deletions

View File

@ -4,6 +4,10 @@ rootLogger: ${es.logger.level}, console, file
logger: logger:
# log action execution errors for easier debugging # log action execution errors for easier debugging
action: DEBUG action: DEBUG
# deprecation logging, turn to DEBUG to see them
deprecation: INFO, deprecation_log_file
# reduce the logging for aws, too much is logged under the default INFO # reduce the logging for aws, too much is logged under the default INFO
com.amazonaws: WARN com.amazonaws: WARN
org.apache.http: INFO org.apache.http: INFO
@ -24,6 +28,7 @@ logger:
additivity: additivity:
index.search.slowlog: false index.search.slowlog: false
index.indexing.slowlog: false index.indexing.slowlog: false
deprecation: false
appender: appender:
console: console:
@ -51,6 +56,14 @@ appender:
#type: pattern #type: pattern
#conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" #conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n"
deprecation_log_file:
type: dailyRollingFile
file: ${path.logs}/${cluster.name}_deprecation.log
datePattern: "'.'yyyy-MM-dd"
layout:
type: pattern
conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n"
index_search_slow_log_file: index_search_slow_log_file:
type: dailyRollingFile type: dailyRollingFile
file: ${path.logs}/${cluster.name}_index_search_slowlog.log file: ${path.logs}/${cluster.name}_index_search_slowlog.log

View File

@ -337,3 +337,20 @@ the http://logging.apache.org/log4j/1.2/manual.html[log4j documentation].
Additional Appenders and other logging classes provided by Additional Appenders and other logging classes provided by
http://logging.apache.org/log4j/extras/[log4j-extras] are also available, http://logging.apache.org/log4j/extras/[log4j-extras] are also available,
out of the box. out of the box.
==== Deprecation logging
In addition to regular logging, Elasticsearch allows you to enable logging
of deprecated actions. For example this allows you to determine early, if
you need to migrate certain functionality in the future. By default,
deprecation logging is disabled. You can enable it in the `config/logging.yml`
file by setting the deprecation log level to `DEBUG`.
[source,yaml]
--------------------------------------------------
deprecation: DEBUG, deprecation_log_file
--------------------------------------------------
This will create a daily rolling deprecation log file in your log directory.
Check this file regularly, especially when you intend to upgrade to a new
major version.

View File

@ -19,6 +19,7 @@
package org.elasticsearch.common.component; package org.elasticsearch.common.component;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -29,16 +30,18 @@ import org.elasticsearch.common.settings.Settings;
public abstract class AbstractComponent { public abstract class AbstractComponent {
protected final ESLogger logger; protected final ESLogger logger;
protected final DeprecationLogger deprecationLogger;
protected final Settings settings; protected final Settings settings;
public AbstractComponent(Settings settings) { public AbstractComponent(Settings settings) {
this.logger = Loggers.getLogger(getClass(), settings); this.logger = Loggers.getLogger(getClass(), settings);
this.deprecationLogger = new DeprecationLogger(logger);
this.settings = settings; this.settings = settings;
} }
public AbstractComponent(Settings settings, Class customClass) { public AbstractComponent(Settings settings, Class customClass) {
this.logger = Loggers.getLogger(customClass, settings); this.logger = Loggers.getLogger(customClass, settings);
this.deprecationLogger = new DeprecationLogger(logger);
this.settings = settings; this.settings = settings;
} }

View File

@ -0,0 +1,51 @@
/*
* 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;
/**
* A logger that logs deprecation notices.
*/
public class DeprecationLogger {
private final ESLogger logger;
/**
* 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(ESLogger parentLogger) {
String name = parentLogger.getName();
if (name.startsWith("org.elasticsearch")) {
name = name.replace("org.elasticsearch.", "org.elasticsearch.deprecation.");
} else {
name = "deprecation." + name;
}
this.logger = ESLoggerFactory.getLogger(parentLogger.getPrefix(), name);
}
/**
* Logs a deprecated message.
*/
public void deprecated(String msg, Object... params) {
logger.debug(msg, params);
}
}

View File

@ -66,6 +66,14 @@ public abstract class ESLoggerFactory {
return defaultFactory.newInstance(name.intern()); return defaultFactory.newInstance(name.intern());
} }
public static DeprecationLogger getDeprecationLogger(String name) {
return new DeprecationLogger(getLogger(name));
}
public static DeprecationLogger getDeprecationLogger(String prefix, String name) {
return new DeprecationLogger(getLogger(prefix, name));
}
public static ESLogger getRootLogger() { public static ESLogger getRootLogger() {
return defaultFactory.rootLogger(); return defaultFactory.rootLogger();
} }

View File

@ -19,7 +19,6 @@
package org.elasticsearch.common.logging.log4j; package org.elasticsearch.common.logging.log4j;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.ESLoggerFactory; import org.elasticsearch.common.logging.ESLoggerFactory;

View File

@ -19,6 +19,7 @@
package org.elasticsearch.index; package org.elasticsearch.index;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -30,9 +31,8 @@ import org.elasticsearch.index.settings.IndexSettings;
public abstract class AbstractIndexComponent implements IndexComponent { public abstract class AbstractIndexComponent implements IndexComponent {
protected final ESLogger logger; protected final ESLogger logger;
protected final DeprecationLogger deprecationLogger;
protected final Index index; protected final Index index;
protected final Settings indexSettings; protected final Settings indexSettings;
/** /**
@ -45,6 +45,7 @@ public abstract class AbstractIndexComponent implements IndexComponent {
this.index = index; this.index = index;
this.indexSettings = indexSettings; this.indexSettings = indexSettings;
this.logger = Loggers.getLogger(getClass(), indexSettings, index); this.logger = Loggers.getLogger(getClass(), indexSettings, index);
this.deprecationLogger = new DeprecationLogger(logger);
} }
@Override @Override

View File

@ -19,6 +19,7 @@
package org.elasticsearch.index.shard; package org.elasticsearch.index.shard;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -30,15 +31,15 @@ import org.elasticsearch.index.settings.IndexSettings;
public abstract class AbstractIndexShardComponent implements IndexShardComponent { public abstract class AbstractIndexShardComponent implements IndexShardComponent {
protected final ESLogger logger; protected final ESLogger logger;
protected final DeprecationLogger deprecationLogger;
protected final ShardId shardId; protected final ShardId shardId;
protected final Settings indexSettings; protected final Settings indexSettings;
protected AbstractIndexShardComponent(ShardId shardId, @IndexSettings Settings indexSettings) { protected AbstractIndexShardComponent(ShardId shardId, @IndexSettings Settings indexSettings) {
this.shardId = shardId; this.shardId = shardId;
this.indexSettings = indexSettings; this.indexSettings = indexSettings;
this.logger = Loggers.getLogger(getClass(), indexSettings, shardId); this.logger = Loggers.getLogger(getClass(), indexSettings, shardId);
this.deprecationLogger = new DeprecationLogger(logger);
} }
@Override @Override

View File

@ -91,7 +91,6 @@ public class JDKESLoggerTests extends ElasticsearchTestCase {
assertThat(record.getMessage(), equalTo("This is a trace")); assertThat(record.getMessage(), equalTo("This is a trace"));
assertThat(record.getSourceClassName(), equalTo(JDKESLoggerTests.class.getCanonicalName())); assertThat(record.getSourceClassName(), equalTo(JDKESLoggerTests.class.getCanonicalName()));
assertThat(record.getSourceMethodName(), equalTo("locationInfoTest")); assertThat(record.getSourceMethodName(), equalTo("locationInfoTest"));
} }
private static class TestHandler extends Handler { private static class TestHandler extends Handler {

View File

@ -24,6 +24,7 @@ import org.apache.log4j.Level;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.apache.log4j.spi.LocationInfo; import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.spi.LoggingEvent;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ElasticsearchTestCase; import org.elasticsearch.test.ElasticsearchTestCase;
@ -42,6 +43,8 @@ public class Log4jESLoggerTests extends ElasticsearchTestCase {
private ESLogger esTestLogger; private ESLogger esTestLogger;
private TestAppender testAppender; private TestAppender testAppender;
private String testLevel; private String testLevel;
private DeprecationLogger deprecationLogger;
private TestAppender deprecationAppender;
@Override @Override
public void setUp() throws Exception { public void setUp() throws Exception {
@ -61,6 +64,13 @@ public class Log4jESLoggerTests extends ElasticsearchTestCase {
assertThat(testLogger.getLevel(), equalTo(Level.TRACE)); assertThat(testLogger.getLevel(), equalTo(Level.TRACE));
testAppender = new TestAppender(); testAppender = new TestAppender();
testLogger.addAppender(testAppender); testLogger.addAppender(testAppender);
// deprecation setup, needs to be set to debug to log
deprecationLogger = Log4jESLoggerFactory.getDeprecationLogger("test");
deprecationAppender = new TestAppender();
ESLogger logger = Log4jESLoggerFactory.getLogger("deprecation.test");
logger.setLevel("DEBUG");
(((Log4jESLogger) logger).logger()).addAppender(deprecationAppender);
} }
@Override @Override
@ -70,6 +80,8 @@ public class Log4jESLoggerTests extends ElasticsearchTestCase {
esTestLogger.setLevel(testLevel); esTestLogger.setLevel(testLevel);
Logger testLogger = ((Log4jESLogger) esTestLogger).logger(); Logger testLogger = ((Log4jESLogger) esTestLogger).logger();
testLogger.removeAppender(testAppender); testLogger.removeAppender(testAppender);
Logger deprecationLogger = ((Log4jESLogger) Log4jESLoggerFactory.getLogger("deprecation.test")).logger();
deprecationLogger.removeAppender(deprecationAppender);
} }
@Test @Test
@ -122,7 +134,16 @@ public class Log4jESLoggerTests extends ElasticsearchTestCase {
assertThat(locationInfo, notNullValue()); assertThat(locationInfo, notNullValue());
assertThat(locationInfo.getClassName(), equalTo(Log4jESLoggerTests.class.getCanonicalName())); assertThat(locationInfo.getClassName(), equalTo(Log4jESLoggerTests.class.getCanonicalName()));
assertThat(locationInfo.getMethodName(), equalTo("locationInfoTest")); assertThat(locationInfo.getMethodName(), equalTo("locationInfoTest"));
}
@Test
public void testDeprecationLogger() {
deprecationLogger.deprecated("This is a deprecation message");
List<LoggingEvent> deprecationEvents = deprecationAppender.getEvents();
LoggingEvent event = deprecationEvents.get(0);
assertThat(event, notNullValue());
assertThat(event.getLevel(), equalTo(Level.DEBUG));
assertThat(event.getRenderedMessage(), equalTo("This is a deprecation message"));
} }
private static class TestAppender extends AppenderSkeleton { private static class TestAppender extends AppenderSkeleton {