blob: c2fde4857d8c3d019f3b21aa60fbb815960615d5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.apache.beam.runners.dataflow.options;
import static org.apache.beam.vendor.guava.v26_0_jre.com.google.common.base.Preconditions.checkNotNull;
import com.fasterxml.jackson.annotation.JsonCreator;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.apache.beam.sdk.options.Default;
import org.apache.beam.sdk.options.Description;
import org.apache.beam.sdk.options.PipelineOptions;
/**
* Options that are used to control logging configuration on the Dataflow worker.
*
* @deprecated This interface will no longer be the source of truth for worker logging configuration
* once jobs are executed using a dedicated SDK harness instead of user code being co-located
* alongside Dataflow worker code. Please set the option below and also the corresponding option
* within {@link org.apache.beam.sdk.options.SdkHarnessOptions} to ensure forward compatibility.
*/
@Description("Options that are used to control logging configuration on the Dataflow worker.")
@Deprecated
public interface DataflowWorkerLoggingOptions extends PipelineOptions {
/** The set of log levels that can be used on the Dataflow worker. */
enum Level {
/** Special level used to turn off logging. */
OFF,
/** Level for logging error messages. */
ERROR,
/** Level for logging warning messages. */
WARN,
/** Level for logging informational messages. */
INFO,
/** Level for logging diagnostic messages. */
DEBUG,
/** Level for logging tracing messages. */
TRACE
}
/** This option controls the default log level of all loggers without a log level override. */
@Description("Controls the default log level of all loggers without a log level override.")
@Default.Enum("INFO")
Level getDefaultWorkerLogLevel();
void setDefaultWorkerLogLevel(Level level);
/**
* Controls the log level given to messages printed to {@code System.out}.
*
* <p>Note that the message may be filtered depending on the {@link #getDefaultWorkerLogLevel
* defaultWorkerLogLevel} or if a {@code System.out} override is specified via {@link
* #getWorkerLogLevelOverrides workerLogLevelOverrides}.
*/
@Description(
"Controls the log level given to messages printed to System.out. Note that the "
+ "message may be filtered depending on the defaultWorkerLogLevel or if a 'System.out' "
+ "override is specified via workerLogLevelOverrides.")
@Default.Enum("INFO")
Level getWorkerSystemOutMessageLevel();
void setWorkerSystemOutMessageLevel(Level level);
/**
* Controls the log level given to messages printed to {@code System.err}.
*
* <p>Note that the message may be filtered depending on the {@link #getDefaultWorkerLogLevel
* defaultWorkerLogLevel} or if a {@code System.err} override is specified via {@link
* #getWorkerLogLevelOverrides workerLogLevelOverrides}.
*/
@Description(
"Controls the log level given to messages printed to System.err. Note that the "
+ "message may be filtered depending on the defaultWorkerLogLevel or if a 'System.err' "
+ "override is specified via workerLogLevelOverrides.")
@Default.Enum("ERROR")
Level getWorkerSystemErrMessageLevel();
void setWorkerSystemErrMessageLevel(Level level);
/**
* This option controls the log levels for specifically named loggers.
*
* <p>Later options with equivalent names override earlier options.
*
* <p>See {@link WorkerLogLevelOverrides} for more information on how to configure logging on a
* per {@link Class}, {@link Package}, or name basis. If used from the command line, the expected
* format is {"Name":"Level",...}, further details on {@link WorkerLogLevelOverrides#from}.
*/
@Description(
"This option controls the log levels for specifically named loggers. "
+ "The expected format is {\"Name\":\"Level\",...}. The Dataflow worker supports a logging "
+ "hierarchy based off of names that are '.' separated. For example, by specifying the value "
+ "{\"a.b.c.Foo\":\"DEBUG\"}, the logger for the class 'a.b.c.Foo' will be configured to "
+ "output logs at the DEBUG level. Similarly, by specifying the value {\"a.b.c\":\"WARN\"}, "
+ "all loggers underneath the 'a.b.c' package will be configured to output logs at the WARN "
+ "level. System.out and System.err levels are configured via loggers of the corresponding "
+ "name. Also, note that when multiple overrides are specified, the exact name followed by "
+ "the closest parent takes precedence.")
WorkerLogLevelOverrides getWorkerLogLevelOverrides();
void setWorkerLogLevelOverrides(WorkerLogLevelOverrides value);
/**
* Defines a log level override for a specific class, package, or name.
*
* <p>The Dataflow worker harness supports a logging hierarchy based off of names that are "."
* separated. It is a common pattern to have the logger for a given class share the same name as
* the class itself. Given the classes {@code a.b.c.Foo}, {@code a.b.c.Xyz}, and {@code a.b.Bar},
* with loggers named {@code "a.b.c.Foo"}, {@code "a.b.c.Xyz"}, and {@code "a.b.Bar"}
* respectively, we can override the log levels:
*
* <ul>
* <li>for {@code Foo} by specifying the name {@code "a.b.c.Foo"} or the {@link Class}
* representing {@code a.b.c.Foo}.
* <li>for {@code Foo}, {@code Xyz}, and {@code Bar} by specifying the name {@code "a.b"} or the
* {@link Package} representing {@code a.b}.
* <li>for {@code Foo} and {@code Bar} by specifying both of their names or classes.
* </ul>
*
* <p>{@code System.out} and {@code System.err} messages are configured via loggers of the
* corresponding name. Note that by specifying multiple overrides, the exact name followed by the
* closest parent takes precedence.
*/
class WorkerLogLevelOverrides extends HashMap<String, Level> {
/**
* Overrides the default log level for the passed in class.
*
* <p>This is equivalent to calling {@link #addOverrideForName(String,
* DataflowWorkerLoggingOptions.Level)} and passing in the {@link Class#getName() class name}.
*/
public WorkerLogLevelOverrides addOverrideForClass(Class<?> klass, Level level) {
checkNotNull(klass, "Expected class to be not null.");
addOverrideForName(klass.getName(), level);
return this;
}
/**
* Overrides the default log level for the passed in package.
*
* <p>This is equivalent to calling {@link #addOverrideForName(String,
* DataflowWorkerLoggingOptions.Level)} and passing in the {@link Package#getName() package
* name}.
*/
public WorkerLogLevelOverrides addOverrideForPackage(Package pkg, Level level) {
checkNotNull(pkg, "Expected package to be not null.");
addOverrideForName(pkg.getName(), level);
return this;
}
/**
* Overrides the default log level for the passed in name.
*
* <p>Note that because of the hierarchical nature of logger names, this will override the log
* level of all loggers that have the passed in name or a parent logger that has the passed in
* name.
*/
public WorkerLogLevelOverrides addOverrideForName(String name, Level level) {
checkNotNull(name, "Expected name to be not null.");
checkNotNull(level, "Expected level to be one of %s.", Arrays.toString(Level.values()));
put(name, level);
return this;
}
/**
* Expects a map keyed by logger {@code Name}s with values representing {@code Level}s. The
* {@code Name} generally represents the fully qualified Java {@link Class#getName() class
* name}, or fully qualified Java {@link Package#getName() package name}, or custom logger name.
* The {@code Level} represents the log level and must be one of {@link Level}.
*/
@JsonCreator
public static WorkerLogLevelOverrides from(Map<String, String> values) {
checkNotNull(values, "Expected values to be not null.");
WorkerLogLevelOverrides overrides = new WorkerLogLevelOverrides();
for (Map.Entry<String, String> entry : values.entrySet()) {
try {
overrides.addOverrideForName(entry.getKey(), Level.valueOf(entry.getValue()));
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(
String.format(
"Unsupported log level '%s' requested for %s. Must be one of %s.",
entry.getValue(), entry.getKey(), Arrays.toString(Level.values())));
}
}
return overrides;
}
}
}