├── .classpath
├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── .project
├── .settings
└── org.eclipse.jdt.core.prefs
├── LICENSE
├── README.md
├── beautiful_logger2.iml
├── pom.xml
└── src
├── main
└── java
│ ├── com.github.forax.beautifullogger
│ ├── Logger.java
│ ├── LoggerConfig.java
│ └── LoggerImpl.java
│ └── com
│ └── github
│ └── forax
│ └── beautifullogger
│ └── tool
│ ├── LoggerGenerator.java
│ ├── ModuleInfoGenerator.java
│ ├── ReflectionSupplier.java
│ ├── ReflectionSupplierEncoder.java
│ └── Rewriter.java
└── test
├── java
└── com
│ └── github
│ └── forax
│ └── beautifullogger
│ ├── LoggerConfigSupport.java
│ ├── LoggerConfigurationTests.java
│ ├── LoggerLevelTests.java
│ ├── integration
│ ├── jul
│ │ └── VerySimpleTests.java
│ ├── log4j
│ │ └── VerySimpleTests.java
│ ├── slf4j
│ │ └── VerySimpleTests.java
│ └── systemlogger
│ │ └── VerySimpleTests.java
│ └── perf
│ ├── LoggerDisabledBenchMark.java
│ ├── LoggerDisabledLoopBenchMark.java
│ └── PatternBenchMark.java
└── resources
├── com.github.forax.beautifullogger.integration.log4j
└── log4j2.xml
├── com.github.forax.beautifullogger.integration.logback
└── logback.xml
├── com.github.forax.beautifullogger.integration.slf4j
└── logback.xml
└── com.github.forax.beautifullogger.perf
├── log4j2.xml
└── logback.xml
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Continuous Integration
2 | on:
3 | schedule:
4 | - cron: "0 0 * * *"
5 | push:
6 | branches: [ master ]
7 | pull_request:
8 | branches: [ master ]
9 | workflow_dispatch:
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 | strategy:
15 | matrix:
16 | java: [ '8', '9', '11', '13', '15', '17', '21', '24' ]
17 | name: Java ${{ matrix.Java }} sample
18 | steps:
19 | - uses: actions/checkout@v3
20 | - name: Setup java
21 | uses: actions/setup-java@v3
22 | with:
23 | distribution: 'zulu'
24 | java-version: ${{ matrix.java }}
25 | - name: build
26 | run: mvn -B package
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.ear
17 | *.zip
18 | *.tar.gz
19 | *.rar
20 |
21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
22 | hs_err_pid*
23 |
24 | # Everything below bin/.
25 | /bin/
26 |
27 | # IDEA files
28 | /.idea/
29 |
30 | /classes/
31 | /target/
32 | /deps/
33 | /eclipse-output/
34 | /pro/
35 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | beautiful_logger2
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
3 | org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
4 | org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
5 | org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
6 | org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
7 | org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
8 | org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
9 | org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
10 | org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
11 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
12 | org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
13 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
14 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
15 | org.eclipse.jdt.core.compiler.compliance=11
16 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
17 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
18 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
19 | org.eclipse.jdt.core.compiler.doc.comment.support=enabled
20 | org.eclipse.jdt.core.compiler.problem.APILeak=warning
21 | org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
22 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
23 | org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
24 | org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
25 | org.eclipse.jdt.core.compiler.problem.deadCode=warning
26 | org.eclipse.jdt.core.compiler.problem.deprecation=warning
27 | org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
28 | org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
29 | org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
30 | org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
31 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
32 | org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning
33 | org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
34 | org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
35 | org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
36 | org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
37 | org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
38 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
39 | org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
40 | org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
41 | org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
42 | org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
43 | org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
44 | org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error
45 | org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
46 | org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
47 | org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
48 | org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
49 | org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
50 | org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
51 | org.eclipse.jdt.core.compiler.problem.missingDefaultCase=warning
52 | org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
53 | org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
54 | org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
55 | org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
56 | org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
57 | org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
58 | org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags
59 | org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error
60 | org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=enabled
61 | org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
62 | org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public
63 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
64 | org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
65 | org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
66 | org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
67 | org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
68 | org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
69 | org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
70 | org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
71 | org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
72 | org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
73 | org.eclipse.jdt.core.compiler.problem.nullReference=warning
74 | org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
75 | org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
76 | org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
77 | org.eclipse.jdt.core.compiler.problem.parameterAssignment=warning
78 | org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
79 | org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
80 | org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
81 | org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
82 | org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
83 | org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
84 | org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
85 | org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning
86 | org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
87 | org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=warning
88 | org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=warning
89 | org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
90 | org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
91 | org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
92 | org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
93 | org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
94 | org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning
95 | org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
96 | org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
97 | org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
98 | org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
99 | org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
100 | org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
101 | org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
102 | org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
103 | org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
104 | org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=warning
105 | org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning
106 | org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
107 | org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
108 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
109 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
110 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
111 | org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
112 | org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=warning
113 | org.eclipse.jdt.core.compiler.problem.unusedImport=warning
114 | org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
115 | org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
116 | org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
117 | org.eclipse.jdt.core.compiler.problem.unusedParameter=warning
118 | org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
119 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
120 | org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
121 | org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
122 | org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=warning
123 | org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
124 | org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
125 | org.eclipse.jdt.core.compiler.release=enabled
126 | org.eclipse.jdt.core.compiler.source=11
127 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Rémi Forax
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # beautiful_logger [](https://github.com/forax/beautiful_logger/actions/workflows/main.yml)
2 | Yet another logger API in Java with beautiful features
3 |
4 | beautiful_logger is a mostly-zero-overhead wrapper on top of the existing logging implementations with a familiar API (info, error, etc)
5 | that let you configure/re-configure the logger dynamically in a programmatic way.
6 |
7 | This library requires at least Java 8 at runtime and is fully compatible with Java 9 modules.
8 |
9 | For the support of Java 15+, the version 0.10.4+ should be used.
10 |
11 | The javadoc of the latest version is [available online](https://jitpack.io/com/github/forax/beautiful_logger/master-SNAPSHOT/javadoc/).
12 |
13 | ## Features
14 | - *real* zero cost (no allocation, no branch, no assembly code) if a logger is disabled
15 | - zero overhead cost when delegating to the logging libraries you already use, SLF4J, Log4J, Logback, JUL or SystemLogger [JEP 264](http://openjdk.java.net/jeps/264).
16 | - dynamic configuration/re-configuration which doesn't use costly inter-thread signaling
17 | - no configuration file, no XML, etc, everything is done programmatically
18 | - very small modular jar with no dependency
19 |
20 |
21 | ## Why another logging API ?
22 |
23 | Technically it's more a facade like SLF4J, anyway, beautiful_logger exists because no other existing logging libraries
24 | provide at least one of features listed above.
25 |
26 |
27 | ## Why do you claim that there is no overhead ?
28 |
29 | The implementation of this API ensures that the JIT can fully inline any calls to the Logger API without decrementing your inlining budget.
30 | This is similar to the way, MethodHandle or VarHandle are optimized in the JDK.
31 | The main drawback is that it put more pressure to the JITs so it may lengthen the time to steady state of an application.
32 |
33 |
34 | ## Example
35 |
36 | ```java
37 | import com.github.forax.beautifullogger.Logger;
38 |
39 | class Example {
40 | // getLogger with no argument uses the current class as configuration class
41 | private static final Logger LOGGER = Logger.getLogger();
42 |
43 | public static void main(String[] args) {
44 | for(int i = 0; i < 10; i++) {
45 | // use a lambda that does not capture any parameters
46 | LOGGER.error((int value) -> "message " + value, i);
47 |
48 | if (i == 1) {
49 | // disable the logger programmatically
50 | LoggerConfig.fromClass(Example.class).update(opt -> opt.enable(false));
51 | }
52 | }
53 | }
54 | }
55 | ```
56 |
57 | ## Build Tool Integration [](https://jitpack.io/#forax/beautiful_logger)
58 |
59 | Get latest binary distribution via [JitPack](https://jitpack.io/#forax/beautiful_logger)
60 |
61 |
62 | ### Maven
63 |
64 | ```xml
65 |
66 |
67 | jitpack.io
68 | https://jitpack.io
69 |
70 |
71 |
72 | com.github.forax
73 | beautiful_logger
74 | master-SNAPSHOT
75 |
76 | ```
77 |
78 | ### Gradle
79 |
80 | ```gradle
81 | repositories {
82 | ...
83 | maven { url 'https://jitpack.io' }
84 | }
85 | dependencies {
86 | compile 'com.github.forax:beautiful_logger:master-SNAPSHOT'
87 | }
88 | ```
--------------------------------------------------------------------------------
/beautiful_logger2.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | com.github.forax
6 | beautifullogger
7 | 0.11
8 |
9 | ${project.groupId}:${project.artifactId}
10 | Yet another logger API in Java with beautiful features
11 | https://github.com/forax/beautiful_logger
12 |
13 |
14 |
15 | MIT License
16 | http://www.opensource.org/licenses/mit-license.php
17 |
18 |
19 |
20 |
21 |
22 | Remi Forax
23 | forax@univ-mlv.fr
24 | University Paris-East Marne-la-vallee
25 | http://www.u-pem.fr/
26 |
27 |
28 |
29 |
30 | scm:git:git@github.com:forax/beautiful_logger.git
31 | scm:git:ssh://github.com:forax/beautiful_logger.git
32 | https://github.com/forax/beautiful_logger/blob/master/
33 |
34 |
35 |
36 |
37 | UTF-8
38 |
39 |
40 |
41 |
42 | org.ow2.asm
43 | asm
44 | 9.7.1
45 | true
46 |
47 |
48 |
49 | org.junit.jupiter
50 | junit-jupiter-api
51 | 5.11.4
52 | test
53 |
54 |
55 | org.junit.jupiter
56 | junit-jupiter-params
57 | 5.11.4
58 | test
59 |
60 |
61 |
62 | org.openjdk.jmh
63 | jmh-core
64 | 1.37
65 | true
66 |
67 |
68 |
69 | org.apache.logging.log4j
70 | log4j-core
71 | 2.24.3
72 | true
73 |
74 |
75 | org.slf4j
76 | slf4j-api
77 | 2.0.16
78 | true
79 |
80 |
81 | ch.qos.logback
82 | logback-classic
83 | 1.3.15
84 | true
85 |
86 |
87 | ch.qos.logback
88 | logback-core
89 | 1.3.15
90 | true
91 |
92 |
93 |
94 | com.google.flogger
95 | flogger
96 | 0.8
97 | test
98 | true
99 |
100 |
101 |
102 |
103 |
104 |
105 | org.apache.maven.plugins
106 | maven-compiler-plugin
107 | 3.13.0
108 |
109 |
110 | 1.8
111 | 1.8
112 |
113 |
114 |
115 |
116 | maven-surefire-plugin
117 | 3.5.2
118 |
119 |
120 |
121 | org.codehaus.mojo
122 | exec-maven-plugin
123 | 3.5.0
124 |
125 |
126 | prepare-package
127 | module-generator
128 |
129 | java
130 |
131 |
132 | com.github.forax.beautifullogger.tool.ModuleInfoGenerator
133 |
134 | target/classes
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 | org.apache.maven.plugins
143 | maven-javadoc-plugin
144 | 3.11.2
145 |
146 | src/main/java/
147 | 8
148 |
149 |
150 |
151 |
152 | attach-javadocs
153 |
154 | jar
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/src/main/java/com.github.forax.beautifullogger/Logger.java:
--------------------------------------------------------------------------------
1 | package com.github.forax.beautifullogger;
2 |
3 | import java.lang.invoke.MethodHandle;
4 | import java.util.Objects;
5 | import java.util.function.BiFunction;
6 | import java.util.function.Consumer;
7 | import java.util.function.DoubleFunction;
8 | import java.util.function.Function;
9 | import java.util.function.IntFunction;
10 | import java.util.function.LongFunction;
11 | import java.util.function.Supplier;
12 |
13 | import com.github.forax.beautifullogger.LoggerConfig.ConfigOption;
14 |
15 | /**
16 | * Log events of the application.
17 | *
18 | * A logger is created using one of the methods {@link #getLogger(Class, Consumer) getLogger}.
19 | * The {@link LoggerConfig configuration} of a that Logger is associated to the class
20 | * that construct it.
21 | *
22 | *
30 | *
31 | * To log an event, one should call the method named by the severity of the event,
32 | * trace for level TRACE, debug for level DEBUG, etc.
33 | *
34 | *
40 | *
41 | * Each logging method has several overloads allowing to choose a message provider
42 | * to avoid if possible, allocations due to concatenation, non constant lambda or
43 | * boxing of primitive values.
44 | *
45 | *
46 | *
47 | *
message providers
48 | *
String
constant String (do not use concatenation !)
49 | *
Supplier
costly operation that does not need arguments
50 | *
Function
costly operation that needs one Object argument
51 | *
IntFunction
costly operation that needs one integer argument
52 | *
LongFunction
costly operation that needs one long argument
53 | *
DoubleFunction
costly operation that needs one double argument
54 | *
BiFunction
costly operation that needs two arguments
55 | *
supported message providers
56 | *
57 | *
58 | */
59 | public interface Logger {
60 | /**
61 | * Log levels used for indicating the severity of an event.
62 | *
63 | * Log levels are ordered from the least specific to the most,
64 | * TRACE < DEBUG < INFO < WARNING < ERROR.
65 | *
66 | * All methods of {@link Logger} are emitted with a a log level
67 | * corresponding to name of the method, the configuration level
68 | * of a Logger can be changed using {@link LoggerConfig#update(Consumer) logConfig.update(upd -> upd.level(aLevel))}.
69 | *
70 | * @see LoggerConfig#level()
71 | */
72 | public enum Level {
73 | /** a fine grained debug level */
74 | TRACE,
75 | /** a general debug level */
76 | DEBUG,
77 | /** an information level */
78 | INFO,
79 | /** a non normal state level */
80 | WARNING,
81 | /** an error level */
82 | ERROR;
83 |
84 | static final Level[] LEVELS = values();
85 | }
86 |
87 | /**
88 | * Log a message at {@link Level#ERROR} level with an exception.
89 | * @param message the log message.
90 | * @param context an exception or null.
91 | */
92 | void error(String message, Throwable context);
93 | /**
94 | * Log a message provided by the supplier at {@link Level#ERROR} level.
95 | * @param messageProvider the provider of the message.
96 | */
97 | void error(Supplier messageProvider);
98 | /**
99 | * Log a message provided by the function at {@link Level#ERROR} level.
100 | * @param the type of the first argument.
101 | * @param messageProvider the provider of the message.
102 | * @param arg0 the first argument.
103 | */
104 | void error(Function super T, String> messageProvider, T arg0);
105 | /**
106 | * Log a message provided by the function at {@link Level#ERROR} level.
107 | * @param messageProvider the provider of the message.
108 | * @param arg0 the first argument.
109 | */
110 | void error(IntFunction messageProvider, int arg0);
111 | /**
112 | * Log a message provided by the function at {@link Level#ERROR} level.
113 | * @param messageProvider the provider of the message.
114 | * @param arg0 the first argument.
115 | */
116 | void error(LongFunction messageProvider, long arg0);
117 | /**
118 | * Log a message provided by the function at {@link Level#ERROR} level.
119 | * @param messageProvider the provider of the message.
120 | * @param arg0 the first argument.
121 | */
122 | void error(DoubleFunction messageProvider, double arg0);
123 | /**
124 | * Log a message provided by the function with two arguments at {@link Level#ERROR} level.
125 | * @param the type of the first argument.
126 | * @param the type of the second argument.
127 | * @param messageProvider the provider of the message.
128 | * @param arg0 the first argument.
129 | * @param arg1 the second argument.
130 | */
131 | void error(BiFunction super T, ? super U, String> messageProvider, T arg0, U arg1);
132 |
133 | /**
134 | * Log a message at {@link Level#WARNING} level with an exception.
135 | * @param message the log message.
136 | * @param context an exception or null.
137 | */
138 | void warning(String message, Throwable context);
139 | /**
140 | * Log a message provided by the supplier at {@link Level#WARNING} level.
141 | * @param messageProvider the provider of the message.
142 | */
143 | void warning(Supplier messageProvider);
144 | /**
145 | * Log a message provided by the function at {@link Level#WARNING} level.
146 | * @param the type of the first argument.
147 | * @param messageProvider the provider of the message.
148 | * @param arg0 the first argument.
149 | */
150 | void warning(Function super T, String> messageProvider, T arg0);
151 | /**
152 | * Log a message provided by the function at {@link Level#WARNING} level.
153 | * @param messageProvider the provider of the message.
154 | * @param arg0 the first argument.
155 | */
156 | void warning(IntFunction messageProvider, int arg0);
157 | /**
158 | * Log a message provided by the function at {@link Level#WARNING} level.
159 | * @param messageProvider the provider of the message.
160 | * @param arg0 the first argument.
161 | */
162 | void warning(LongFunction messageProvider, long arg0);
163 | /**
164 | * Log a message provided by the function at {@link Level#WARNING} level.
165 | * @param messageProvider the provider of the message.
166 | * @param arg0 the first argument.
167 | */
168 | void warning(DoubleFunction messageProvider, double arg0);
169 | /**
170 | * Log a message provided by the function with two arguments at {@link Level#WARNING} level.
171 | * @param the type of the first argument.
172 | * @param the type of the second argument.
173 | * @param messageProvider the provider of the message.
174 | * @param arg0 the first argument.
175 | * @param arg1 the second argument.
176 | */
177 | void warning(BiFunction super T, ? super U, String> messageProvider, T arg0, U arg1);
178 |
179 | /**
180 | * Log a message at {@link Level#INFO} level with an exception.
181 | * @param message the log message.
182 | * @param context an exception or null.
183 | */
184 | void info(String message, Throwable context);
185 | /**
186 | * Log a message provided by the supplier at {@link Level#INFO} level.
187 | * @param messageProvider the provider of the message.
188 | */
189 | void info(Supplier messageProvider);
190 | /**
191 | * Log a message provided by the function at {@link Level#INFO} level.
192 | * @param the type of the first argument.
193 | * @param messageProvider the provider of the message.
194 | * @param arg0 the first argument.
195 | */
196 | void info(Function super T, String> messageProvider, T arg0);
197 | /**
198 | * Log a message provided by the function at {@link Level#INFO} level.
199 | * @param messageProvider the provider of the message.
200 | * @param arg0 the first argument.
201 | */
202 | void info(IntFunction messageProvider, int arg0);
203 | /**
204 | * Log a message provided by the function at {@link Level#INFO} level.
205 | * @param messageProvider the provider of the message.
206 | * @param arg0 the first argument.
207 | */
208 | void info(LongFunction messageProvider, long arg0);
209 | /**
210 | * Log a message provided by the function at {@link Level#INFO} level.
211 | * @param messageProvider the provider of the message.
212 | * @param arg0 the first argument.
213 | */
214 | void info(DoubleFunction messageProvider, double arg0);
215 | /**
216 | * Log a message provided by the function with two arguments at {@link Level#INFO} level.
217 | * @param the type of the first argument.
218 | * @param the type of the second argument.
219 | * @param messageProvider the provider of the message.
220 | * @param arg0 the first argument.
221 | * @param arg1 the second argument.
222 | */
223 | void info(BiFunction super T, ? super U, String> messageProvider, T arg0, U arg1);
224 |
225 | /**
226 | * Log a message at {@link Level#DEBUG} level with an exception.
227 | * @param message the log message.
228 | * @param context an exception or null.
229 | */
230 | void debug(String message, Throwable context);
231 | /**
232 | * Log a message provided by the supplier at {@link Level#DEBUG} level.
233 | * @param messageProvider the provider of the message.
234 | */
235 | void debug(Supplier messageProvider);
236 | /**
237 | * Log a message provided by the function at {@link Level#DEBUG} level.
238 | * @param the type of the first argument.
239 | * @param messageProvider the provider of the message.
240 | * @param arg0 the first argument.
241 | */
242 | void debug(Function super T, String> messageProvider, T arg0);
243 | /**
244 | * Log a message provided by the function at {@link Level#DEBUG} level.
245 | * @param messageProvider the provider of the message.
246 | * @param arg0 the first argument.
247 | */
248 | void debug(IntFunction messageProvider, int arg0);
249 | /**
250 | * Log a message provided by the function at {@link Level#DEBUG} level.
251 | * @param messageProvider the provider of the message.
252 | * @param arg0 the first argument.
253 | */
254 | void debug(LongFunction messageProvider, long arg0);
255 | /**
256 | * Log a message provided by the function at {@link Level#DEBUG} level.
257 | * @param messageProvider the provider of the message.
258 | * @param arg0 the first argument.
259 | */
260 | void debug(DoubleFunction messageProvider, double arg0);
261 | /**
262 | * Log a message provided by the function with two arguments at {@link Level#DEBUG} level.
263 | * @param the type of the first argument.
264 | * @param the type of the second argument.
265 | * @param messageProvider the provider of the message.
266 | * @param arg0 the first argument.
267 | * @param arg1 the second argument.
268 | */
269 | void debug(BiFunction super T, ? super U, String> messageProvider, T arg0, U arg1);
270 |
271 | /**
272 | * Log a message at {@link Level#TRACE} level with an exception.
273 | * @param message the log message.
274 | * @param context an exception or null.
275 | */
276 | void trace(String message, Throwable context);
277 | /**
278 | * Log a message provided by the supplier at {@link Level#TRACE} level.
279 | * @param messageProvider the provider of the message.
280 | */
281 | void trace(Supplier messageProvider);
282 | /**
283 | * Log a message provided by the function at {@link Level#TRACE} level.
284 | * @param the type of the first argument.
285 | * @param messageProvider the provider of the message.
286 | * @param arg0 the first argument.
287 | */
288 | void trace(Function super T, String> messageProvider, T arg0);
289 | /**
290 | * Log a message provided by the function at {@link Level#TRACE} level.
291 | * @param messageProvider the provider of the message.
292 | * @param arg0 the first argument.
293 | */
294 | void trace(IntFunction messageProvider, int arg0);
295 | /**
296 | * Log a message provided by the function at {@link Level#TRACE} level.
297 | * @param messageProvider the provider of the message.
298 | * @param arg0 the first argument.
299 | */
300 | void trace(LongFunction messageProvider, long arg0);
301 | /**
302 | * Log a message provided by the function at {@link Level#TRACE} level.
303 | * @param messageProvider the provider of the message.
304 | * @param arg0 the first argument.
305 | */
306 | void trace(DoubleFunction messageProvider, double arg0);
307 | /**
308 | * Log a message provided by the function with two arguments at {@link Level#TRACE} level.
309 | * @param the type of the first argument.
310 | * @param the type of the second argument.
311 | * @param messageProvider the provider of the message.
312 | * @param arg0 the first argument.
313 | * @param arg1 the second argument.
314 | */
315 | void trace(BiFunction super T, ? super U, String> messageProvider, T arg0, U arg1);
316 |
317 | /**
318 | * Create a logger with the configuration of class that calls this method.
319 | *
320 | * @return a logger.
321 | *
322 | * @see LoggerConfig#fromClass(Class)
323 | */
324 | public static Logger getLogger() {
325 | Class> callerClass;
326 | if (LoggerImpl.GET_CALLER_CLASS_MH != null) {
327 | try {
328 | callerClass = (Class>) LoggerImpl.GET_CALLER_CLASS_MH.invokeExact();
329 | } catch (Throwable e) {
330 | throw new AssertionError(e);
331 | }
332 | } else {
333 | callerClass = LoggerImpl.getCallerClassNoStackWalker();
334 | }
335 | return getLogger(callerClass, LoggerImpl.EMPTY_CONSUMER);
336 | }
337 |
338 | /**
339 | * Create a logger with the configuration of the configClass.
340 | *
341 | * @param configClass the class that hold the configuration.
342 | * @return a logger.
343 | * @throws NullPointerException if the configuration class is null.
344 | *
345 | * @see LoggerConfig#fromClass(Class)
346 | */
347 | public static Logger getLogger(Class> configClass) {
348 | return getLogger(configClass, LoggerImpl.EMPTY_CONSUMER);
349 | }
350 |
351 | /**
352 | * Create a logger with the configuration of the configClass and an initializer to change
353 | * the configuration.
354 | *
355 | * @param configClass the class that hold the configuration.
356 | * @param configUpdater a consumer that can update a configuration.
357 | * @return a logger.
358 | * @throws NullPointerException if the configuration class or the configuration updater is null.
359 | *
360 | * @see LoggerConfig#fromClass(Class)
361 | */
362 | public static Logger getLogger(Class> configClass, Consumer super ConfigOption> configUpdater) {
363 | Objects.requireNonNull(configClass);
364 | Objects.requireNonNull(configUpdater);
365 | if (configUpdater != LoggerImpl.EMPTY_CONSUMER) {
366 | LoggerConfig.fromClass(configClass).update(configUpdater);
367 | }
368 | MethodHandle mh = LoggerImpl.getLoggingMethodHandle(configClass, 4);
369 | return LoggerImpl.createLogger(mh);
370 | }
371 | }
372 |
--------------------------------------------------------------------------------
/src/main/java/com.github.forax.beautifullogger/LoggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.github.forax.beautifullogger;
2 |
3 | import static com.github.forax.beautifullogger.LoggerImpl.LoggerConfigKind.CLASS;
4 | import static com.github.forax.beautifullogger.LoggerImpl.LoggerConfigKind.MODULE;
5 | import static com.github.forax.beautifullogger.LoggerImpl.LoggerConfigKind.PACKAGE;
6 |
7 | import java.lang.invoke.MethodHandle;
8 | import java.net.URL;
9 | import java.util.Arrays;
10 | import java.util.Objects;
11 | import java.util.Optional;
12 | import java.util.function.Consumer;
13 |
14 | import com.github.forax.beautifullogger.Logger.Level;
15 |
16 | /**
17 | * The configuration of a {@link Logger}.
18 | *
19 | * The configuration can be set on a {@link LoggerConfig#fromModule(String) module},
20 | * a {@link LoggerConfig#fromPackage(Package) package} or
21 | * a {@link LoggerConfig#fromClass(Class) class}.
22 | * When a logger read a configuration property, it first tries to read the configuration property
23 | * of its configuration class, if the property is not defined, it tries to read the configuration property of the package
24 | * and if it is not defined, it tries to read the configuration property of the module, if it is not defined,
25 | * it uses the default values below.
26 | *
27 | *
28 | *
29 | *
enable
true
30 | *
level
{@link Level#INFO}
31 | *
levelOverride
false
32 | *
logEventFactory
{@link LogFacadeFactory#defaultFactory()}
33 | *
default value of the configuration properties
34 | *
35 | *
36 | *
37 | * An example of reading the configuration
38 | *
47 | *
48 | * Because changing a configuration property may cause the Java Virtual Machine to de-optimize assembly codes,
49 | * the change to the properties of a LoggerConfig has to be done in bulk using the method {@link LoggerConfig#update(Consumer)}.
50 | *
51 | * For example to change the level of a configuration
52 | *