meg*_*off 3 java logging properties
如何通过属性配置 java.util.logging 以使用标准输出而不是标准错误?
我当前的财产文件
# Logging
handlers = java.util.logging.ConsoleHandler
# Console Logging
java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format = %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n
Run Code Online (Sandbox Code Playgroud)
从<logger>.handlers属性派生新的处理程序java.util.logging.StreamHandler并使用其\n完全限定名称。
(如果使用 Apache Maven,请注意使用 Surefire 插件作为IPC及其分叉子项stdout的手段,因此在测试期间会出现损坏警告,请参阅此处。)
例如(Java 9+)...
\n\n布局目录:
\n\nmkdir -p /tmp/logger/{src/org.foo/{{classes,tests}/org/foo/logging{,/internal},resources},{build/modules/org.foo,dist}}\nRun Code Online (Sandbox Code Playgroud)\n\n验证布局:
\n\ncd /tmp/logger && gio tree --hidden\nRun Code Online (Sandbox Code Playgroud)\n\n文件:///tmp/logger\n|-- 构建\n| `-- 模块\n| `-- org.foo\n|-- dist\n`-- src\n `-- org.foo\n |-- 类\n | `-- 组织\n | `-- foo\n | `-- 日志记录\n | `-- 内部\n |-- 资源\n `-- 测试\n `-- org\n `-- foo\n `-- 日志记录\n `-- 内部\n\n\n
在分支下写类src/org.foo/classes。
一个处理程序。
\n\npackage org.foo.logging.internal;\n\nimport java.io.FileDescriptor;\nimport java.io.FileOutputStream;\nimport java.util.Objects;\n\nimport java.util.logging.Formatter;\nimport java.util.logging.LogRecord;\nimport java.util.logging.SimpleFormatter;\nimport java.util.logging.StreamHandler;\n\npublic class StandardOutConsoleHandler extends StreamHandler\n{\n public StandardOutConsoleHandler(Formatter formatter)\n {\n super(new FileOutputStream(FileDescriptor.out),\n Objects.requireNonNull(formatter, "formatter"));\n }\n\n public StandardOutConsoleHandler() { this(new SimpleFormatter()); }\n\n /* Taken from java.logging/java.util.logging.ConsoleHandler. */\n @Override\n public void publish(LogRecord record)\n {\n super.publish(record);\n flush();\n }\n\n /* Taken from java.logging/java.util.logging.ConsoleHandler. */\n @Override\n public void close() { flush(); }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n过滤器(可选)。
\n\npackage org.foo.logging.internal;\n\nimport java.time.LocalTime;\nimport java.time.ZoneId;\nimport java.time.temporal.TemporalAccessor;\nimport java.time.temporal.TemporalQuery;\nimport java.util.Objects;\n\nimport java.util.logging.Filter;\nimport java.util.logging.LogRecord;\n\npublic class WallClockTimeFilter implements Filter\n{\n private static final TemporalQuery<Boolean> BUSINESS_HOURS\n = new BusinessHours();\n\n static class BusinessHours implements TemporalQuery<Boolean>\n {\n private static final LocalTime FROM = LocalTime.of(9, 0);\n private static final LocalTime TO = LocalTime.of(17, 0);\n\n @Override\n public Boolean queryFrom(TemporalAccessor temporal)\n {\n final LocalTime now = LocalTime.from(temporal);\n return (now.isAfter(FROM) && now.isBefore(TO));\n }\n }\n\n @Override\n public boolean isLoggable(LogRecord record)\n {\n Objects.requireNonNull(record, "record");\n final LocalTime now = LocalTime.ofInstant(record.getInstant(),\n ZoneId.systemDefault());\n return now.query(BUSINESS_HOURS);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n属性配置器。
\n\npackage org.foo.logging.internal;\n\nimport java.io.IOException;\nimport java.io.InputStream;\n\nimport java.util.logging.LogManager;\n\n/*\n * This class could be referenced on the command-line as follows\n *\n * -Djava.util.logging.config.class=org.foo.logging.internal.LoggingPropertiesConfigurer\n *\n * See java.logging/java.util.logging.LogManager#readConfiguration().\n */\npublic class LoggingPropertiesConfigurer\n{\n private static final String RESOURCE = "/logging.properties";\n\n public LoggingPropertiesConfigurer() throws IOException\n {\n try (final InputStream is = getClass().getResourceAsStream(\n RESOURCE)) {\n if (is == null)\n throw new IllegalStateException(\n String.format("Unavailable resource: \'%s\'",\n RESOURCE));\n\n /* Prefer new non-null values over old values. */\n LogManager.getLogManager().updateConfiguration(is,\n property ->\n ((oldValue, newValue) -> {\n return (oldValue == null && newValue == null)\n ? null /* Discard the property. */\n : (newValue == null)\n ? oldValue\n : newValue;\n }));\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n一个假人。
\n\npackage org.foo.logging;\n\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.Optional;\n\nimport java.util.logging.Logger;\n\nimport org.foo.logging.internal.LoggingPropertiesConfigurer;\n\npublic class Dummy\n{\n static {\n try {\n final String fileName = System.getProperty(\n "java.util.logging.config.file");\n final String klassName = System.getProperty(\n "java.util.logging.config.class");\n\n if (klassName == null && fileName == null)\n new LoggingPropertiesConfigurer();\n } catch (final IOException e) {\n throw new ExceptionInInitializerError(e);\n }\n }\n\n static Optional<Logger> getLogger()\n {\n /*\n * Note that for any org.foo.Bar.Baz.Quux member class\n * Class::getName returns an org.foo.Bar$Baz$Quux string,\n * therefore name accordingly these loggers, if any, in\n * the properties files, e.g.\n * org.foo.Bar$Baz$Quux.level = WARNING\n */\n return Optional.ofNullable(Logger.getLogger(\n Dummy.class.getName()));\n }\n\n public static void main(String[] args)\n {\n /*\n * A weakly-reachable logger.\n *\n * See java.base/java.lang.ref.Reference#reachabilityFence(Object)\n */\n Dummy.getLogger().ifPresent(logger -> logger.warning(() ->\n Arrays.toString(args)));\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n将模块声明编写为src/org.foo/classes/module-info.java.
module org.foo {\n requires transitive java.logging;\n\n exports org.foo.logging;\n\n exports org.foo.logging.internal to\n java.logging;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n编译类:
\n\njavac -Xlint -d build/modules --module-source-path src/\\*/classes/ $(find src/*/classes/ -type f -name \\*.java)\nRun Code Online (Sandbox Code Playgroud)\n\n描述一个模块:
\n\njava --describe-module org.foo --module-path build/modules\nRun Code Online (Sandbox Code Playgroud)\n\n将属性文件编写为src/org.foo/resources/logging.properties.
## From [java.home]/conf/logging.properties:\n# handlers = java.util.logging.ConsoleHandler\n\nhandlers = org.foo.logging.internal.StandardOutConsoleHandler\n\njava.util.logging.SimpleFormatter.format = %1$tY-%<tm-%<td %<tH:%<tM:%<tS %4$s %2$s %5$s%6$s%n\n\n## See the Javadoc of java.logging/java.util.logging.StreamHandler.\norg.foo.logging.internal.StandardOutConsoleHandler.level = ALL\n# org.foo.logging.internal.StandardOutConsoleHandler.filter = org.foo.logging.internal.WallClockTimeFilter\norg.foo.logging.internal.StandardOutConsoleHandler.formatter = java.util.logging.SimpleFormatter\norg.foo.logging.internal.StandardOutConsoleHandler.encoding = ISO-8859-1\nRun Code Online (Sandbox Code Playgroud)\n\n复制一份用于包装:
\n\ncp -t build/modules/org.foo src/org.foo/resources/logging.properties\nRun Code Online (Sandbox Code Playgroud)\n\n打包类和复制的资源(观察末尾的. ):
\n\njar --create --module-version 0.0.1 --file dist/logger-0.0.1.jar --main-class org.foo.logging.Dummy -C build/modules/org.foo/ .\nRun Code Online (Sandbox Code Playgroud)\n\n尝试使用重定向运行stdout, stderr。\n
\nStdout记录。当当地时间允许时,取消注释中与时间相关的过滤器行logging.properties:
java -Xdiag --module-path dist/logger-0.0.1.jar --module org.foo raison d\\\'\xc3\xaatre 2>/dev/null\nRun Code Online (Sandbox Code Playgroud)\n\nStderr记录。将/path/to/jdk替换为 Java 安装目录的真实路径:
java -enablesystemassertions -Xdiag -Djava.util.logging.config.file=/path/to/jdk/conf/logging.properties --module-path dist/logger-0.0.1.jar --module org.foo raison d\\\'\xc3\xaatre 2>/dev/null\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
5240 次 |
| 最近记录: |