diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
deleted file mode 100644
index 6e53241..0000000
--- a/.github/CODEOWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax
-* @sschnabe @rpahli @fabian-schlegel @wistefan
-.github/workflows/* @kokuwaio-bot @sschnabe @rpahli @fabian-schlegel @wistefan
-pom.xml @kokuwaio-bot @sschnabe @rpahli @fabian-schlegel @wistefan
diff --git a/.github/README.md b/.github/README.md
new file mode 100644
index 0000000..8875cce
--- /dev/null
+++ b/.github/README.md
@@ -0,0 +1,11 @@
+# Micronaut Logging support
+
+Enhanced logging for Micronaut using MDC or request header.
+
+[](https://central.sonatype.com/artifact/io.kokuwa.micronaut/micronaut-logging)
+[](https://git.kokuwa.io/kokuwaio/micronaut-logging/src/branch/main/LICENSE)
+[](https://git.kokuwa.io/kokuwaio/micronaut-logging/issues)
+[](https://git.kokuwa.io/kokuwaio/micronaut-logging/pulls)
+[](https://ci.kokuwa.io/repos/kokuwaio/micronaut-logging/)
+
+For more documention see: [git.kokuwa.io/kokuwaio/micronaut-logging](https://git.kokuwa.io/kokuwaio/micronaut-logging)
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index e754c9d..0000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-version: 2
-updates:
- - package-ecosystem: maven
- directory: /
- schedule:
- interval: monthly
- day: monday
- # github parses time without quotes to int
- # yamllint disable-line rule:quoted-strings
- time: "09:00"
- timezone: Europe/Berlin
- ignore:
- # logback 1.3 and 1.4 are compatible with slf4j 2.x only
- - dependency-name: ch.qos.logback:logback-classic
- update-types: [version-update:semver-major, version-update:semver-minor]
- - package-ecosystem: github-actions
- directory: /
- schedule:
- interval: monthly
- day: monday
- # github parses time without quotes to int
- # yamllint disable-line rule:quoted-strings
- time: "09:00"
- timezone: Europe/Berlin
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
deleted file mode 100644
index 8383223..0000000
--- a/.github/workflows/ci.yaml
+++ /dev/null
@@ -1,71 +0,0 @@
-name: CI
-
-on:
- push:
- branches: [main]
- pull_request: {}
- schedule: [cron: 0 0 * * 1-5]
-
-jobs:
-
- yaml:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: ibiqlik/action-yamllint@v3
- with:
- format: colored
- strict: true
-
- markdown:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: avto-dev/markdown-lint@v1
- with:
- args: /github/workspace
-
- javadoc:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-java@v3
- with:
- distribution: temurin
- java-version: 11
- cache: maven
- - run: mvn -B -ntp dependency:go-offline
- - run: mvn -B -ntp javadoc:javadoc-no-fork -Dmaven.javadoc.failOnWarnings=true -Ddoclint=all
-
- checkstyle:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-java@v3
- with:
- distribution: temurin
- java-version: 11
- cache: maven
- - run: mvn -B -ntp dependency:go-offline
- - run: mvn -B -ntp checkstyle:check
-
- build:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-java@v3
- with:
- distribution: temurin
- java-version: 11
- cache: maven
- server-id: sonatype-nexus
- server-username: SERVER_USERNAME
- server-password: SERVER_PASSWORD
- - run: mvn -B -ntp dependency:go-offline
- - run: mvn -B -ntp verify -Dcheckstyle.skip
- if: ${{ github.ref != 'refs/heads/main' }}
- - run: mvn -B -ntp deploy -Dcheckstyle.skip
- if: ${{ github.ref == 'refs/heads/main' }}
- env:
- SERVER_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }}
- SERVER_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }}
diff --git a/.github/workflows/dependabot.yaml b/.github/workflows/dependabot.yaml
deleted file mode 100644
index ed63eca..0000000
--- a/.github/workflows/dependabot.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-name: Dependabot
-
-on: pull_request_target
-
-jobs:
- auto-merge:
- runs-on: ubuntu-latest
- if: ${{ github.actor == 'dependabot[bot]' }}
- steps:
- - run: gh pr review --approve "$PR_URL"
- env:
- PR_URL: ${{ github.event.pull_request.html_url }}
- GITHUB_TOKEN: ${{ secrets.GIT_ACTION_TOKEN }}
- - run: gh pr merge --auto --squash "$PR_URL"
- env:
- PR_URL: ${{ github.event.pull_request.html_url }}
- GITHUB_TOKEN: ${{ secrets.GIT_ACTION_TOKEN }}
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
deleted file mode 100644
index 4f561a0..0000000
--- a/.github/workflows/release.yaml
+++ /dev/null
@@ -1,34 +0,0 @@
-name: Release
-
-on: workflow_dispatch
-
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- with:
- token: ${{ secrets.GIT_ACTION_TOKEN }}
- - uses: crazy-max/ghaction-import-gpg@v5
- with:
- gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
- passphrase: ${{ secrets.GPG_PASSPHRASE }}
- git_user_signingkey: true
- git_commit_gpgsign: true
- - uses: actions/setup-java@v3
- with:
- distribution: temurin
- java-version: 11
- cache: maven
- server-id: sonatype-nexus
- server-username: SERVER_USERNAME
- server-password: SERVER_PASSWORD
- gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
- gpg-passphrase: GPG_PASSPHRASE
- - run: mvn -B -ntp dependency:go-offline
- - run: mvn -B -ntp release:prepare
- - run: mvn -B -ntp release:perform
- env:
- SERVER_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }}
- SERVER_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }}
- GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
diff --git a/.justfile b/.justfile
new file mode 100644
index 0000000..81f407b
--- /dev/null
+++ b/.justfile
@@ -0,0 +1,12 @@
+# https://just.systems/man/en/
+
+[private]
+@default:
+ just --list --unsorted
+
+# Run linter.
+@lint:
+ docker run --rm --read-only --volume=$(pwd):$(pwd):ro --workdir=$(pwd) kokuwaio/yamllint
+ docker run --rm --read-only --volume=$(pwd):$(pwd):rw --workdir=$(pwd) kokuwaio/markdownlint --fix
+ docker run --rm --read-only --volume=$(pwd):$(pwd):ro --workdir=$(pwd) kokuwaio/renovate-config-validator
+ docker run --rm --read-only --volume=$(pwd):$(pwd):ro --workdir=$(pwd) woodpeckerci/woodpecker-cli lint
diff --git a/.woodpecker/deploy.yaml b/.woodpecker/deploy.yaml
new file mode 100644
index 0000000..11f903e
--- /dev/null
+++ b/.woodpecker/deploy.yaml
@@ -0,0 +1,16 @@
+when:
+ instance: ci.kokuwa.io
+ repo: kokuwaio/micronaut-logging
+ event: [manual, push]
+ branch: main
+ path: [.woodpecker/deploy.yaml, pom.xml, src/main/**]
+
+steps:
+
+ maven:
+ image: maven:3.9.10-eclipse-temurin-17
+ commands: mvn deploy --settings=.woodpecker/maven/settings.xml
+ environment:
+ MAVEN_GPG_KEY: {from_secret: woodpecker_gpg_key}
+ SONATYPE_ORG_USERNAME: {from_secret: sonatype_org_username}
+ SONATYPE_ORG_PASSWORD: {from_secret: sonatype_org_password}
diff --git a/.woodpecker/lint.yaml b/.woodpecker/lint.yaml
new file mode 100644
index 0000000..74bb114
--- /dev/null
+++ b/.woodpecker/lint.yaml
@@ -0,0 +1,21 @@
+when:
+ event: [manual, pull_request, push]
+ branch: main
+ path: [.woodpecker/lint.yaml, renovate.json, "**/*.y*ml", "**/*.md"]
+
+steps:
+
+ renovate:
+ image: kokuwaio/renovate-config-validator
+ depends_on: []
+ when: [path: [.woodpecker/lint.yaml, renovate.json]]
+
+ yaml:
+ image: kokuwaio/yamllint
+ depends_on: []
+ when: [path: [.woodpecker/lint.yaml, .yamllint.yaml, "**/*.y*ml"]]
+
+ markdown:
+ image: kokuwaio/markdownlint
+ depends_on: []
+ when: [path: [.woodpecker/lint.yaml, .markdownlint.yaml, "**/*.md"]]
diff --git a/.woodpecker/maven/settings.xml b/.woodpecker/maven/settings.xml
new file mode 100644
index 0000000..57ad1cb
--- /dev/null
+++ b/.woodpecker/maven/settings.xml
@@ -0,0 +1,23 @@
+
+
+ false
+ /woodpecker/.m2
+
+
+ git.kokuwa.io
+ ${env.FORGEJO_USERNAME}
+ ${env.FORGEJO_PASSWORD}
+
+
+ sonatype.org
+ ${env.SONATYPE_ORG_USERNAME}
+ ${env.SONATYPE_ORG_PASSWORD}
+
+
+
+
+ http://mirror.woodpecker.svc.cluster.local/maven2
+ central
+
+
+
diff --git a/.woodpecker/release.yaml b/.woodpecker/release.yaml
new file mode 100644
index 0000000..21a190e
--- /dev/null
+++ b/.woodpecker/release.yaml
@@ -0,0 +1,29 @@
+when:
+ instance: ci.kokuwa.io
+ repo: kokuwaio/micronaut-logging
+ event: deployment
+ branch: main
+
+steps:
+
+ maven:
+ image: maven:3.9.10-eclipse-temurin-17
+ commands:
+ # setup git with ssk key signing
+ - git config user.email "$GIT_USER_EMAIL"
+ - git config user.name "$GIT_USER_NAME"
+ - git config commit.gpgsign true
+ - git config gpg.format ssh
+ - git config user.signingkey /run/secrets/sign.pub
+ - install -m 400 /dev/null /run/secrets/sign && echo "$GIT_SIGN_KEY" > /run/secrets/sign
+ - install -m 444 /dev/null /run/secrets/sign.pub && echo "$GIT_SIGN_PUB" > /run/secrets/sign.pub
+ # release
+ - mvn release:prepare release:perform --settings=.woodpecker/maven/settings.xml
+ environment:
+ MAVEN_GPG_KEY: {from_secret: woodpecker_gpg_key}
+ GIT_SIGN_KEY: {from_secret: woodpecker_sign_key}
+ GIT_SIGN_PUB: {from_secret: woodpecker_sign_pub}
+ FORGEJO_USERNAME: {from_secret: woodpecker_username}
+ FORGEJO_PASSWORD: {from_secret: woodpecker_password}
+ SONATYPE_ORG_USERNAME: {from_secret: sonatype_org_username}
+ SONATYPE_ORG_PASSWORD: {from_secret: sonatype_org_password}
diff --git a/.woodpecker/verify.yaml b/.woodpecker/verify.yaml
new file mode 100644
index 0000000..094b317
--- /dev/null
+++ b/.woodpecker/verify.yaml
@@ -0,0 +1,9 @@
+when:
+ event: [manual, pull_request]
+ path: [.woodpecker/verify.yaml, pom.xml, src/**]
+
+steps:
+
+ test:
+ image: maven:3.9.10-eclipse-temurin-17
+ commands: mvn verify --settings=.woodpecker/maven/settings.xml -P-deploy
diff --git a/.yamllint b/.yamllint.yaml
similarity index 83%
rename from .yamllint
rename to .yamllint.yaml
index 8011808..21966f2 100644
--- a/.yamllint
+++ b/.yamllint.yaml
@@ -13,7 +13,3 @@ rules:
quoted-strings:
quote-type: double
required: only-when-needed
-
- # allow everything on keys
- truthy:
- check-keys: false
diff --git a/LICENSE b/LICENSE
index 261eeb9..dacd3ae 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,201 +1,288 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+ EUROPEAN UNION PUBLIC LICENCE v. 1.2
+ EUPL © the European Union 2007, 2016
- 1. Definitions.
+This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined
+below) which is provided under the terms of this Licence. Any use of the Work,
+other than as authorised under this Licence is prohibited (to the extent such
+use is covered by a right of the copyright holder of the Work).
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
+The Work is provided under the terms of this Licence when the Licensor (as
+defined below) has placed the following notice immediately following the
+copyright notice for the Work:
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
+ Licensed under the EUPL
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
+or has expressed by any other means his willingness to license under the EUPL.
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
+1. Definitions
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
+In this Licence, the following terms have the following meaning:
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
+- ‘The Licence’: this Licence.
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
+- ‘The Original Work’: the work or software distributed or communicated by the
+ Licensor under this Licence, available as Source Code and also as Executable
+ Code as the case may be.
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
+- ‘Derivative Works’: the works or software that could be created by the
+ Licensee, based upon the Original Work or modifications thereof. This Licence
+ does not define the extent of modification or dependence on the Original Work
+ required in order to classify a work as a Derivative Work; this extent is
+ determined by copyright law applicable in the country mentioned in Article 15.
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
+- ‘The Work’: the Original Work or its Derivative Works.
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
+- ‘The Source Code’: the human-readable form of the Work which is the most
+ convenient for people to study and modify.
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
+- ‘The Executable Code’: any code which has generally been compiled and which is
+ meant to be interpreted by a computer as a program.
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
+- ‘The Licensor’: the natural or legal person that distributes or communicates
+ the Work under the Licence.
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
+- ‘Contributor(s)’: any natural or legal person who modifies the Work under the
+ Licence, or otherwise contributes to the creation of a Derivative Work.
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
+- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of
+ the Work under the terms of the Licence.
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
+- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending,
+ renting, distributing, communicating, transmitting, or otherwise making
+ available, online or offline, copies of the Work or providing access to its
+ essential functionalities at the disposal of any other natural or legal
+ person.
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
+2. Scope of the rights granted by the Licence
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
+The Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
+sublicensable licence to do the following, for the duration of copyright vested
+in the Original Work:
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
+- use the Work in any circumstance and for all usage,
+- reproduce the Work,
+- modify the Work, and make Derivative Works based upon the Work,
+- communicate to the public, including the right to make available or display
+ the Work or copies thereof to the public and perform publicly, as the case may
+ be, the Work,
+- distribute the Work or copies thereof,
+- lend and rent the Work or copies thereof,
+- sublicense rights in the Work or copies thereof.
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
+Those rights can be exercised on any media, supports and formats, whether now
+known or later invented, as far as the applicable law permits so.
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
+In the countries where moral rights apply, the Licensor waives his right to
+exercise his moral right to the extent allowed by law in order to make effective
+the licence of the economic rights here above listed.
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
+The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to
+any patents held by the Licensor, to the extent necessary to make use of the
+rights granted on the Work under this Licence.
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
+3. Communication of the Source Code
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
+The Licensor may provide the Work either in its Source Code form, or as
+Executable Code. If the Work is provided as Executable Code, the Licensor
+provides in addition a machine-readable copy of the Source Code of the Work
+along with each copy of the Work that the Licensor distributes or indicates, in
+a notice following the copyright notice attached to the Work, a repository where
+the Source Code is easily and freely accessible for as long as the Licensor
+continues to distribute or communicate the Work.
- END OF TERMS AND CONDITIONS
+4. Limitations on copyright
- APPENDIX: How to apply the Apache License to your work.
+Nothing in this Licence is intended to deprive the Licensee of the benefits from
+any exception or limitation to the exclusive rights of the rights owners in the
+Work, of the exhaustion of those rights or of other applicable limitations
+thereto.
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
+5. Obligations of the Licensee
- Copyright [yyyy] [name of copyright owner]
+The grant of the rights mentioned above is subject to some restrictions and
+obligations imposed on the Licensee. Those obligations are the following:
- Licensed 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
+Attribution right: The Licensee shall keep intact all copyright, patent or
+trademarks notices and all notices that refer to the Licence and to the
+disclaimer of warranties. The Licensee must include a copy of such notices and a
+copy of the Licence with every copy of the Work he/she distributes or
+communicates. The Licensee must cause any Derivative Work to carry prominent
+notices stating that the Work has been modified and the date of modification.
- http://www.apache.org/licenses/LICENSE-2.0
+Copyleft clause: If the Licensee distributes or communicates copies of the
+Original Works or Derivative Works, this Distribution or Communication will be
+done under the terms of this Licence or of a later version of this Licence
+unless the Original Work is expressly distributed only under this version of the
+Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee
+(becoming Licensor) cannot offer or impose any additional terms or conditions on
+the Work or Derivative Work that alter or restrict the terms of the Licence.
- 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.
+Compatibility clause: If the Licensee Distributes or Communicates Derivative
+Works or copies thereof based upon both the Work and another work licensed under
+a Compatible Licence, this Distribution or Communication can be done under the
+terms of this Compatible Licence. For the sake of this clause, ‘Compatible
+Licence’ refers to the licences listed in the appendix attached to this Licence.
+Should the Licensee's obligations under the Compatible Licence conflict with
+his/her obligations under this Licence, the obligations of the Compatible
+Licence shall prevail.
+
+Provision of Source Code: When distributing or communicating copies of the Work,
+the Licensee will provide a machine-readable copy of the Source Code or indicate
+a repository where this Source will be easily and freely available for as long
+as the Licensee continues to distribute or communicate the Work.
+
+Legal Protection: This Licence does not grant permission to use the trade names,
+trademarks, service marks, or names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the copyright notice.
+
+6. Chain of Authorship
+
+The original Licensor warrants that the copyright in the Original Work granted
+hereunder is owned by him/her or licensed to him/her and that he/she has the
+power and authority to grant the Licence.
+
+Each Contributor warrants that the copyright in the modifications he/she brings
+to the Work are owned by him/her or licensed to him/her and that he/she has the
+power and authority to grant the Licence.
+
+Each time You accept the Licence, the original Licensor and subsequent
+Contributors grant You a licence to their contributions to the Work, under the
+terms of this Licence.
+
+7. Disclaimer of Warranty
+
+The Work is a work in progress, which is continuously improved by numerous
+Contributors. It is not a finished work and may therefore contain defects or
+‘bugs’ inherent to this type of development.
+
+For the above reason, the Work is provided under the Licence on an ‘as is’ basis
+and without warranties of any kind concerning the Work, including without
+limitation merchantability, fitness for a particular purpose, absence of defects
+or errors, accuracy, non-infringement of intellectual property rights other than
+copyright as stated in Article 6 of this Licence.
+
+This disclaimer of warranty is an essential part of the Licence and a condition
+for the grant of any rights to the Work.
+
+8. Disclaimer of Liability
+
+Except in the cases of wilful misconduct or damages directly caused to natural
+persons, the Licensor will in no event be liable for any direct or indirect,
+material or moral, damages of any kind, arising out of the Licence or of the use
+of the Work, including without limitation, damages for loss of goodwill, work
+stoppage, computer failure or malfunction, loss of data or any commercial
+damage, even if the Licensor has been advised of the possibility of such damage.
+However, the Licensor will be liable under statutory product liability laws as
+far such laws apply to the Work.
+
+9. Additional agreements
+
+While distributing the Work, You may choose to conclude an additional agreement,
+defining obligations or services consistent with this Licence. However, if
+accepting obligations, You may act only on your own behalf and on your sole
+responsibility, not on behalf of the original Licensor or any other Contributor,
+and only if You agree to indemnify, defend, and hold each Contributor harmless
+for any liability incurred by, or claims asserted against such Contributor by
+the fact You have accepted any warranty or additional liability.
+
+10. Acceptance of the Licence
+
+The provisions of this Licence can be accepted by clicking on an icon ‘I agree’
+placed under the bottom of a window displaying the text of this Licence or by
+affirming consent in any other similar way, in accordance with the rules of
+applicable law. Clicking on that icon indicates your clear and irrevocable
+acceptance of this Licence and all of its terms and conditions.
+
+Similarly, you irrevocably accept this Licence and all of its terms and
+conditions by exercising any rights granted to You by Article 2 of this Licence,
+such as the use of the Work, the creation by You of a Derivative Work or the
+Distribution or Communication by You of the Work or copies thereof.
+
+11. Information to the public
+
+In case of any Distribution or Communication of the Work by means of electronic
+communication by You (for example, by offering to download the Work from a
+remote location) the distribution channel or media (for example, a website) must
+at least provide to the public the information requested by the applicable law
+regarding the Licensor, the Licence and the way it may be accessible, concluded,
+stored and reproduced by the Licensee.
+
+12. Termination of the Licence
+
+The Licence and the rights granted hereunder will terminate automatically upon
+any breach by the Licensee of the terms of the Licence.
+
+Such a termination will not terminate the licences of any person who has
+received the Work from the Licensee under the Licence, provided such persons
+remain in full compliance with the Licence.
+
+13. Miscellaneous
+
+Without prejudice of Article 9 above, the Licence represents the complete
+agreement between the Parties as to the Work.
+
+If any provision of the Licence is invalid or unenforceable under applicable
+law, this will not affect the validity or enforceability of the Licence as a
+whole. Such provision will be construed or reformed so as necessary to make it
+valid and enforceable.
+
+The European Commission may publish other linguistic versions or new versions of
+this Licence or updated versions of the Appendix, so far this is required and
+reasonable, without reducing the scope of the rights granted by the Licence. New
+versions of the Licence will be published with a unique version number.
+
+All linguistic versions of this Licence, approved by the European Commission,
+have identical value. Parties can take advantage of the linguistic version of
+their choice.
+
+14. Jurisdiction
+
+Without prejudice to specific agreement between parties,
+
+- any litigation resulting from the interpretation of this License, arising
+ between the European Union institutions, bodies, offices or agencies, as a
+ Licensor, and any Licensee, will be subject to the jurisdiction of the Court
+ of Justice of the European Union, as laid down in article 272 of the Treaty on
+ the Functioning of the European Union,
+
+- any litigation arising between other parties and resulting from the
+ interpretation of this License, will be subject to the exclusive jurisdiction
+ of the competent court where the Licensor resides or conducts its primary
+ business.
+
+15. Applicable Law
+
+Without prejudice to specific agreement between parties,
+
+- this Licence shall be governed by the law of the European Union Member State
+ where the Licensor has his seat, resides or has his registered office,
+
+- this licence shall be governed by Belgian law if the Licensor has no seat,
+ residence or registered office inside a European Union Member State.
+
+Appendix
+
+‘Compatible Licences’ according to Article 5 EUPL are:
+
+- GNU General Public License (GPL) v. 2, v. 3
+- GNU Affero General Public License (AGPL) v. 3
+- Open Software License (OSL) v. 2.1, v. 3.0
+- Eclipse Public License (EPL) v. 1.0
+- CeCILL v. 2.0, v. 2.1
+- Mozilla Public Licence (MPL) v. 2
+- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3
+- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for
+ works other than software
+- European Union Public Licence (EUPL) v. 1.1, v. 1.2
+- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong
+ Reciprocity (LiLiQ-R+).
+
+The European Commission may update this Appendix to later versions of the above
+licences without producing a new version of the EUPL, as long as they provide
+the rights granted in Article 2 of this Licence and protect the covered Source
+Code from exclusive appropriation.
+
+All other changes or additions to this Appendix require the production of a new
+EUPL version.
diff --git a/README.md b/README.md
index 9260ec1..4a3a2ec 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,12 @@
# Micronaut Logging support
-[](http://www.apache.org/licenses/)
-[](https://search.maven.org/search?q=g:%22io.kokuwa.micronaut%22%20AND%20a:%22micronaut-logging%22)
-[](https://github.com/kokuwaio/micronaut-logging/actions/workflows/ci.yaml?query=branch%3Amain)
-[](https://github.com/kokuwaio/micronaut-logging/actions/workflows/ci.yaml?query=branch%3A4.x)
+Enhanced logging for Micronaut using MDC or request header.
+
+[](https://central.sonatype.com/artifact/io.kokuwa.micronaut/micronaut-logging)
+[](https://git.kokuwa.io/kokuwaio/micronaut-logging/src/branch/main/LICENSE)
+[](https://git.kokuwa.io/kokuwaio/micronaut-logging/issues)
+[](https://git.kokuwa.io/kokuwaio/micronaut-logging/pulls)
+[](https://ci.kokuwa.io/repos/kokuwaio/micronaut-logging/)
Include in your `pom.xml`:
@@ -14,12 +17,18 @@ Include in your `pom.xml`:
${version.io.kokuwa.micronaut.logging}
runtime
+
+
+ io.micronaut.serde
+ micronaut-serde-jsonp
+ runtime
+
```
## Features
-* Version [3.x](https://github.com/kokuwaio/micronaut-logging/tree/main) is based on SLF4J 1.7 & Logback 1.2
-* Version [4.x](https://github.com/kokuwaio/micronaut-logging/tree/4.x) is based on SLF4J 2.0 & Logback 1.4 (WIP)
+* Version [3.x](https://github.com/kokuwaio/micronaut-logging/tree/3.x) is based on SLF4J 1.7 & Logback 1.2 & Micronaut 3.x
+* Version [4.x](https://github.com/kokuwaio/micronaut-logging/tree/main) is based on SLF4J 2.0 & Logback 1.4 & Micronaut 4.x
* [set log level based on MDC values](docs/features/logback_mdc_level.md)
* [add default xml](docs/features/logback_default.md)
* [preconfigured appender for different environments](docs/features/logback_appender.md)
@@ -28,13 +37,8 @@ Include in your `pom.xml`:
* [add HTTP header to MDC](docs/features/http_mdc_header.md)
* [add authentication information from HTTP request to MDC](docs/features/http_mdc_authentication.md)
-## Development
-
-* [build](docs/build.md)
-
## Open Topics
* configure mdc on refresh event
* read **serviceName** and **serviceVersion** from yaml
* support auto select appender with custom `logback.xml`
-* add maven site with jacoco / dependency updates for snapshot build
diff --git a/docs/build.md b/docs/build.md
deleted file mode 100644
index 0d2c727..0000000
--- a/docs/build.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Build & Release
-
-## Dependency updates
-
-Display dependency updates:
-
-```sh
-mvn versions:display-parent-updates versions:display-property-updates -U
-```
-
-Update dependencies:
-
-```sh
-mvn versions:update-parent versions:update-properties
-```
-
-## Release locally
-
-Run:
-
-```sh
-mvn release:prepare release:perform release:clean -B
-```
diff --git a/docs/features/logback_appender.md b/docs/features/logback_appender.md
index 1975e8b..d71885b 100644
--- a/docs/features/logback_appender.md
+++ b/docs/features/logback_appender.md
@@ -12,5 +12,3 @@
2. if GCP is detected gcp appender will be used
3. if Kubernetes is detected json appender will be used
4. console appender else
-
-*IMPORTENT*: only works without custom `logback.xml`
diff --git a/docs/features/logback_default.md b/docs/features/logback_default.md
index 98ccbc5..5b34f1a 100644
--- a/docs/features/logback_default.md
+++ b/docs/features/logback_default.md
@@ -4,15 +4,13 @@ If no `logback.xml` by user is provided a default [logback.xml](../../src/main/r
```xml
-
+
-
+
-
-
-
-
-
+
+
+
```
diff --git a/docs/features/logback_mdc_level.md b/docs/features/logback_mdc_level.md
index 53887d5..ee1e853 100644
--- a/docs/features/logback_mdc_level.md
+++ b/docs/features/logback_mdc_level.md
@@ -7,7 +7,7 @@ This can be used to change the log level based on MDC valus. E.g. change log lev
Property | Description | Default
-------- | ----------- | -------
`logger.mdc.enabled` | MDC enabled? | `true`
-`logger.mdc.` | MDC key to use |
+`logger.mdc.` | MDC key to use | ``
`logger.mdc..key` | MDC key override, see complex example below for usage | ``
`logger.mdc..level` | log level to use | `TRACE`
`logger.mdc..loggers` | passlist of logger names, matches all loggers if empty | `[]`
diff --git a/pom.xml b/pom.xml
index ff43677..22f50e6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,11 +4,11 @@
io.kokuwa.micronaut
micronaut-logging
- 3.0.6
+ 5.0.1-SNAPSHOT
Logging Support for Micronaut
Enhanced logging using MDC or request header.
- https://github.com/kokuwaio/micronaut-logging
+ https://git.kokuwa.io/kokuwaio/micronaut-logging
2020
Kokuwa.io
@@ -16,130 +16,58 @@
- Apache License 2.0
- https://www.apache.org/licenses/LICENSE-2.0
+ EUPL-1.2
+ https://eupl.eu/1.2/en
+ repo
- sschnabe
+ stephan.schnabel
Stephan Schnabel
- https://github.com/sschnabe
- stephan@grayc.de
- GrayC GmbH
- https://grayc.de
+ https://schnabel.org
+ stephan@schnabel.org
+ Europe/Berlin
- https://github.com/kokuwaio/micronaut-logging
- scm:git:https://github.com/kokuwaio/micronaut-logging.git
- scm:git:https://github.com/kokuwaio/micronaut-logging.git
- 3.0.6
+ https://git.kokuwa.io/kokuwaio/micronaut-logging
+ scm:git:https://git.kokuwa.io/kokuwaio/micronaut-logging.git
+ scm:git:https://git.kokuwa.io/kokuwaio/micronaut-logging.git
+ HEAD
- github
- https://github.com/kokuwaio/micronaut-logging/issues
+ forgejo
+ https://git.kokuwa.io/kokuwaio/micronaut-logging/issues
- github
- https://github.com/kokuwaio/micronaut-logging/actions
+ woodpecker
+ https://ci.kokuwa.io/repos/kokuwaio/micronaut-logging
- sonatype-nexus
- https://oss.sonatype.org/content/repositories/snapshots
+ sonatype.org
+ https://central.sonatype.com/repository/maven-snapshots/
-
- sonatype-nexus
- https://oss.sonatype.org/service/local/staging/deploy/maven2
-
-
-
-
-
-
+ 2025-06-27T18:11:48Z
UTF-8
- ISO-8859-1
-
- 11
- 11
- true
- true
- true
- true
- true
-
-
-
-
-
-
-
- 3.2.1
- 3.2.0
- 3.10.1
- 3.5.0
- 3.1.0
- 3.0.1
- 3.1.0
- 3.5.0
- 3.3.0
- 3.0.0-M7
- 3.3.0
- 3.2.1
- 3.0.0-M9
- 1.2.0
- 1.6.13
- 10.7.0
- 0.5.6
-
-
-
- 1.2.11
- 0.1.5
- 3.8.5
-
+ 17
-
-
- io.micronaut
- micronaut-bom
- ${version.io.micronaut}
+ io.micronaut.platform
+ micronaut-platform
+ 4.9.0
pom
import
-
-
-
- ch.qos.logback
- logback-classic
- ${version.ch.qos.logback}
-
-
- ch.qos.logback.contrib
- logback-json-classic
- ${version.ch.qos.logback.contrib}
-
-
- ch.qos.logback.contrib
- logback-json-core
- ${version.ch.qos.logback.contrib}
-
-
- ch.qos.logback.contrib
- logback-jackson
- ${version.ch.qos.logback.contrib}
-
-
@@ -147,7 +75,7 @@
io.micronaut
- micronaut-runtime
+ micronaut-http
provided
@@ -155,6 +83,10 @@
micronaut-security
provided
+
+ io.micronaut.serde
+ micronaut-serde-api
+
io.micronaut.test
micronaut-test-junit5
@@ -175,178 +107,184 @@
micronaut-security-jwt
test
+
+ io.micronaut.serde
+ micronaut-serde-jackson
+ test
+
+
+ org.yaml
+ snakeyaml
+ test
+
-
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+
+ org.slf4j
+ slf4j-api
+
ch.qos.logback
logback-classic
- ch.qos.logback.contrib
- logback-json-classic
-
-
- ch.qos.logback.contrib
- logback-jackson
- runtime
+ ch.qos.logback
+ logback-core
+ verify
-
- org.apache.maven.plugins
- maven-checkstyle-plugin
- ${version.org.apache.maven.plugins.checkstyle}
-
- checkstyle.xml
- checkstyle-suppression.xml
- true
-
-
-
- com.puppycrawl.tools
- checkstyle
- ${version.com.puppycrawl.tools.checkstyle}
-
-
- io.kokuwa
- maven-parent
- ${version.io.kokuwa.checkstyle}
- zip
- checkstyle
-
-
-
-
- org.apache.maven.plugins
- maven-clean-plugin
- ${version.org.apache.maven.plugins.clean}
-
org.apache.maven.plugins
maven-compiler-plugin
- ${version.org.apache.maven.plugins.compiler}
+ 3.14.0
+ class
+ true
+ true
+ true
+ -Xlint:all,-processing
io.micronaut
micronaut-inject-java
- ${version.io.micronaut}
-
- org.apache.maven.plugins
- maven-dependency-plugin
- ${version.org.apache.maven.plugins.dependency}
-
org.apache.maven.plugins
maven-deploy-plugin
- ${version.org.apache.maven.plugins.deploy}
+ 3.1.4
org.apache.maven.plugins
maven-gpg-plugin
- ${version.org.apache.maven.plugins.gpg}
+ 3.2.7
org.apache.maven.plugins
maven-install-plugin
- ${version.org.apache.maven.plugins.install}
+ 3.1.4
org.apache.maven.plugins
- maven-javadoc-plugin
- ${version.org.apache.maven.plugins.javadoc}
+ maven-invoker-plugin
+ 3.9.1
org.apache.maven.plugins
maven-jar-plugin
- ${version.org.apache.maven.plugins.jar}
+ 3.4.2
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.11.2
org.apache.maven.plugins
maven-release-plugin
- ${version.org.apache.maven.plugins.release}
+ 3.1.1
- @{project.version}
- release
- true
+ verify
+ check
+ deploy
+ deploy,release
true
+ @{prefix} prepare release @{releaseLabel} [CI SKIP]
+ @{project.version}
org.apache.maven.plugins
maven-resources-plugin
- ${version.org.apache.maven.plugins.resources}
+ 3.3.1
+
+ ISO-8859-1
+
org.apache.maven.plugins
maven-source-plugin
- ${version.org.apache.maven.plugins.source}
+ 3.3.1
org.apache.maven.plugins
maven-surefire-plugin
- ${version.org.apache.maven.plugins.surefire}
-
- true
-
+ 3.5.3
org.codehaus.mojo
tidy-maven-plugin
- ${version.org.codehaus.mojo.tidy}
+ 1.4.0
- org.sonatype.plugins
- nexus-staging-maven-plugin
- ${version.org.sonatype.plugins.nexus-staging}
+ org.sonatype.central
+ central-publishing-maven-plugin
+ 0.8.0
+
+
+ net.revelc.code.formatter
+ formatter-maven-plugin
+ 2.27.0
+
+ ${project.basedir}/src/eclipse/formatter.xml
+
+
+
+ net.revelc.code
+ impsort-maven-plugin
+ 1.12.0
+
+ true
+ java.,javax.,jakarta.,org.
+
-
+
org.apache.maven.plugins
- maven-source-plugin
+ maven-invoker-plugin
- jar-no-fork
+ install
+ integration-test
+ verify
+
+ ${project.build.directory}/its
+ true
+ test
+ false
+ true
+
-
-
- org.codehaus.mojo
- tidy-maven-plugin
-
-
-
- check
-
-
-
-
-
-
+
org.apache.maven.plugins
- maven-checkstyle-plugin
+ maven-install-plugin
-
- check
-
+ default-install
+
@@ -356,11 +294,126 @@
- release
+ dev
+
+
+ !env.CI
+
+
+
+ true
+
+
+
+
+ org.codehaus.mojo
+ tidy-maven-plugin
+
+
+ validate
+
+ pom
+
+
+
+
+
+ net.revelc.code
+ impsort-maven-plugin
+
+
+ validate
+
+ sort
+
+
+
+
+
+ net.revelc.code.formatter
+ formatter-maven-plugin
+
+
+ validate
+
+ format
+
+
+
+
+
+
+
+
+ check
+
+
+ env.CI
+
+
+
+
+
+ org.codehaus.mojo
+ tidy-maven-plugin
+
+
+ validate
+
+ check
+
+
+
+
+
+ net.revelc.code
+ impsort-maven-plugin
+
+
+ validate
+
+ check
+
+
+
+
+
+ net.revelc.code.formatter
+ formatter-maven-plugin
+
+
+ validate
+
+ validate
+
+
+
+
+
+
+
+
+ deploy
+
+
+ env.CI
+
+
-
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+
+ jar
+
+
+
+
org.apache.maven.plugins
maven-javadoc-plugin
@@ -373,7 +426,7 @@
-
+
org.apache.maven.plugins
maven-gpg-plugin
@@ -382,22 +435,30 @@
sign
+
+ bc
+
-
-
- org.sonatype.plugins
- nexus-staging-maven-plugin
- true
-
- sonatype-nexus
- https://oss.sonatype.org/
- true
-
-
-
+
+
+
+
+ release
+
+
+
+ org.sonatype.central
+ central-publishing-maven-plugin
+ true
+
+ sonatype.org
+ true
+ published
+
+
diff --git a/renovate.json b/renovate.json
new file mode 100644
index 0000000..4bf0e44
--- /dev/null
+++ b/renovate.json
@@ -0,0 +1,8 @@
+{
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+ "extends": ["local>kokuwaio/renovate-config", ":reviewer(stephan.schnabel)"],
+ "packageRules": [{
+ "matchPackageNames": ["io.kokuwa.micronaut:mirconaut-logging-it"],
+ "enabled": false
+ }]
+}
diff --git a/src/eclipse/formatter.xml b/src/eclipse/formatter.xml
new file mode 100644
index 0000000..61186a2
--- /dev/null
+++ b/src/eclipse/formatter.xml
@@ -0,0 +1,404 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/it/invoker.properties b/src/it/invoker.properties
new file mode 100644
index 0000000..7920ff9
--- /dev/null
+++ b/src/it/invoker.properties
@@ -0,0 +1,3 @@
+invoker.environmentVariables.KUBERNETES_SERVICE_HOST=
+invoker.environmentVariables.LOGBACK_APPENDER=
+invoker.environmentVariables.GOOGLE_CLOUD_PROJECT=
diff --git a/src/it/level-from-micronaut/invoker.properties b/src/it/level-from-micronaut/invoker.properties
new file mode 100644
index 0000000..46bbf8c
--- /dev/null
+++ b/src/it/level-from-micronaut/invoker.properties
@@ -0,0 +1 @@
+invoker.environmentVariables.LOGGER_LEVELS_IO_KOKUWA_MICRONAUT_LOGGING=DEBUG
diff --git a/src/it/level-from-micronaut/pom.xml b/src/it/level-from-micronaut/pom.xml
new file mode 100644
index 0000000..cf36117
--- /dev/null
+++ b/src/it/level-from-micronaut/pom.xml
@@ -0,0 +1,12 @@
+
+
+ 4.0.0
+
+
+ io.kokuwa.micronaut
+ mirconaut-logging-it
+ LOCAL-SNAPSHOT
+
+
+ mirconaut-logging-it-level-from-micronaut
+
diff --git a/src/it/level-from-micronaut/postbuild.bsh b/src/it/level-from-micronaut/postbuild.bsh
new file mode 100644
index 0000000..026881f
--- /dev/null
+++ b/src/it/level-from-micronaut/postbuild.bsh
@@ -0,0 +1,22 @@
+// verify log
+
+String expected = "^[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{0,3} main DEBUG i.k.m.logging.LoggingTest test-output-marker$";
+String[] logs = org.codehaus.plexus.util.FileUtils.fileRead(basedir + "/build.log").split("\n");
+
+for (String log : logs) {
+ if (!log.contains("test-output-marker")) {
+ continue;
+ }
+ if (java.util.regex.Pattern.matches(expected, log.replaceAll("\u001B\\[[;\\d]*m", ""))) {
+ return true;
+ } else {
+ System.out.println("marker found, but formatting invalid:");
+ System.out.println("[EXPECTED] " + expected);
+ System.out.println("[ACTUAL] " + log);
+ System.out.println("[BASE64] " + Base64.getEncoder().encodeToString(log.getBytes()));
+ return false;
+ }
+}
+
+System.out.println("marker not found");
+return false;
diff --git a/src/it/log-gcp-from-env/invoker.properties b/src/it/log-gcp-from-env/invoker.properties
new file mode 100644
index 0000000..f9f63a8
--- /dev/null
+++ b/src/it/log-gcp-from-env/invoker.properties
@@ -0,0 +1 @@
+invoker.environmentVariables.LOGBACK_APPENDER=GCP
diff --git a/src/it/log-gcp-from-env/pom.xml b/src/it/log-gcp-from-env/pom.xml
new file mode 100644
index 0000000..11f4a92
--- /dev/null
+++ b/src/it/log-gcp-from-env/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+
+ io.kokuwa.micronaut
+ mirconaut-logging-it
+ LOCAL-SNAPSHOT
+
+
+ mirconaut-logging-it-log-gcp-from-env
+
+
+
+ io.micronaut.serde
+ micronaut-serde-jsonp
+
+
+
diff --git a/src/it/log-gcp-from-env/postbuild.bsh b/src/it/log-gcp-from-env/postbuild.bsh
new file mode 100644
index 0000000..d9e0657
--- /dev/null
+++ b/src/it/log-gcp-from-env/postbuild.bsh
@@ -0,0 +1,21 @@
+// verify log
+
+String expected = "^\\{\"time\":\"202[3-9]-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{0,3}Z\",\"severity\":\"INFO\",\"thread\":\"main\",\"logger\":\"io.kokuwa.micronaut.logging.LoggingTest\",\"message\":\"test-output-marker\",\"raw-message\":\"test-output-marker\"}$";
+String[] logs = org.codehaus.plexus.util.FileUtils.fileRead(basedir + "/build.log").split("\n");
+
+for (String log : logs) {
+ if (!log.contains("test-output-marker")) {
+ continue;
+ }
+ if (java.util.regex.Pattern.matches(expected, log)) {
+ return true;
+ } else {
+ System.out.println("marker found, but formatting invalid:");
+ System.out.println("[EXPECTED] " + expected);
+ System.out.println("[ACTUAL] " + log);
+ return false;
+ }
+}
+
+System.out.println("marker not found");
+return false;
diff --git a/src/it/log-gcp-from-gcloud/invoker.properties b/src/it/log-gcp-from-gcloud/invoker.properties
new file mode 100644
index 0000000..ec347b6
--- /dev/null
+++ b/src/it/log-gcp-from-gcloud/invoker.properties
@@ -0,0 +1 @@
+invoker.environmentVariables.GOOGLE_CLOUD_PROJECT=value
diff --git a/src/it/log-gcp-from-gcloud/pom.xml b/src/it/log-gcp-from-gcloud/pom.xml
new file mode 100644
index 0000000..0bf33a2
--- /dev/null
+++ b/src/it/log-gcp-from-gcloud/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+
+ io.kokuwa.micronaut
+ mirconaut-logging-it
+ LOCAL-SNAPSHOT
+
+
+ mirconaut-logging-it-log-gcp-from-gcloud
+
+
+
+ io.micronaut.serde
+ micronaut-serde-jsonp
+
+
+
diff --git a/src/it/log-gcp-from-gcloud/postbuild.bsh b/src/it/log-gcp-from-gcloud/postbuild.bsh
new file mode 100644
index 0000000..d9e0657
--- /dev/null
+++ b/src/it/log-gcp-from-gcloud/postbuild.bsh
@@ -0,0 +1,21 @@
+// verify log
+
+String expected = "^\\{\"time\":\"202[3-9]-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{0,3}Z\",\"severity\":\"INFO\",\"thread\":\"main\",\"logger\":\"io.kokuwa.micronaut.logging.LoggingTest\",\"message\":\"test-output-marker\",\"raw-message\":\"test-output-marker\"}$";
+String[] logs = org.codehaus.plexus.util.FileUtils.fileRead(basedir + "/build.log").split("\n");
+
+for (String log : logs) {
+ if (!log.contains("test-output-marker")) {
+ continue;
+ }
+ if (java.util.regex.Pattern.matches(expected, log)) {
+ return true;
+ } else {
+ System.out.println("marker found, but formatting invalid:");
+ System.out.println("[EXPECTED] " + expected);
+ System.out.println("[ACTUAL] " + log);
+ return false;
+ }
+}
+
+System.out.println("marker not found");
+return false;
diff --git a/src/it/log-gcp-with-service/invoker.properties b/src/it/log-gcp-with-service/invoker.properties
new file mode 100644
index 0000000..887fd80
--- /dev/null
+++ b/src/it/log-gcp-with-service/invoker.properties
@@ -0,0 +1,3 @@
+invoker.environmentVariables.LOGBACK_APPENDER=GCP
+invoker.environmentVariables.SERVICE_NAME=test-service
+invoker.environmentVariables.SERVICE_VERSION=0.1.2
diff --git a/src/it/log-gcp-with-service/pom.xml b/src/it/log-gcp-with-service/pom.xml
new file mode 100644
index 0000000..0f81f40
--- /dev/null
+++ b/src/it/log-gcp-with-service/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+
+ io.kokuwa.micronaut
+ mirconaut-logging-it
+ LOCAL-SNAPSHOT
+
+
+ mirconaut-logging-it-log-gcp-with-service
+
+
+
+ io.micronaut.serde
+ micronaut-serde-jsonp
+
+
+
diff --git a/src/it/log-gcp-with-service/postbuild.bsh b/src/it/log-gcp-with-service/postbuild.bsh
new file mode 100644
index 0000000..6264c10
--- /dev/null
+++ b/src/it/log-gcp-with-service/postbuild.bsh
@@ -0,0 +1,21 @@
+// verify log
+
+String expected = "^\\{\"time\":\"202[3-9]-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{0,3}Z\",\"severity\":\"INFO\",\"thread\":\"main\",\"logger\":\"io.kokuwa.micronaut.logging.LoggingTest\",\"message\":\"test-output-marker\",\"raw-message\":\"test-output-marker\",\"serviceContext\":\\{\"service\":\"test-service\",\"version\":\"0.1.2\"}}$";
+String[] logs = org.codehaus.plexus.util.FileUtils.fileRead(basedir + "/build.log").split("\n");
+
+for (String log : logs) {
+ if (!log.contains("test-output-marker")) {
+ continue;
+ }
+ if (java.util.regex.Pattern.matches(expected, log)) {
+ return true;
+ } else {
+ System.out.println("marker found, but formatting invalid:");
+ System.out.println("[EXPECTED] " + expected);
+ System.out.println("[ACTUAL] " + log);
+ return false;
+ }
+}
+
+System.out.println("marker not found");
+return false;
diff --git a/src/it/log-json-from-env-serde-jackson/invoker.properties b/src/it/log-json-from-env-serde-jackson/invoker.properties
new file mode 100644
index 0000000..08de0de
--- /dev/null
+++ b/src/it/log-json-from-env-serde-jackson/invoker.properties
@@ -0,0 +1 @@
+invoker.environmentVariables.LOGBACK_APPENDER=JSON
diff --git a/src/it/log-json-from-env-serde-jackson/pom.xml b/src/it/log-json-from-env-serde-jackson/pom.xml
new file mode 100644
index 0000000..87283dd
--- /dev/null
+++ b/src/it/log-json-from-env-serde-jackson/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+
+ io.kokuwa.micronaut
+ mirconaut-logging-it
+ LOCAL-SNAPSHOT
+
+
+ mirconaut-logging-it-log-json-from-env-serde-jackson
+
+
+
+ io.micronaut.serde
+ micronaut-serde-jackson
+
+
+
diff --git a/src/it/log-json-from-env-serde-jackson/postbuild.bsh b/src/it/log-json-from-env-serde-jackson/postbuild.bsh
new file mode 100644
index 0000000..0693fe0
--- /dev/null
+++ b/src/it/log-json-from-env-serde-jackson/postbuild.bsh
@@ -0,0 +1,21 @@
+// verify log
+
+String expected = "^\\{\"timestamp\":\"[0-9]{13}\",\"level\":\"INFO\",\"thread\":\"main\",\"logger\":\"io.kokuwa.micronaut.logging.LoggingTest\",\"message\":\"test-output-marker\",\"raw-message\":\"test-output-marker\"}$";
+String[] logs = org.codehaus.plexus.util.FileUtils.fileRead(basedir + "/build.log").split("\n");
+
+for (String log : logs) {
+ if (!log.contains("test-output-marker")) {
+ continue;
+ }
+ if (java.util.regex.Pattern.matches(expected, log)) {
+ return true;
+ } else {
+ System.out.println("marker found, but formatting invalid:");
+ System.out.println("[EXPECTED] " + expected);
+ System.out.println("[ACTUAL] " + log);
+ return false;
+ }
+}
+
+System.out.println("marker not found");
+return false;
diff --git a/src/it/log-json-from-env-serde-jsonp/invoker.properties b/src/it/log-json-from-env-serde-jsonp/invoker.properties
new file mode 100644
index 0000000..08de0de
--- /dev/null
+++ b/src/it/log-json-from-env-serde-jsonp/invoker.properties
@@ -0,0 +1 @@
+invoker.environmentVariables.LOGBACK_APPENDER=JSON
diff --git a/src/it/log-json-from-env-serde-jsonp/pom.xml b/src/it/log-json-from-env-serde-jsonp/pom.xml
new file mode 100644
index 0000000..2d0d0ad
--- /dev/null
+++ b/src/it/log-json-from-env-serde-jsonp/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+
+ io.kokuwa.micronaut
+ mirconaut-logging-it
+ LOCAL-SNAPSHOT
+
+
+ mirconaut-logging-it-log-json-from-env-serde-jsonp
+
+
+
+ io.micronaut.serde
+ micronaut-serde-jsonp
+
+
+
diff --git a/src/it/log-json-from-env-serde-jsonp/postbuild.bsh b/src/it/log-json-from-env-serde-jsonp/postbuild.bsh
new file mode 100644
index 0000000..0693fe0
--- /dev/null
+++ b/src/it/log-json-from-env-serde-jsonp/postbuild.bsh
@@ -0,0 +1,21 @@
+// verify log
+
+String expected = "^\\{\"timestamp\":\"[0-9]{13}\",\"level\":\"INFO\",\"thread\":\"main\",\"logger\":\"io.kokuwa.micronaut.logging.LoggingTest\",\"message\":\"test-output-marker\",\"raw-message\":\"test-output-marker\"}$";
+String[] logs = org.codehaus.plexus.util.FileUtils.fileRead(basedir + "/build.log").split("\n");
+
+for (String log : logs) {
+ if (!log.contains("test-output-marker")) {
+ continue;
+ }
+ if (java.util.regex.Pattern.matches(expected, log)) {
+ return true;
+ } else {
+ System.out.println("marker found, but formatting invalid:");
+ System.out.println("[EXPECTED] " + expected);
+ System.out.println("[ACTUAL] " + log);
+ return false;
+ }
+}
+
+System.out.println("marker not found");
+return false;
diff --git a/src/it/log-json-from-env-serde-missing/invoker.properties b/src/it/log-json-from-env-serde-missing/invoker.properties
new file mode 100644
index 0000000..08de0de
--- /dev/null
+++ b/src/it/log-json-from-env-serde-missing/invoker.properties
@@ -0,0 +1 @@
+invoker.environmentVariables.LOGBACK_APPENDER=JSON
diff --git a/src/it/log-json-from-env-serde-missing/pom.xml b/src/it/log-json-from-env-serde-missing/pom.xml
new file mode 100644
index 0000000..fcf06e0
--- /dev/null
+++ b/src/it/log-json-from-env-serde-missing/pom.xml
@@ -0,0 +1,12 @@
+
+
+ 4.0.0
+
+
+ io.kokuwa.micronaut
+ mirconaut-logging-it
+ LOCAL-SNAPSHOT
+
+
+ mirconaut-logging-it-log-json-from-env-serde-missing
+
diff --git a/src/it/log-json-from-env-serde-missing/postbuild.bsh b/src/it/log-json-from-env-serde-missing/postbuild.bsh
new file mode 100644
index 0000000..465b88c
--- /dev/null
+++ b/src/it/log-json-from-env-serde-missing/postbuild.bsh
@@ -0,0 +1,5 @@
+// verify log
+
+return org.codehaus.plexus.util.FileUtils
+ .fileRead(basedir + "/build.log")
+ .contains("Failed to get object mapper from micronaut, please check your classpath");
diff --git a/src/it/log-json-from-kubernetes/invoker.properties b/src/it/log-json-from-kubernetes/invoker.properties
new file mode 100644
index 0000000..5bba112
--- /dev/null
+++ b/src/it/log-json-from-kubernetes/invoker.properties
@@ -0,0 +1 @@
+invoker.environmentVariables.KUBERNETES_SERVICE_HOST=value
diff --git a/src/it/log-json-from-kubernetes/pom.xml b/src/it/log-json-from-kubernetes/pom.xml
new file mode 100644
index 0000000..20d412c
--- /dev/null
+++ b/src/it/log-json-from-kubernetes/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+
+ io.kokuwa.micronaut
+ mirconaut-logging-it
+ LOCAL-SNAPSHOT
+
+
+ mirconaut-logging-it-log-json-from-kubernetes
+
+
+
+ io.micronaut.serde
+ micronaut-serde-jsonp
+
+
+
diff --git a/src/it/log-json-from-kubernetes/postbuild.bsh b/src/it/log-json-from-kubernetes/postbuild.bsh
new file mode 100644
index 0000000..0693fe0
--- /dev/null
+++ b/src/it/log-json-from-kubernetes/postbuild.bsh
@@ -0,0 +1,21 @@
+// verify log
+
+String expected = "^\\{\"timestamp\":\"[0-9]{13}\",\"level\":\"INFO\",\"thread\":\"main\",\"logger\":\"io.kokuwa.micronaut.logging.LoggingTest\",\"message\":\"test-output-marker\",\"raw-message\":\"test-output-marker\"}$";
+String[] logs = org.codehaus.plexus.util.FileUtils.fileRead(basedir + "/build.log").split("\n");
+
+for (String log : logs) {
+ if (!log.contains("test-output-marker")) {
+ continue;
+ }
+ if (java.util.regex.Pattern.matches(expected, log)) {
+ return true;
+ } else {
+ System.out.println("marker found, but formatting invalid:");
+ System.out.println("[EXPECTED] " + expected);
+ System.out.println("[ACTUAL] " + log);
+ return false;
+ }
+}
+
+System.out.println("marker not found");
+return false;
diff --git a/src/it/log-text/pom.xml b/src/it/log-text/pom.xml
new file mode 100644
index 0000000..f89c081
--- /dev/null
+++ b/src/it/log-text/pom.xml
@@ -0,0 +1,12 @@
+
+
+ 4.0.0
+
+
+ io.kokuwa.micronaut
+ mirconaut-logging-it
+ LOCAL-SNAPSHOT
+
+
+ mirconaut-logging-it-log-text
+
diff --git a/src/it/log-text/postbuild.bsh b/src/it/log-text/postbuild.bsh
new file mode 100644
index 0000000..40e2f91
--- /dev/null
+++ b/src/it/log-text/postbuild.bsh
@@ -0,0 +1,22 @@
+// verify log
+
+String expected = "^[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{0,3} main INFO i.k.m.logging.LoggingTest test-output-marker$";
+String[] logs = org.codehaus.plexus.util.FileUtils.fileRead(basedir + "/build.log").split("\n");
+
+for (String log : logs) {
+ if (!log.contains("test-output-marker")) {
+ continue;
+ }
+ if (java.util.regex.Pattern.matches(expected, log.replaceAll("\u001B\\[[;\\d]*m", ""))) {
+ return true;
+ } else {
+ System.out.println("marker found, but formatting invalid:");
+ System.out.println("[EXPECTED] " + expected);
+ System.out.println("[ACTUAL] " + log);
+ System.out.println("[BASE64] " + Base64.getEncoder().encodeToString(log.getBytes()));
+ return false;
+ }
+}
+
+System.out.println("marker not found");
+return false;
diff --git a/src/it/logback-xml-custom/pom.xml b/src/it/logback-xml-custom/pom.xml
new file mode 100644
index 0000000..f89c081
--- /dev/null
+++ b/src/it/logback-xml-custom/pom.xml
@@ -0,0 +1,12 @@
+
+
+ 4.0.0
+
+
+ io.kokuwa.micronaut
+ mirconaut-logging-it
+ LOCAL-SNAPSHOT
+
+
+ mirconaut-logging-it-log-text
+
diff --git a/src/it/logback-xml-custom/postbuild.bsh b/src/it/logback-xml-custom/postbuild.bsh
new file mode 100644
index 0000000..c6a3d94
--- /dev/null
+++ b/src/it/logback-xml-custom/postbuild.bsh
@@ -0,0 +1,21 @@
+// verify log
+
+String expected = "^TRACE io.kokuwa.micronaut.logging.LoggingTest test-output-marker$";
+String[] logs = org.codehaus.plexus.util.FileUtils.fileRead(basedir + "/build.log").split("\n");
+
+for (String log : logs) {
+ if (!log.contains("test-output-marker")) {
+ continue;
+ }
+ if (java.util.regex.Pattern.matches(expected, log)) {
+ return true;
+ } else {
+ System.out.println("marker found, but formatting invalid:");
+ System.out.println("[EXPECTED] " + expected);
+ System.out.println("[ACTUAL] " + log);
+ return false;
+ }
+}
+
+System.out.println("marker not found");
+return false;
diff --git a/src/it/logback-xml-custom/src/test/resources/logback.xml b/src/it/logback-xml-custom/src/test/resources/logback.xml
new file mode 100644
index 0000000..a704605
--- /dev/null
+++ b/src/it/logback-xml-custom/src/test/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %-5level %logger{40} %msg%n
+
+
+
+
+
+
+
+
diff --git a/src/it/pom.xml b/src/it/pom.xml
new file mode 100644
index 0000000..d08c441
--- /dev/null
+++ b/src/it/pom.xml
@@ -0,0 +1,122 @@
+
+
+ 4.0.0
+
+ io.kokuwa.micronaut
+ mirconaut-logging-it
+ LOCAL-SNAPSHOT
+ pom
+
+
+ log-text
+ log-json-from-env
+ log-json-from-kubernetes
+ log-gcp-from-env
+ log-gcp-from-gcloud
+ level-from-micronaut
+ logback-xml-custom
+
+
+
+ 2025-06-27T00:00:00Z
+ UTF-8
+ 17
+
+
+
+
+
+ io.kokuwa.micronaut
+ micronaut-logging
+ @project.version@
+
+
+ io.micronaut.platform
+ micronaut-platform
+ 4.9.0
+ pom
+ import
+
+
+
+
+
+
+
+ io.micronaut
+ micronaut-runtime
+
+
+ io.micronaut.test
+ micronaut-test-junit5
+ test
+
+
+ io.kokuwa.micronaut
+ micronaut-logging
+ runtime
+
+
+
+
+
+ ${project.basedir}/../src/test/java
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.14.0
+
+ class
+ true
+ true
+ true
+ -Xlint:all,-processing
+
+
+ io.micronaut
+ micronaut-inject-java
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 3.3.1
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 3.5.3
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+
+
+ default-resources
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ default-compile
+
+
+
+
+
+
+
+
diff --git a/src/it/src/test/java/io/kokuwa/micronaut/logging/LoggingTest.java b/src/it/src/test/java/io/kokuwa/micronaut/logging/LoggingTest.java
new file mode 100644
index 0000000..2d8463a
--- /dev/null
+++ b/src/it/src/test/java/io/kokuwa/micronaut/logging/LoggingTest.java
@@ -0,0 +1,13 @@
+package io.kokuwa.micronaut.logging;
+
+@io.micronaut.test.extensions.junit5.annotation.MicronautTest
+public class LoggingTest {
+
+ @org.junit.jupiter.api.Test
+ void log() {
+ var log = org.slf4j.LoggerFactory.getLogger(LoggingTest.class);
+ log.trace("test-output-marker");
+ log.debug("test-output-marker");
+ log.info("test-output-marker");
+ }
+}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/LogbackUtil.java b/src/main/java/io/kokuwa/micronaut/logging/LogbackUtil.java
index df1d6ab..bb21701 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/LogbackUtil.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/LogbackUtil.java
@@ -4,14 +4,14 @@ import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
+import jakarta.inject.Singleton;
+
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.turbo.TurboFilter;
import io.micronaut.context.annotation.BootstrapContextCompatible;
import io.micronaut.context.annotation.Requires;
-import io.micronaut.core.annotation.Internal;
-import jakarta.inject.Singleton;
/**
* Utility class for Logback operations.
@@ -21,7 +21,6 @@ import jakarta.inject.Singleton;
@Requires(classes = LoggerContext.class)
@BootstrapContextCompatible
@Singleton
-@Internal
public class LogbackUtil {
private final LoggerContext context;
diff --git a/src/main/java/io/kokuwa/micronaut/logging/configurator/DefaultConfigurator.java b/src/main/java/io/kokuwa/micronaut/logging/configurator/DefaultConfigurator.java
index 1d808a9..3b1a51a 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/configurator/DefaultConfigurator.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/configurator/DefaultConfigurator.java
@@ -1,8 +1,8 @@
package io.kokuwa.micronaut.logging.configurator;
-import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.Configurator;
+import ch.qos.logback.classic.util.DefaultJoranConfigurator;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.spi.ContextAwareBase;
@@ -13,13 +13,19 @@ import ch.qos.logback.core.spi.ContextAwareBase;
*/
public class DefaultConfigurator extends ContextAwareBase implements Configurator {
+ @SuppressWarnings("deprecation")
@Override
- public void configure(LoggerContext loggerContext) {
+ public ExecutionStatus configure(LoggerContext loggerContext) {
+
+ if (new DefaultJoranConfigurator().findURLOfDefaultConfigurationFile(false) != null) {
+ // there is a default logback file, use this one instead of our default
+ return ExecutionStatus.INVOKE_NEXT_IF_ANY;
+ }
var base = DefaultConfigurator.class.getResource("/io/kokuwa/logback/logback-default.xml");
if (base == null) {
addError("Failed to find logback.xml from io.kokuwa:micronaut-logging");
- return;
+ return ExecutionStatus.NEUTRAL;
}
try {
@@ -29,8 +35,9 @@ public class DefaultConfigurator extends ContextAwareBase implements Configurato
configurator.doConfigure(base);
} catch (JoranException e) {
addError("Failed to load logback.xml from io.kokuwa:micronaut-logging", e);
+ return ExecutionStatus.NEUTRAL;
}
- loggerContext.getLogger("io.micronaut.logging.PropertiesLoggingLevelsConfigurer").setLevel(Level.WARN);
+ return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY;
}
}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/configurator/MicronautJoranConfigurator.java b/src/main/java/io/kokuwa/micronaut/logging/configurator/MicronautJoranConfigurator.java
index f89db16..a1010d7 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/configurator/MicronautJoranConfigurator.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/configurator/MicronautJoranConfigurator.java
@@ -12,8 +12,8 @@ import ch.qos.logback.core.joran.spi.RuleStore;
public class MicronautJoranConfigurator extends JoranConfigurator {
@Override
- public void addInstanceRules(RuleStore rs) {
- super.addInstanceRules(rs);
- rs.addRule(new ElementSelector("configuration/root/autoAppender"), new RootAutoSelectAppenderAction());
+ public void addElementSelectorAndActionAssociations(RuleStore rs) {
+ super.addElementSelectorAndActionAssociations(rs);
+ rs.addRule(new ElementSelector("configuration/root/autoAppender"), () -> new RootAutoSelectAppenderAction());
}
}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/configurator/RootAutoSelectAppenderAction.java b/src/main/java/io/kokuwa/micronaut/logging/configurator/RootAutoSelectAppenderAction.java
index b490a35..1d0db03 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/configurator/RootAutoSelectAppenderAction.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/configurator/RootAutoSelectAppenderAction.java
@@ -1,16 +1,18 @@
package io.kokuwa.micronaut.logging.configurator;
-import java.util.Map;
-
-import org.xml.sax.Attributes;
+import java.util.Optional;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.Appender;
+import ch.qos.logback.core.ConsoleAppender;
+import ch.qos.logback.core.Layout;
+import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
import ch.qos.logback.core.joran.action.Action;
-import ch.qos.logback.core.joran.action.ActionConst;
-import ch.qos.logback.core.joran.spi.InterpretationContext;
+import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext;
+import io.kokuwa.micronaut.logging.layout.GcpJsonLayout;
+import io.kokuwa.micronaut.logging.layout.JsonLayout;
import io.micronaut.core.util.StringUtils;
/**
@@ -27,9 +29,17 @@ public class RootAutoSelectAppenderAction extends Action {
private static final String APPENDER_JSON = "JSON";
private static final String APPENDER_GCP = "GCP";
private static final String LOGBACK_APPENDER = "LOGBACK_APPENDER";
+ private static final String LOGBACK_PATTERN = "LOGBACK_PATTERN";
+ private static final String LOGBACK_PATTERN_DEFAULT = """
+ %cyan(%d{HH:mm:ss.SSS}) \
+ %gray(%-6.6thread) \
+ %highlight(%-5level) \
+ %magenta(%32logger{32}) \
+ %mdc \
+ %msg%n""";
@Override
- public void begin(InterpretationContext ic, String name, Attributes attributes) {
+ public void begin(SaxEventInterpretationContext ic, String name, org.xml.sax.Attributes attributes) {
var rootLogger = LoggerContext.class.cast(context).getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
var rootLoggerAppenders = rootLogger.iteratorForAppenders();
@@ -38,36 +48,83 @@ public class RootAutoSelectAppenderAction extends Action {
return;
}
- var envAppender = System.getenv(LOGBACK_APPENDER);
- if (envAppender != null && setAppender(ic, rootLogger, envAppender)) {
+ var envAppender = env(LOGBACK_APPENDER, null);
+ if (envAppender != null) {
+ setAppender(rootLogger, envAppender);
return;
}
- if (IS_KUBERNETES && setAppender(ic, rootLogger, APPENDER_JSON)) {
+ if (IS_KUBERNETES) {
+ setAppender(rootLogger, APPENDER_JSON);
return;
}
- if (IS_GCP && setAppender(ic, rootLogger, APPENDER_GCP)) {
+ if (IS_GCP) {
+ setAppender(rootLogger, APPENDER_GCP);
return;
}
- setAppender(ic, rootLogger, APPENDER_CONSOLE);
+ setAppender(rootLogger, APPENDER_CONSOLE);
}
@Override
- public void end(InterpretationContext ic, String name) {}
-
- private boolean setAppender(InterpretationContext ic, Logger rootLogger, String appenderName) {
-
- @SuppressWarnings("unchecked")
- var appenderBag = (Map>) ic.getObjectMap().get(ActionConst.APPENDER_BAG);
- var appender = appenderBag.get(appenderName);
- if (appender == null) {
- addError("Could not find an appender named [" + appenderName
- + "]. Did you define it below instead of above in the configuration file?");
- return false;
- }
+ public void end(SaxEventInterpretationContext ic, String name) {}
+ private void setAppender(Logger rootLogger, String appenderName) {
addInfo("Use appender: " + appenderName);
+
+ var layout = switch (appenderName) {
+ case APPENDER_JSON -> json();
+ case APPENDER_GCP -> gcp();
+ case APPENDER_CONSOLE -> console();
+ default -> {
+ addError("Appender " + appenderName + " not found. Using console ...");
+ yield console();
+ }
+ };
+ layout.start();
+
+ var encoder = new LayoutWrappingEncoder();
+ encoder.setContext(context);
+ encoder.setLayout(layout);
+ encoder.start();
+
+ var appender = new ConsoleAppender();
+ appender.setContext(context);
+ appender.setName(appenderName);
+ appender.setEncoder(encoder);
+ appender.start();
+
rootLogger.addAppender(appender);
- return true;
+ }
+
+ private Layout console() {
+ var layout = new PatternLayout();
+ layout.setContext(context);
+ layout.setPattern(env(LOGBACK_PATTERN, LOGBACK_PATTERN_DEFAULT));
+ return layout;
+ }
+
+ private Layout json() {
+ var layout = new JsonLayout();
+ layout.setContext(context);
+ return layout;
+ }
+
+ private Layout gcp() {
+ var layout = new GcpJsonLayout();
+ layout.setContext(context);
+ layout.setServiceName(env("SERVICE_NAME", null));
+ layout.setServiceVersion(env("SERVICE_VERSION", null));
+ return layout;
+ }
+
+ private String env(String name, String defaultValue) {
+ var envValue = Optional.ofNullable(System.getenv(name)).map(String::trim).filter(StringUtils::isNotEmpty);
+ var finalValue = envValue.orElse(defaultValue);
+ if (envValue.isPresent()) {
+ addInfo("Use provided config: " + name + "=" + finalValue);
+ } else {
+ addInfo("Use default config: " + name + "=" + finalValue);
+ }
+ return finalValue;
}
}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/http/level/LogLevelServerFilter.java b/src/main/java/io/kokuwa/micronaut/logging/http/level/LogLevelServerFilter.java
index 0e5d07a..6626fee 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/http/level/LogLevelServerFilter.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/http/level/LogLevelServerFilter.java
@@ -3,8 +3,8 @@ package io.kokuwa.micronaut.logging.http.level;
import java.util.Map;
import java.util.Optional;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
import org.reactivestreams.Publisher;
diff --git a/src/main/java/io/kokuwa/micronaut/logging/http/mdc/HeaderMdcFilter.java b/src/main/java/io/kokuwa/micronaut/logging/http/mdc/HeaderMdcFilter.java
index a59b425..a5a8b85 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/http/mdc/HeaderMdcFilter.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/http/mdc/HeaderMdcFilter.java
@@ -3,8 +3,6 @@ package io.kokuwa.micronaut.logging.http.mdc;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
import org.reactivestreams.Publisher;
@@ -33,14 +31,14 @@ public class HeaderMdcFilter extends AbstractMdcFilter {
public static final String PREFIX = "logger.http.header";
public static final int DEFAULT_ORDER = ServerFilterPhase.FIRST.before();
- private final Set headers;
+ private final List headers;
public HeaderMdcFilter(
@Value("${" + PREFIX + ".names}") List headers,
@Value("${" + PREFIX + ".prefix}") Optional prefix,
@Value("${" + PREFIX + ".order}") Optional order) {
super(order.orElse(DEFAULT_ORDER), prefix.orElse(null));
- this.headers = headers.stream().map(String::toLowerCase).collect(Collectors.toSet());
+ this.headers = headers.stream().map(String::toLowerCase).toList();
log.info("Configured with header names {}", headers);
}
@@ -48,9 +46,7 @@ public class HeaderMdcFilter extends AbstractMdcFilter {
public Publisher> doFilter(HttpRequest> request, ServerFilterChain chain) {
var mdc = new HashMap();
for (var header : headers) {
- request.getHeaders()
- .getFirst(header)
- .ifPresent(value -> mdc.put(header, String.valueOf(value)));
+ request.getHeaders().getFirst(header).ifPresent(value -> mdc.put(header, String.valueOf(value)));
}
return doFilter(request, chain, mdc);
}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/layout/GcpJsonLayout.java b/src/main/java/io/kokuwa/micronaut/logging/layout/GcpJsonLayout.java
index 139607c..524601c 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/layout/GcpJsonLayout.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/layout/GcpJsonLayout.java
@@ -1,12 +1,10 @@
package io.kokuwa.micronaut.logging.layout;
import java.time.Instant;
-import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.contrib.json.classic.JsonLayout;
import io.micronaut.core.util.StringUtils;
/**
@@ -44,7 +42,7 @@ public class GcpJsonLayout extends JsonLayout {
private void addServiceContext(Map map) {
if (serviceContext == null) {
- serviceContext = new HashMap<>(2);
+ serviceContext = new LinkedHashMap<>(2);
if (StringUtils.isNotEmpty(serviceName) && !serviceName.endsWith(UNDEFINED)) {
serviceContext.put("service", serviceName);
}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/layout/JsonLayout.java b/src/main/java/io/kokuwa/micronaut/logging/layout/JsonLayout.java
new file mode 100644
index 0000000..4665494
--- /dev/null
+++ b/src/main/java/io/kokuwa/micronaut/logging/layout/JsonLayout.java
@@ -0,0 +1,197 @@
+package io.kokuwa.micronaut.logging.layout;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.TimeZone;
+
+import ch.qos.logback.classic.pattern.ThrowableHandlingConverter;
+import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.CoreConstants;
+import ch.qos.logback.core.LayoutBase;
+import ch.qos.logback.core.status.OnConsoleStatusListener;
+import ch.qos.logback.core.status.StatusUtil;
+import ch.qos.logback.core.util.StatusListenerConfigHelper;
+import io.micronaut.http.MediaType;
+import io.micronaut.json.JsonMapper;
+
+public class JsonLayout extends LayoutBase {
+
+ public static final String TIMESTAMP_ATTR_NAME = "timestamp";
+ public static final String LEVEL_ATTR_NAME = "level";
+ public static final String THREAD_ATTR_NAME = "thread";
+ public static final String MDC_ATTR_NAME = "mdc";
+ public static final String LOGGER_ATTR_NAME = "logger";
+ public static final String FORMATTED_MESSAGE_ATTR_NAME = "message";
+ public static final String MESSAGE_ATTR_NAME = "raw-message";
+ public static final String EXCEPTION_ATTR_NAME = "exception";
+ public static final String CONTEXT_ATTR_NAME = "context";
+
+ protected boolean includeLevel = true;
+ protected boolean includeThreadName = true;
+ protected boolean includeMDC = true;
+ protected boolean includeLoggerName = true;
+ protected boolean includeFormattedMessage = true;
+ protected boolean includeMessage = true;
+ protected boolean includeException = true;
+ protected boolean includeContextName = false;
+ protected boolean includeTimestamp = true;
+ private String timestampFormat;
+ private String timestampFormatTimezoneId;
+ private ThrowableHandlingConverter throwableHandlingConverter = new ThrowableProxyConverter();
+ private JsonMapper mapper;
+
+ @Override
+ public String getContentType() {
+ return MediaType.APPLICATION_JSON;
+ }
+
+ @Override
+ public void start() {
+ this.throwableHandlingConverter.start();
+ super.start();
+ }
+
+ @Override
+ public void stop() {
+ super.stop();
+ this.throwableHandlingConverter.stop();
+ }
+
+ @Override
+ public String doLayout(ILoggingEvent event) {
+ var map = toJsonMap(event);
+
+ if (mapper == null) {
+ try {
+ mapper = JsonMapper.createDefault();
+ } catch (IllegalStateException e) {
+ if (!StatusUtil.contextHasStatusListener(context)) {
+ addError("Failed to get object mapper from micronaut, please check your classpath");
+ StatusListenerConfigHelper.addOnConsoleListenerInstance(context, new OnConsoleStatusListener());
+ }
+ return map.toString() + CoreConstants.LINE_SEPARATOR;
+ }
+ }
+
+ try {
+ return new String(mapper.writeValueAsBytes(map), StandardCharsets.UTF_8) + CoreConstants.LINE_SEPARATOR;
+ } catch (IOException e) {
+ addError("Failed to write json from event " + event + " and map " + map, e);
+ return null;
+ }
+ }
+
+ protected Map toJsonMap(ILoggingEvent event) {
+ var map = new LinkedHashMap();
+ addTimestamp(TIMESTAMP_ATTR_NAME, includeTimestamp, event.getTimeStamp(), map);
+ add(LEVEL_ATTR_NAME, includeLevel, String.valueOf(event.getLevel()), map);
+ add(THREAD_ATTR_NAME, includeThreadName, event.getThreadName(), map);
+ addMap(MDC_ATTR_NAME, includeMDC, event.getMDCPropertyMap(), map);
+ add(LOGGER_ATTR_NAME, includeLoggerName, event.getLoggerName(), map);
+ add(FORMATTED_MESSAGE_ATTR_NAME, includeFormattedMessage, event.getFormattedMessage(), map);
+ add(MESSAGE_ATTR_NAME, includeMessage, event.getMessage(), map);
+ add(CONTEXT_ATTR_NAME, includeContextName, event.getLoggerContextVO().getName(), map);
+ addThrowableInfo(EXCEPTION_ATTR_NAME, includeException, event, map);
+ return map;
+ }
+
+ protected void addThrowableInfo(String fieldName, boolean field, ILoggingEvent value, Map map) {
+ if (field && value != null) {
+ var throwableProxy = value.getThrowableProxy();
+ if (throwableProxy != null) {
+ var ex = throwableHandlingConverter.convert(value);
+ if (ex != null && !ex.isEmpty()) {
+ map.put(fieldName, ex);
+ }
+ }
+ }
+ }
+
+ protected void addMap(String key, boolean field, Map mapValue, Map map) {
+ if (field && mapValue != null && !mapValue.isEmpty()) {
+ map.put(key, mapValue);
+ }
+ }
+
+ protected void addTimestamp(String key, boolean field, long timeStamp, Map map) {
+ if (field) {
+ var formatted = formatTimestamp(timeStamp);
+ if (formatted != null) {
+ map.put(key, formatted);
+ }
+ }
+ }
+
+ protected void add(String fieldName, boolean field, String value, Map map) {
+ if (field && value != null) {
+ map.put(fieldName, value);
+ }
+ }
+
+ protected String formatTimestamp(long timestamp) {
+ if (timestampFormat == null || timestamp < 0) {
+ return String.valueOf(timestamp);
+ }
+ var date = new Date(timestamp);
+ var format = new SimpleDateFormat(timestampFormat);
+ if (timestampFormatTimezoneId != null) {
+ format.setTimeZone(TimeZone.getTimeZone(timestampFormatTimezoneId));
+ }
+ return format.format(date);
+ }
+
+ // setter
+
+ public void setIncludeLevel(boolean includeLevel) {
+ this.includeLevel = includeLevel;
+ }
+
+ public void setIncludeThreadName(boolean includeThreadName) {
+ this.includeThreadName = includeThreadName;
+ }
+
+ public void setIncludeMDC(boolean includeMDC) {
+ this.includeMDC = includeMDC;
+ }
+
+ public void setIncludeLoggerName(boolean includeLoggerName) {
+ this.includeLoggerName = includeLoggerName;
+ }
+
+ public void setIncludeFormattedMessage(boolean includeFormattedMessage) {
+ this.includeFormattedMessage = includeFormattedMessage;
+ }
+
+ public void setIncludeMessage(boolean includeMessage) {
+ this.includeMessage = includeMessage;
+ }
+
+ public void setIncludeException(boolean includeException) {
+ this.includeException = includeException;
+ }
+
+ public void setIncludeContextName(boolean includeContextName) {
+ this.includeContextName = includeContextName;
+ }
+
+ public void setIncludeTimestamp(boolean includeTimestamp) {
+ this.includeTimestamp = includeTimestamp;
+ }
+
+ public void setTimestampFormat(String timestampFormat) {
+ this.timestampFormat = timestampFormat;
+ }
+
+ public void setTimestampFormatTimezoneId(String timestampFormatTimezoneId) {
+ this.timestampFormatTimezoneId = timestampFormatTimezoneId;
+ }
+
+ public void setThrowableHandlingConverter(ThrowableHandlingConverter throwableHandlingConverter) {
+ this.throwableHandlingConverter = throwableHandlingConverter;
+ }
+}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterConfigurer.java b/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterConfigurer.java
index e3abfb4..de87997 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterConfigurer.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterConfigurer.java
@@ -1,5 +1,6 @@
package io.kokuwa.micronaut.logging.mdc;
+import java.util.Collection;
import java.util.Set;
import org.slf4j.Logger;
@@ -11,37 +12,60 @@ import io.micronaut.context.annotation.BootstrapContextCompatible;
import io.micronaut.context.annotation.Context;
import io.micronaut.context.annotation.Requires;
import io.micronaut.context.env.Environment;
-import io.micronaut.core.annotation.Internal;
import io.micronaut.core.type.Argument;
import io.micronaut.core.util.StringUtils;
+import io.micronaut.logging.LogLevel;
+import io.micronaut.logging.LoggingSystem;
/**
* Configure MDC filter.
*
* @author Stephan Schnabel
*/
+@BootstrapContextCompatible
@Requires(beans = LogbackUtil.class)
@Requires(property = MDCTurboFilterConfigurer.PREFIX)
@Requires(property = MDCTurboFilterConfigurer.PREFIX + ".enabled", notEquals = StringUtils.FALSE)
-@BootstrapContextCompatible
@Context
-@Internal
-public class MDCTurboFilterConfigurer {
+public class MDCTurboFilterConfigurer implements LoggingSystem {
public static final String PREFIX = "logger.mdc";
private static final Logger log = LoggerFactory.getLogger(MDCTurboFilterConfigurer.class);
+
private final LogbackUtil logback;
private final Environment environment;
+ private Collection mdcs = Set.of();
+ private boolean initialized;
+
public MDCTurboFilterConfigurer(LogbackUtil logback, Environment environment) {
this.logback = logback;
this.environment = environment;
- configure();
+ this.refresh();
}
- public void configure() {
- for (var name : environment.getPropertyEntries(PREFIX)) {
+ @Override
+ public final void refresh() {
+
+ mdcs = environment.getPropertyEntries(PREFIX);
+ initialized = false;
+
+ if (environment.getProperties("logger.levels").isEmpty()) {
+ log.warn("MDCs are configured, but no levels are set. MDC may not work.");
+ }
+ }
+
+ @Override
+ public void setLogLevel(String name, LogLevel level) {
+ if (!initialized) {
+ configure();
+ initialized = true;
+ }
+ }
+
+ private void configure() {
+ for (var name : mdcs) {
var prefix = PREFIX + "." + name + ".";
var key = environment.getProperty(prefix + "key", String.class, name);
diff --git a/src/main/resources/META-INF/native-image/io.kokuwa.micronaut/micronaut-logging/resource-config.json b/src/main/resources/META-INF/native-image/io.kokuwa.micronaut/micronaut-logging/resource-config.json
index d1dfcab..3a97089 100644
--- a/src/main/resources/META-INF/native-image/io.kokuwa.micronaut/micronaut-logging/resource-config.json
+++ b/src/main/resources/META-INF/native-image/io.kokuwa.micronaut/micronaut-logging/resource-config.json
@@ -1,24 +1,9 @@
{
"resources": {
"includes": [
- {
- "pattern": "\\Qio/kokuwa/logback/appender-console.xml\\E"
- },
- {
- "pattern": "\\Qio/kokuwa/logback/appender-gcp.xml\\E"
- },
- {
- "pattern": "\\Qio/kokuwa/logback/appender-json.xml\\E"
- },
- {
- "pattern": "\\Qio/kokuwa/logback/base.xml\\E"
- },
{
"pattern": "\\Qio/kokuwa/logback/logback-default.xml\\E"
},
- {
- "pattern": "\\Qio/kokuwa/logback/logback-example.xml\\E"
- },
{
"pattern": "\\QMETA-INF/services/ch.qos.logback.classic.spi.Configurator\\E"
}
diff --git a/src/main/resources/io/kokuwa/logback/appender-console.xml b/src/main/resources/io/kokuwa/logback/appender-console.xml
deleted file mode 100644
index e4bfb1d..0000000
--- a/src/main/resources/io/kokuwa/logback/appender-console.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
- ${CONSOLE_LOG_JANSI:-true}
-
- ${CONSOLE_LOG_PATTERN:-%cyan(%d{HH:mm:ss.SSS}) %gray(%-6.6thread) %highlight(%-5level) %magenta(%32logger{32}) %mdc %msg%n}
- ${CONSOLE_LOG_CHARSET:-default}
-
-
-
-
diff --git a/src/main/resources/io/kokuwa/logback/appender-gcp.xml b/src/main/resources/io/kokuwa/logback/appender-gcp.xml
deleted file mode 100644
index e847d99..0000000
--- a/src/main/resources/io/kokuwa/logback/appender-gcp.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
- ${SERVICE_NAME}
- ${SERVICE_VERSION}
-
- true
- true
- false
-
-
-
-
-
diff --git a/src/main/resources/io/kokuwa/logback/appender-json.xml b/src/main/resources/io/kokuwa/logback/appender-json.xml
deleted file mode 100644
index b850ac7..0000000
--- a/src/main/resources/io/kokuwa/logback/appender-json.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
- true
- true
- false
-
-
-
-
-
diff --git a/src/main/resources/io/kokuwa/logback/base.xml b/src/main/resources/io/kokuwa/logback/base.xml
deleted file mode 100644
index 24ae946..0000000
--- a/src/main/resources/io/kokuwa/logback/base.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/src/main/resources/io/kokuwa/logback/logback-default.xml b/src/main/resources/io/kokuwa/logback/logback-default.xml
index 1092ea9..78fe3f0 100644
--- a/src/main/resources/io/kokuwa/logback/logback-default.xml
+++ b/src/main/resources/io/kokuwa/logback/logback-default.xml
@@ -1,8 +1,6 @@
-
-
diff --git a/src/main/resources/io/kokuwa/logback/logback-example.xml b/src/main/resources/io/kokuwa/logback/logback-example.xml
deleted file mode 100644
index 47deab2..0000000
--- a/src/main/resources/io/kokuwa/logback/logback-example.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/test/java/io/kokuwa/micronaut/logging/http/AbstractFilterTest.java b/src/test/java/io/kokuwa/micronaut/logging/http/AbstractFilterTest.java
index ab31e47..4587dcb 100644
--- a/src/test/java/io/kokuwa/micronaut/logging/http/AbstractFilterTest.java
+++ b/src/test/java/io/kokuwa/micronaut/logging/http/AbstractFilterTest.java
@@ -7,19 +7,21 @@ import static org.junit.jupiter.api.Assertions.fail;
import java.util.Map;
import java.util.function.Consumer;
+import jakarta.inject.Inject;
+
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
+import ch.qos.logback.classic.Level;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jwt.JWTClaimsSet;
-
-import ch.qos.logback.classic.Level;
import io.kokuwa.micronaut.logging.AbstractTest;
+import io.micronaut.core.annotation.Nullable;
import io.micronaut.core.util.CollectionUtils;
import io.micronaut.http.HttpHeaderValues;
import io.micronaut.http.HttpRequest;
@@ -34,8 +36,8 @@ import io.micronaut.runtime.server.EmbeddedServer;
import io.micronaut.security.annotation.Secured;
import io.micronaut.security.rules.SecurityRule;
import io.micronaut.security.token.jwt.signature.SignatureGeneratorConfiguration;
+import io.micronaut.serde.annotation.Serdeable;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
-import jakarta.inject.Inject;
/**
* Test for {@link HttpServerFilter}.
@@ -118,6 +120,7 @@ public abstract class AbstractFilterTest extends AbstractTest {
}
}
+ @Serdeable
public static class TestResponse {
private final String path;
@@ -128,7 +131,7 @@ public abstract class AbstractFilterTest extends AbstractTest {
public TestResponse(
@JsonProperty("path") String path,
@JsonProperty("level") String level,
- @JsonProperty("context") Map context) {
+ @Nullable @JsonProperty("context") Map context) {
this.path = path;
this.level = level;
this.context = context == null ? Map.of() : context;
diff --git a/src/test/java/io/kokuwa/micronaut/logging/http/mdc/PathMdcFilterTest.java b/src/test/java/io/kokuwa/micronaut/logging/http/mdc/PathMdcFilterTest.java
index 3654d4d..3b7ac78 100644
--- a/src/test/java/io/kokuwa/micronaut/logging/http/mdc/PathMdcFilterTest.java
+++ b/src/test/java/io/kokuwa/micronaut/logging/http/mdc/PathMdcFilterTest.java
@@ -89,9 +89,9 @@ public class PathMdcFilterTest extends AbstractFilterTest {
@DisplayName("mdc: test for documentation example")
@Test
- @Property(name = "logger.http.path.patterns", value = ""
- + "\\/gateway\\/(?[a-f0-9\\-]{36}),"
- + "\\/gateway\\/(?[a-f0-9\\-]{36})\\/configuration\\/(?[a-z]+)")
+ @Property(name = "logger.http.path.patterns", value = """
+ \\/gateway\\/(?[a-f0-9\\-]{36}),\
+ \\/gateway\\/(?[a-f0-9\\-]{36})\\/configuration\\/(?[a-z]+)""")
void mdcMatchExample() {
var uuid = UUID.randomUUID().toString();
assertContext(Map.of("gatewayId", uuid), "/gateway/" + uuid);
diff --git a/src/test/resources/application-test-mdc.yaml b/src/test/resources/application-test-mdc.yaml
index c0fd2a2..69cbc89 100644
--- a/src/test/resources/application-test-mdc.yaml
+++ b/src/test/resources/application-test-mdc.yaml
@@ -1,4 +1,6 @@
logger:
+ levels:
+ io.micronaut.logging.PropertiesLoggingLevelsConfigurer: "OFF"
mdc:
key1:
key: key