You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by Ralph Goers <ra...@dslextreme.com> on 2014/08/20 22:04:01 UTC
Re: svn commit: r1619026 - in /logging/log4j/log4j2/trunk: log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/ log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/ src/changes/ src/site/xdoc/manual/
Why is the lookup that returns JVM arguments named jmx-input? That just seems strange.
Ralph
On Aug 19, 2014, at 8:19 PM, ggregory@apache.org wrote:
> Author: ggregory
> Date: Wed Aug 20 03:19:09 2014
> New Revision: 1619026
>
> URL: http://svn.apache.org/r1619026
> Log:
> [LOG4J2-771] Add lookup for application main arguments.
> [LOG4J2-787] Add lookup for JVM arguments.
>
> Added:
> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java (with props)
> logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java (with props)
> logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java (with props)
> Modified:
> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
> logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MapLookup.java
> logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MapLookupTest.java
> logging/log4j/log4j2/trunk/src/changes/changes.xml
> logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml.vm
> logging/log4j/log4j2/trunk/src/site/xdoc/manual/lookups.xml
>
> Modified: logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java
> URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java?rev=1619026&r1=1619025&r2=1619026&view=diff
> ==============================================================================
> --- logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java (original)
> +++ logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/Interpolator.java Wed Aug 20 03:19:09 2014
> @@ -27,7 +27,7 @@ import org.apache.logging.log4j.core.uti
> import org.apache.logging.log4j.status.StatusLogger;
>
> /**
> - * Proxies all the other StrLookups.
> + * Proxies all the other {@link StrLookup}s.
> */
> public class Interpolator implements StrLookup {
>
> @@ -72,6 +72,8 @@ public class Interpolator implements Str
> // TODO: this ought to use the PluginManager
> lookups.put("sys", new SystemPropertiesLookup());
> lookups.put("env", new EnvironmentLookup());
> + lookups.put("main", MapLookup.MAIN_SINGLETON);
> + // JNDI
> try {
> // [LOG4J2-703] We might be on Android
> lookups.put("jndi",
> @@ -82,6 +84,17 @@ public class Interpolator implements Str
> "JNDI lookup class is not available because this JRE does not support JNDI. JNDI string lookups will not be available, continuing configuration.",
> e);
> }
> + // JMX input args
> + try {
> + // We might be on Android
> + lookups.put("jmx-input",
> + Loader.newCheckedInstanceOf("org.apache.logging.log4j.core.lookup.JmxRuntimeInputArgumentsLookup", StrLookup.class));
> + } catch (Throwable e) {
> + // java.lang.VerifyError: org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup
> + LOGGER.warn(
> + "JMX runtime input lookup class is not available because this JRE does not support JMX. JMX lookups will not be available, continuing configuration.",
> + e);
> + }
> lookups.put("date", new DateLookup());
> lookups.put("ctx", new ContextMapLookup());
> if (Loader.isClassAvailable("javax.servlet.ServletContext")) {
>
> Added: logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java
> URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java?rev=1619026&view=auto
> ==============================================================================
> --- logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java (added)
> +++ logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java Wed Aug 20 03:19:09 2014
> @@ -0,0 +1,29 @@
> +package org.apache.logging.log4j.core.lookup;
> +
> +import java.lang.management.ManagementFactory;
> +import java.util.List;
> +import java.util.Map;
> +
> +import org.apache.logging.log4j.core.config.plugins.Plugin;
> +
> +/**
> + * Maps JVM input arguments (but not main arguments) using JMX to acquire JVM arguments.
> + *
> + * @see java.lang.management.RuntimeMXBean#getInputArguments()
> + * @since 2.1
> + */
> +@Plugin(name = "jmx-input", category = "Lookup")
> +public class JmxRuntimeInputArgumentsLookup extends MapLookup {
> +
> + static {
> + List<String> argsList = ManagementFactory.getRuntimeMXBean().getInputArguments();
> + JMX_SINGLETON = new JmxRuntimeInputArgumentsLookup(MapLookup.toMap(argsList));
> + }
> +
> + public static final JmxRuntimeInputArgumentsLookup JMX_SINGLETON;
> +
> + public JmxRuntimeInputArgumentsLookup(Map<String, String> map) {
> + super(map);
> + }
> +
> +}
>
> Propchange: logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/JmxRuntimeInputArgumentsLookup.java
> ------------------------------------------------------------------------------
> svn:keywords = Id
>
> Modified: logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MapLookup.java
> URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MapLookup.java?rev=1619026&r1=1619025&r2=1619026&view=diff
> ==============================================================================
> --- logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MapLookup.java (original)
> +++ logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/lookup/MapLookup.java Wed Aug 20 03:19:09 2014
> @@ -16,6 +16,8 @@
> */
> package org.apache.logging.log4j.core.lookup;
>
> +import java.util.HashMap;
> +import java.util.List;
> import java.util.Map;
>
> import org.apache.logging.log4j.core.LogEvent;
> @@ -23,25 +25,82 @@ import org.apache.logging.log4j.core.con
> import org.apache.logging.log4j.message.MapMessage;
>
> /**
> - * The basis for a lookup based on a Map.
> + * A map-based lookup.
> */
> @Plugin(name = "map", category = "Lookup")
> public class MapLookup implements StrLookup {
> -
> +
> /**
> - * Map keys are variable names and value.
> + * A singleton used by a main method to save its arguments.
> */
> - private final Map<String, String> map;
> + static final MapLookup MAIN_SINGLETON = new MapLookup(newMap(0));
> +
> + static Map<String, String> initMap(final String[] srcArgs, final Map<String, String> destMap) {
> + for (int i = 0; i < srcArgs.length; i++) {
> + final int next = i + 1;
> + final String value = srcArgs[i];
> + destMap.put(Integer.toString(i), value);
> + destMap.put(value, next < srcArgs.length ? srcArgs[next] : null);
> + }
> + return destMap;
> + }
> +
> + private static HashMap<String, String> newMap(final int initialCapacity) {
> + return new HashMap<String, String>(initialCapacity);
> + }
>
> /**
> - * Creates a new instance backed by a Map. Used by the default lookup.
> - *
> - * @param map the map of keys to values, may be null
> + * An application's {@code public static main(String[])} method calls this method to make its main arguments
> + * available for lookup with the prefix {@code main}.
> + * <p>
> + * The map provides two kinds of access: First by index, starting at {@code "0"}, {@code "1"} and so on. For
> + * example, the command line {@code --file path/file.txt -x 2} can be accessed from a configuration file with:
> + * </p>
> + * <ul>
> + * <li>{@code "main:0"} = {@code "--file"}</li>
> + * <li>{@code "main:1"} = {@code "path/file.txt"}</li>
> + * <li>{@code "main:2"} = {@code "-x"}</li>
> + * <li>{@code "main:3"} = {@code "2"}</li>
> + * </ul>
> + * <p>
> + * Second using the argument at position n as the key to access the value at n+1.
> + * </p>
> + * <ul>
> + * <li>{@code "main:--file"} = {@code "path/file.txt"}</li>
> + * <li>{@code "main:-x"} = {@code "2"}</li>
> + * </ul>
> + *
> + * @param args
> + * An application's {@code public static main(String[])} arguments.
> + * @since 2.1
> */
> - public MapLookup(final Map<String, String> map) {
> - this.map = map;
> + public static void setMainArguments(final String[] args) {
> + if (args == null) {
> + return;
> + }
> + initMap(args, MAIN_SINGLETON.map);
> + }
> +
> + static Map<String, String> toMap(final List<String> args) {
> + if (args == null) {
> + return null;
> + }
> + final int size = args.size();
> + return initMap(args.toArray(new String[size]), newMap(size));
> }
>
> + static Map<String, String> toMap(final String[] args) {
> + if (args == null) {
> + return null;
> + }
> + return initMap(args, newMap(args.length));
> + }
> +
> + /**
> + * Map keys are variable names and value.
> + */
> + private final Map<String, String> map;
> +
> /**
> * Constructor when used directly as a plugin.
> */
> @@ -50,21 +109,13 @@ public class MapLookup implements StrLoo
> }
>
> /**
> - * Looks up a String key to a String value using the map.
> - * <p>
> - * If the map is null, then null is returned.
> - * The map result object is converted to a string using toString().
> - * </p>
> + * Creates a new instance backed by a Map. Used by the default lookup.
> *
> - * @param key the key to be looked up, may be null
> - * @return the matching value, null if no match
> + * @param map
> + * the map of keys to values, may be null
> */
> - @Override
> - public String lookup(final String key) {
> - if (map == null) {
> - return null;
> - }
> - return map.get(key);
> + public MapLookup(final Map<String, String> map) {
> + this.map = map;
> }
>
> @Override
> @@ -83,4 +134,23 @@ public class MapLookup implements StrLoo
> }
> return null;
> }
> +
> + /**
> + * Looks up a String key to a String value using the map.
> + * <p>
> + * If the map is null, then null is returned. The map result object is converted to a string using toString().
> + * </p>
> + *
> + * @param key
> + * the key to be looked up, may be null
> + * @return the matching value, null if no match
> + */
> + @Override
> + public String lookup(final String key) {
> + if (map == null) {
> + return null;
> + }
> + return map.get(key);
> + }
> +
> }
>
> Added: logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java
> URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java?rev=1619026&view=auto
> ==============================================================================
> --- logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java (added)
> +++ logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java Wed Aug 20 03:19:09 2014
> @@ -0,0 +1,57 @@
> +/*
> + * 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.logging.log4j.core.lookup;
> +
> +import static org.junit.Assert.assertEquals;
> +
> +import org.junit.Test;
> +
> +/**
> + * Tests {@link JmxRuntimeInputArgumentsLookup} from the command line, not a JUnit test.
> + *
> + * From an IDE or CLI: --file foo.txt
> + *
> + * @since 2.1
> + */
> +public class MainInputArgumentsJmxLookupTest {
> +
> + public static void main(String[] args) {
> + new MainInputArgumentsJmxLookupTest().callFromMain();
> + }
> +
> + @Test
> + public void testMap() {
> + JmxRuntimeInputArgumentsLookup lookup = JmxRuntimeInputArgumentsLookup.JMX_SINGLETON;
> + assertEquals(null, lookup.lookup(null));
> + assertEquals(null, lookup.lookup("X"));
> + assertEquals(null, lookup.lookup("foo.txt"));
> + }
> +
> + public void callFromMain() {
> + JmxRuntimeInputArgumentsLookup lookup = JmxRuntimeInputArgumentsLookup.JMX_SINGLETON;
> + assertEquals(null, lookup.lookup(null));
> + assertEquals(null, lookup.lookup("X"));
> + // Eclipse adds -Dfile.encoding=Cp1252
> + // assertEquals("--file", lookup.lookup("0"));
> + // assertEquals("foo.txt", lookup.lookup("1"));
> + //
> + // JMX does not include the main arguments.
> + // assertEquals("foo.txt", lookup.lookup("--file"));
> + // assertEquals(null, lookup.lookup("foo.txt"));
> + }
> +
> +}
>
> Propchange: logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsJmxLookupTest.java
> ------------------------------------------------------------------------------
> svn:keywords = Id
>
> Added: logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java
> URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java?rev=1619026&view=auto
> ==============================================================================
> --- logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java (added)
> +++ logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java Wed Aug 20 03:19:09 2014
> @@ -0,0 +1,41 @@
> +package org.apache.logging.log4j.core.lookup;
> +
> +import java.util.Map;
> +
> +/**
> + * Work in progress, saved for future experimentation.
> + *
> + * TODO The goal is to use the Sun debugger API to find the main arg values on the stack.
> + */
> +public class MainInputArgumentsMapLookup extends MapLookup {
> +
> + public static final MainInputArgumentsMapLookup SINGLETON_STACK;
> +
> + static {
> + Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
> + String[] args = null;
> + for (Map.Entry<Thread, StackTraceElement[]> entry : allStackTraces.entrySet()) {
> + StackTraceElement[] stackTraceElements = entry.getValue();
> + Thread thread = entry.getKey();
> + // Can't use the thread name to look for "main" since anyone can set it.
> + // Can't use thread ID since it can be any positive value, and is likely vender dependent. Oracle seems to
> + // use 1.
> + // We are left to look for "main" at the top of the stack
> + if (stackTraceElements != null) {
> + final int frame0 = stackTraceElements.length - 1;
> + if ("main".equals(stackTraceElements[frame0].getMethodName())) {
> + // We could further validate the main is a public static void method that takes a String[], if not,
> + // look at the other threads.
> + //
> + // How do we get the main args from the stack with the debug API?
> + // Must we be started in debug mode? Seems like it.
> + }
> + }
> + }
> + SINGLETON_STACK = new MainInputArgumentsMapLookup(MapLookup.toMap(args));
> + }
> +
> + public MainInputArgumentsMapLookup(Map<String, String> map) {
> + super(map);
> + }
> +}
>
> Propchange: logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MainInputArgumentsMapLookup.java
> ------------------------------------------------------------------------------
> svn:keywords = Id
>
> Modified: logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MapLookupTest.java
> URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MapLookupTest.java?rev=1619026&r1=1619025&r2=1619026&view=diff
> ==============================================================================
> --- logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MapLookupTest.java (original)
> +++ logging/log4j/log4j2/trunk/log4j-core/src/test/java/org/apache/logging/log4j/core/lookup/MapLookupTest.java Wed Aug 20 03:19:09 2014
> @@ -49,4 +49,19 @@ public class MapLookupTest {
> assertEquals(null, lookup.lookup(null));
> assertEquals(null, lookup.lookup("X"));
> }
> +
> + @Test
> + public void testMainMap() {
> + MapLookup.setMainArguments(new String[] {
> + "--file",
> + "foo.txt" });
> + MapLookup lookup = MapLookup.MAIN_SINGLETON;
> + assertEquals(null, lookup.lookup(null));
> + assertEquals(null, lookup.lookup("X"));
> + assertEquals("--file", lookup.lookup("0"));
> + assertEquals("foo.txt", lookup.lookup("1"));
> + assertEquals("foo.txt", lookup.lookup("--file"));
> + assertEquals(null, lookup.lookup("foo.txt"));
> + }
> +
> }
>
> Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
> URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1619026&r1=1619025&r2=1619026&view=diff
> ==============================================================================
> --- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
> +++ logging/log4j/log4j2/trunk/src/changes/changes.xml Wed Aug 20 03:19:09 2014
> @@ -21,10 +21,16 @@
> <title>Changes</title>
> </properties>
> <body>
> - <release version="2.?.?" date="2014-??-??" description="Bug fixes and enhancements">
> + <release version="2.?.?" date="2014-??-??" description="Bug fixes and enhancements">
> <action issue="LOG4J2-783" dev="rpopma" type="fix" due-to="Minglei Lee">
> PatternLayout should use platform character encoding by default, not UTF-8.
> </action>
> + <action issue="LOG4J2-771" dev="ggregory" type="add">
> + Add lookup for application main arguments.
> + </action>
> + <action issue="LOG4J2-787" dev="ggregory" type="add">
> + Add lookup for JVM arguments.
> + </action>
> </release>
> <release version="2.0.2" date="2014-08-16" description="Bug fixes and enhancements">
> <action issue="LOG4J2-775" dev="ggregory" type="update">
>
> Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml.vm
> URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml.vm?rev=1619026&r1=1619025&r2=1619026&view=diff
> ==============================================================================
> --- logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml.vm (original)
> +++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/configuration.xml.vm Wed Aug 20 03:19:09 2014
> @@ -869,6 +869,14 @@ public class Bar {
> <td>System environment variables</td>
> </tr>
> <tr>
> + <td>jmx-input</td>
> + <td>A JVM input argument accessed through JMX, but not a main argument; see <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/management/RuntimeMXBean.html#getInputArguments--">RuntimeMXBean.html#getInputArguments()</a></td>
> + </tr>
> + <tr>
> + <td>main</td>
> + <td>A value set with <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/MapLookup.html#setMainArguments%28java.lang.String[]%29">MapLookup.setMainArguments(String[])</a></td>
> + </tr>
> + <tr>
> <td>map</td>
> <td>A value from a MapMessage</td>
> </tr>
>
> Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/lookups.xml
> URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/lookups.xml?rev=1619026&r1=1619025&r2=1619026&view=diff
> ==============================================================================
> --- logging/log4j/log4j2/trunk/src/site/xdoc/manual/lookups.xml (original)
> +++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/lookups.xml Wed Aug 20 03:19:09 2014
> @@ -98,11 +98,12 @@
> <subsection name="MapLookup">
> <a name="MapLookup"/>
> <p>
> - The MapLookup serves two purposes.
> + The MapLookup serves several purposes.
> </p>
> <ol>
> <li>Provide the base for Properties declared in the configuration file.</li>
> <li>Retrieve values from MapMessages in LogEvents.</li>
> + <li>Retrieve values set with <a href="../log4j-core/apidocs/org/apache/logging/log4j/core/lookup/MapLookup.html#setMainArguments%28java.lang.String[]%29">MapLookup.setMainArguments(String[])</a></li>
> </ol>
> <p>
> The first item simply means that the MapLookup is used to substitute properties that are defined
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org