diff --git a/.github/README.md b/.github/README.md deleted file mode 100644 index 8875cce..0000000 --- a/.github/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Micronaut Logging support - -Enhanced logging for Micronaut using MDC or request header. - -[![maven](https://img.shields.io/maven-central/v/io.kokuwa.micronaut/micronaut-logging.svg?label=maven)](https://central.sonatype.com/artifact/io.kokuwa.micronaut/micronaut-logging) -[![license](https://img.shields.io/badge/license-EUPL%201.2-blue)](https://git.kokuwa.io/kokuwaio/micronaut-logging/src/branch/main/LICENSE) -[![issues](https://img.shields.io/gitea/issues/open/kokuwaio/micronaut-logging?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/micronaut-logging/issues) -[![prs](https://img.shields.io/gitea/pull-requests/open/kokuwaio/micronaut-logging?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/micronaut-logging/pulls) -[![build](https://ci.kokuwa.io/api/badges/kokuwaio/micronaut-logging/status.svg)](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/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..35cff56 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,32 @@ +name: Release + +"on": + workflow_dispatch: {} + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + token: ${{ secrets.GIT_ACTION_TOKEN }} + - name: git-configure + run: | + git config user.email "actions@github.com" + git config user.name "GitHub Actions" + - uses: actions/setup-java@v2 + with: + distribution: temurin + java-version: 11 + 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 dependency:go-offline -q + - run: mvn -B release:prepare + - run: mvn -B release:perform + env: + SERVER_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }} + SERVER_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }} + GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} diff --git a/.github/workflows/snapshot.yaml b/.github/workflows/snapshot.yaml new file mode 100644 index 0000000..4414d1c --- /dev/null +++ b/.github/workflows/snapshot.yaml @@ -0,0 +1,54 @@ +name: Build + +"on": + workflow_dispatch: {} + push: {} + +jobs: + + lint-yaml: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: ibiqlik/action-yamllint@v3 + with: + format: colored + strict: true + + lint-markdown: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: docker://avtodev/markdown-lint:v1 + with: + args: /github/workspace + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-java@v2 + with: + distribution: temurin + java-version: 11 + cache: maven + server-id: sonatype-nexus + server-username: SERVER_USERNAME + server-password: SERVER_PASSWORD + - run: mvn -B dependency:go-offline -q + - run: mvn -B verify + if: github.ref != 'refs/heads/main' + - run: mvn -B deploy + if: github.ref == 'refs/heads/main' + env: + SERVER_USERNAME: ${{ secrets.SONATYPE_NEXUS_USERNAME }} + SERVER_PASSWORD: ${{ secrets.SONATYPE_NEXUS_PASSWORD }} + - uses: dorny/test-reporter@v1 + if: failure() + with: + name: surefire + path: '*/target/surefire-reports/*.xml' + reporter: java-junit + list-suites: failed + list-tests: failed + fail-on-error: false diff --git a/.justfile b/.justfile deleted file mode 100644 index 81f407b..0000000 --- a/.justfile +++ /dev/null @@ -1,12 +0,0 @@ -# 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/.markdownlint.yaml b/.markdownlint.yaml index 5f08047..dd23793 100644 --- a/.markdownlint.yaml +++ b/.markdownlint.yaml @@ -1,9 +1,6 @@ # Default state for all rules default: true -# MD009 - Trailing spaces -MD009: - strict: true - -# MD013 - Line length -MD013: false +# MD013/line-length - Line length +MD013: + line_length: 10000 diff --git a/.woodpecker/deploy.yaml b/.woodpecker/deploy.yaml deleted file mode 100644 index 11f903e..0000000 --- a/.woodpecker/deploy.yaml +++ /dev/null @@ -1,16 +0,0 @@ -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 deleted file mode 100644 index 74bb114..0000000 --- a/.woodpecker/lint.yaml +++ /dev/null @@ -1,21 +0,0 @@ -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 deleted file mode 100644 index 57ad1cb..0000000 --- a/.woodpecker/maven/settings.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - 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 deleted file mode 100644 index 21a190e..0000000 --- a/.woodpecker/release.yaml +++ /dev/null @@ -1,29 +0,0 @@ -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 deleted file mode 100644 index 094b317..0000000 --- a/.woodpecker/verify.yaml +++ /dev/null @@ -1,9 +0,0 @@ -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.yaml b/.yamllint similarity index 64% rename from .yamllint.yaml rename to .yamllint index 21966f2..9d1b12e 100644 --- a/.yamllint.yaml +++ b/.yamllint @@ -8,8 +8,3 @@ rules: # line length is not important line-length: disable - - # force double quotes everywhere - quoted-strings: - quote-type: double - required: only-when-needed diff --git a/LICENSE b/LICENSE index dacd3ae..261eeb9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,288 +1,201 @@ - - EUROPEAN UNION PUBLIC LICENCE v. 1.2 - EUPL © the European Union 2007, 2016 - -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). - -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: - - Licensed under the EUPL - -or has expressed by any other means his willingness to license under the EUPL. - -1. Definitions - -In this Licence, the following terms have the following meaning: - -- ‘The Licence’: this Licence. - -- ‘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’: 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. - -- ‘The Work’: the Original Work or its Derivative Works. - -- ‘The Source Code’: the human-readable form of the Work which is the most - convenient for people to study and modify. - -- ‘The Executable Code’: any code which has generally been compiled and which is - meant to be interpreted by a computer as a program. - -- ‘The Licensor’: the natural or legal person that distributes or communicates - the Work under the Licence. - -- ‘Contributor(s)’: any natural or legal person who modifies the Work under the - Licence, or otherwise contributes to the creation of a Derivative Work. - -- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of - the Work under the terms of the Licence. - -- ‘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. - -2. Scope of the rights granted by the Licence - -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: - -- 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. - -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. - -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. - -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. - -3. Communication of the Source Code - -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. - -4. Limitations on copyright - -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. - -5. Obligations of the Licensee - -The grant of the rights mentioned above is subject to some restrictions and -obligations imposed on the Licensee. Those obligations are the following: - -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. - -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. - -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. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "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. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "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. + + "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). + + "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. + + "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." + + "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. + + 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. + + 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. + + 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: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (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 + + (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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + 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. + + Copyright [yyyy] [name of copyright owner] + + 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 + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 4a3a2ec..28fab9b 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,9 @@ # Micronaut Logging support -Enhanced logging for Micronaut using MDC or request header. - -[![maven](https://img.shields.io/maven-central/v/io.kokuwa.micronaut/micronaut-logging.svg?label=maven)](https://central.sonatype.com/artifact/io.kokuwa.micronaut/micronaut-logging) -[![license](https://img.shields.io/badge/license-EUPL%201.2-blue)](https://git.kokuwa.io/kokuwaio/micronaut-logging/src/branch/main/LICENSE) -[![issues](https://img.shields.io/gitea/issues/open/kokuwaio/micronaut-logging?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/micronaut-logging/issues) -[![prs](https://img.shields.io/gitea/pull-requests/open/kokuwaio/micronaut-logging?gitea_url=https%3A%2F%2Fgit.kokuwa.io)](https://git.kokuwa.io/kokuwaio/micronaut-logging/pulls) -[![build](https://ci.kokuwa.io/api/badges/kokuwaio/micronaut-logging/status.svg)](https://ci.kokuwa.io/repos/kokuwaio/micronaut-logging/) - -Include in your `pom.xml`: - -```xml - - io.kokuwa.micronaut - micronaut-logging - ${version.io.kokuwa.micronaut.logging} - runtime - - - - io.micronaut.serde - micronaut-serde-jsonp - runtime - -``` +[![Maven Central](https://img.shields.io/maven-central/v/io.kokuwa.micronaut/micronaut-logging.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22io.kokuwa.micronaut%22%20AND%20a:%22micronaut-logging%22) [![CI](https://github.com/kokuwaio/micronaut-logging/actions/workflows/snapshot.yaml/badge.svg)](https://github.com/kokuwaio/micronaut-logging/actions/workflows/snapshot.yaml) ## Features -* 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) @@ -37,8 +12,13 @@ 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 new file mode 100644 index 0000000..0d2c727 --- /dev/null +++ b/docs/build.md @@ -0,0 +1,23 @@ +# 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/http_mdc_header.md b/docs/features/http_mdc_header.md index 8a8e9d4..db91c1e 100644 --- a/docs/features/http_mdc_header.md +++ b/docs/features/http_mdc_header.md @@ -21,8 +21,8 @@ logger: prefix: header. names: - x-request-id - - x-b3-traceId + - x-b3-traceId - x-b3-parentspanid - x-b3-spanid - - x-b3-sampled + - x-b3-sampled ``` diff --git a/docs/features/logback_appender.md b/docs/features/logback_appender.md index d71885b..1975e8b 100644 --- a/docs/features/logback_appender.md +++ b/docs/features/logback_appender.md @@ -12,3 +12,5 @@ 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 5b34f1a..98ccbc5 100644 --- a/docs/features/logback_default.md +++ b/docs/features/logback_default.md @@ -4,13 +4,15 @@ 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 ee1e853..53887d5 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 22f50e6..9459387 100644 --- a/pom.xml +++ b/pom.xml @@ -1,14 +1,14 @@ - + 4.0.0 io.kokuwa.micronaut micronaut-logging - 5.0.1-SNAPSHOT + 3.0.2 Logging Support for Micronaut Enhanced logging using MDC or request header. - https://git.kokuwa.io/kokuwaio/micronaut-logging + https://github.com/kokuwaio/micronaut-logging 2020 Kokuwa.io @@ -16,58 +16,125 @@ - EUPL-1.2 - https://eupl.eu/1.2/en - repo + Apache License 2.0 + https://www.apache.org/licenses/LICENSE-2.0 - stephan.schnabel + stephanschnabel Stephan Schnabel - https://schnabel.org - stephan@schnabel.org - Europe/Berlin + https://github.com/stephanschnabel + stephan@grayc.de + GrayC GmbH + http://grayc.de - 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 + 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.2 - forgejo - https://git.kokuwa.io/kokuwaio/micronaut-logging/issues + github + https://github.com/kokuwaio/micronaut-logging/issues - woodpecker - https://ci.kokuwa.io/repos/kokuwaio/micronaut-logging + github + https://github.com/kokuwaio/micronaut-logging/actions - sonatype.org - https://central.sonatype.com/repository/maven-snapshots/ + sonatype-nexus + https://oss.sonatype.org/content/repositories/snapshots + + sonatype-nexus + https://oss.sonatype.org/service/local/staging/deploy/maven2 + - 2025-06-27T18:11:48Z + + + + + UTF-8 - 17 + ISO-8859-1 + UTF-8 + + 11 + 11 + true + true + true + + + + + + + + 1.2.10 + 0.1.5 + 3.2.3 + + + + 3.1.0 + 3.8.1 + 3.0.0-M1 + 3.0.1 + 3.0.0-M1 + 3.3.1 + 3.2.0 + 3.0.0-M4 + 3.2.0 + 3.2.1 + 3.0.0-M5 + 1.1.0 + 1.6.8 + + + - io.micronaut.platform - micronaut-platform - 4.9.0 + io.micronaut + micronaut-bom + ${version.io.micronaut} 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} + + @@ -75,7 +142,7 @@ io.micronaut - micronaut-http + micronaut-runtime provided @@ -83,10 +150,6 @@ micronaut-security provided - - io.micronaut.serde - micronaut-serde-api - io.micronaut.test micronaut-test-junit5 @@ -107,57 +170,42 @@ 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 - logback-core + ch.qos.logback.contrib + logback-json-classic + + + ch.qos.logback.contrib + logback-jackson + runtime - verify + + org.apache.maven.plugins + maven-clean-plugin + ${version.org.apache.maven.plugins.clean} + org.apache.maven.plugins maven-compiler-plugin - 3.14.0 + ${version.org.apache.maven.plugins.compiler} - class - true - true - true - -Xlint:all,-processing io.micronaut micronaut-inject-java + ${version.io.micronaut} @@ -165,126 +213,93 @@ org.apache.maven.plugins maven-deploy-plugin - 3.1.4 + ${version.org.apache.maven.plugins.deploy} org.apache.maven.plugins maven-gpg-plugin - 3.2.7 + ${version.org.apache.maven.plugins.gpg} org.apache.maven.plugins maven-install-plugin - 3.1.4 - - - org.apache.maven.plugins - maven-invoker-plugin - 3.9.1 - - - org.apache.maven.plugins - maven-jar-plugin - 3.4.2 + ${version.org.apache.maven.plugins.install} org.apache.maven.plugins maven-javadoc-plugin - 3.11.2 + ${version.org.apache.maven.plugins.javadoc} + + + org.apache.maven.plugins + maven-jar-plugin + ${version.org.apache.maven.plugins.jar} org.apache.maven.plugins maven-release-plugin - 3.1.1 + ${version.org.apache.maven.plugins.release} - verify - check - deploy - deploy,release - true - @{prefix} prepare release @{releaseLabel} [CI SKIP] @{project.version} + release + true org.apache.maven.plugins maven-resources-plugin - 3.3.1 - - ISO-8859-1 - + ${version.org.apache.maven.plugins.resources} org.apache.maven.plugins maven-source-plugin - 3.3.1 + ${version.org.apache.maven.plugins.source} org.apache.maven.plugins maven-surefire-plugin - 3.5.3 + ${version.org.apache.maven.plugins.surefire} + + true + true + org.codehaus.mojo tidy-maven-plugin - 1.4.0 + ${version.org.codehaus.mojo.tidy} - 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.sonatype.plugins + nexus-staging-maven-plugin + ${version.org.sonatype.plugins.nexus-staging} - + org.apache.maven.plugins - maven-invoker-plugin + maven-source-plugin - install - integration-test - verify + jar-no-fork - - ${project.build.directory}/its - true - test - false - true - - + - org.apache.maven.plugins - maven-install-plugin + org.codehaus.mojo + tidy-maven-plugin - default-install - + + check + @@ -294,126 +309,11 @@ - 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 - - + release - - - org.apache.maven.plugins - maven-source-plugin - - - - jar - - - - + org.apache.maven.plugins maven-javadoc-plugin @@ -426,7 +326,7 @@ - + org.apache.maven.plugins maven-gpg-plugin @@ -436,29 +336,28 @@ sign - bc + + + --pinentry-mode + loopback + - - - - - release - - + - org.sonatype.central - central-publishing-maven-plugin + org.sonatype.plugins + nexus-staging-maven-plugin true - sonatype.org - true - published + sonatype-nexus + https://oss.sonatype.org/ + true + diff --git a/renovate.json b/renovate.json deleted file mode 100644 index 4bf0e44..0000000 --- a/renovate.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$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 deleted file mode 100644 index 61186a2..0000000 --- a/src/eclipse/formatter.xml +++ /dev/null @@ -1,404 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/it/invoker.properties b/src/it/invoker.properties deleted file mode 100644 index 7920ff9..0000000 --- a/src/it/invoker.properties +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 46bbf8c..0000000 --- a/src/it/level-from-micronaut/invoker.properties +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index cf36117..0000000 --- a/src/it/level-from-micronaut/pom.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - 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 deleted file mode 100644 index 026881f..0000000 --- a/src/it/level-from-micronaut/postbuild.bsh +++ /dev/null @@ -1,22 +0,0 @@ -// 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 deleted file mode 100644 index f9f63a8..0000000 --- a/src/it/log-gcp-from-env/invoker.properties +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 11f4a92..0000000 --- a/src/it/log-gcp-from-env/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - 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 deleted file mode 100644 index d9e0657..0000000 --- a/src/it/log-gcp-from-env/postbuild.bsh +++ /dev/null @@ -1,21 +0,0 @@ -// 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 deleted file mode 100644 index ec347b6..0000000 --- a/src/it/log-gcp-from-gcloud/invoker.properties +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 0bf33a2..0000000 --- a/src/it/log-gcp-from-gcloud/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - 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 deleted file mode 100644 index d9e0657..0000000 --- a/src/it/log-gcp-from-gcloud/postbuild.bsh +++ /dev/null @@ -1,21 +0,0 @@ -// 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 deleted file mode 100644 index 887fd80..0000000 --- a/src/it/log-gcp-with-service/invoker.properties +++ /dev/null @@ -1,3 +0,0 @@ -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 deleted file mode 100644 index 0f81f40..0000000 --- a/src/it/log-gcp-with-service/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - 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 deleted file mode 100644 index 6264c10..0000000 --- a/src/it/log-gcp-with-service/postbuild.bsh +++ /dev/null @@ -1,21 +0,0 @@ -// 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 deleted file mode 100644 index 08de0de..0000000 --- a/src/it/log-json-from-env-serde-jackson/invoker.properties +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 87283dd..0000000 --- a/src/it/log-json-from-env-serde-jackson/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - 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 deleted file mode 100644 index 0693fe0..0000000 --- a/src/it/log-json-from-env-serde-jackson/postbuild.bsh +++ /dev/null @@ -1,21 +0,0 @@ -// 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 deleted file mode 100644 index 08de0de..0000000 --- a/src/it/log-json-from-env-serde-jsonp/invoker.properties +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 2d0d0ad..0000000 --- a/src/it/log-json-from-env-serde-jsonp/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - 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 deleted file mode 100644 index 0693fe0..0000000 --- a/src/it/log-json-from-env-serde-jsonp/postbuild.bsh +++ /dev/null @@ -1,21 +0,0 @@ -// 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 deleted file mode 100644 index 08de0de..0000000 --- a/src/it/log-json-from-env-serde-missing/invoker.properties +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index fcf06e0..0000000 --- a/src/it/log-json-from-env-serde-missing/pom.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - 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 deleted file mode 100644 index 465b88c..0000000 --- a/src/it/log-json-from-env-serde-missing/postbuild.bsh +++ /dev/null @@ -1,5 +0,0 @@ -// 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 deleted file mode 100644 index 5bba112..0000000 --- a/src/it/log-json-from-kubernetes/invoker.properties +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 20d412c..0000000 --- a/src/it/log-json-from-kubernetes/pom.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - 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 deleted file mode 100644 index 0693fe0..0000000 --- a/src/it/log-json-from-kubernetes/postbuild.bsh +++ /dev/null @@ -1,21 +0,0 @@ -// 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 deleted file mode 100644 index f89c081..0000000 --- a/src/it/log-text/pom.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - 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 deleted file mode 100644 index 40e2f91..0000000 --- a/src/it/log-text/postbuild.bsh +++ /dev/null @@ -1,22 +0,0 @@ -// 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 deleted file mode 100644 index f89c081..0000000 --- a/src/it/logback-xml-custom/pom.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - 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 deleted file mode 100644 index c6a3d94..0000000 --- a/src/it/logback-xml-custom/postbuild.bsh +++ /dev/null @@ -1,21 +0,0 @@ -// 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 deleted file mode 100644 index a704605..0000000 --- a/src/it/logback-xml-custom/src/test/resources/logback.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - %-5level %logger{40} %msg%n - - - - - - - - diff --git a/src/it/pom.xml b/src/it/pom.xml deleted file mode 100644 index d08c441..0000000 --- a/src/it/pom.xml +++ /dev/null @@ -1,122 +0,0 @@ - - - 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 deleted file mode 100644 index 2d8463a..0000000 --- a/src/it/src/test/java/io/kokuwa/micronaut/logging/LoggingTest.java +++ /dev/null @@ -1,13 +0,0 @@ -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 bb21701..df1d6ab 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,6 +21,7 @@ import io.micronaut.context.annotation.Requires; @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 3b1a51a..1d808a9 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,19 +13,13 @@ import ch.qos.logback.core.spi.ContextAwareBase; */ public class DefaultConfigurator extends ContextAwareBase implements Configurator { - @SuppressWarnings("deprecation") @Override - 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; - } + public void configure(LoggerContext loggerContext) { 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 ExecutionStatus.NEUTRAL; + return; } try { @@ -35,9 +29,8 @@ 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; } - return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY; + loggerContext.getLogger("io.micronaut.logging.PropertiesLoggingLevelsConfigurer").setLevel(Level.WARN); } } 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 a1010d7..f89db16 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 addElementSelectorAndActionAssociations(RuleStore rs) { - super.addElementSelectorAndActionAssociations(rs); - rs.addRule(new ElementSelector("configuration/root/autoAppender"), () -> new RootAutoSelectAppenderAction()); + public void addInstanceRules(RuleStore rs) { + super.addInstanceRules(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 1d0db03..b490a35 100644 --- a/src/main/java/io/kokuwa/micronaut/logging/configurator/RootAutoSelectAppenderAction.java +++ b/src/main/java/io/kokuwa/micronaut/logging/configurator/RootAutoSelectAppenderAction.java @@ -1,18 +1,16 @@ package io.kokuwa.micronaut.logging.configurator; -import java.util.Optional; +import java.util.Map; + +import org.xml.sax.Attributes; 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.ConsoleAppender; -import ch.qos.logback.core.Layout; -import ch.qos.logback.core.encoder.LayoutWrappingEncoder; +import ch.qos.logback.core.Appender; import ch.qos.logback.core.joran.action.Action; -import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext; -import io.kokuwa.micronaut.logging.layout.GcpJsonLayout; -import io.kokuwa.micronaut.logging.layout.JsonLayout; +import ch.qos.logback.core.joran.action.ActionConst; +import ch.qos.logback.core.joran.spi.InterpretationContext; import io.micronaut.core.util.StringUtils; /** @@ -29,17 +27,9 @@ 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(SaxEventInterpretationContext ic, String name, org.xml.sax.Attributes attributes) { + public void begin(InterpretationContext ic, String name, Attributes attributes) { var rootLogger = LoggerContext.class.cast(context).getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); var rootLoggerAppenders = rootLogger.iteratorForAppenders(); @@ -48,83 +38,36 @@ public class RootAutoSelectAppenderAction extends Action { return; } - var envAppender = env(LOGBACK_APPENDER, null); - if (envAppender != null) { - setAppender(rootLogger, envAppender); + var envAppender = System.getenv(LOGBACK_APPENDER); + if (envAppender != null && setAppender(ic, rootLogger, envAppender)) { return; } - if (IS_KUBERNETES) { - setAppender(rootLogger, APPENDER_JSON); + if (IS_KUBERNETES && setAppender(ic, rootLogger, APPENDER_JSON)) { return; } - if (IS_GCP) { - setAppender(rootLogger, APPENDER_GCP); + if (IS_GCP && setAppender(ic, rootLogger, APPENDER_GCP)) { return; } - setAppender(rootLogger, APPENDER_CONSOLE); + setAppender(ic, rootLogger, APPENDER_CONSOLE); } @Override - public void end(SaxEventInterpretationContext ic, String name) {} + public void end(InterpretationContext ic, String name) {} - private void setAppender(Logger rootLogger, String appenderName) { - addInfo("Use appender: " + appenderName); + private boolean setAppender(InterpretationContext ic, Logger rootLogger, String 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); - } - - 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); + @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; } - return finalValue; + + addInfo("Use appender: " + appenderName); + rootLogger.addAppender(appender); + return true; } } 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 6626fee..0e5d07a 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 jakarta.annotation.PostConstruct; -import jakarta.annotation.PreDestroy; +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; import org.reactivestreams.Publisher; diff --git a/src/main/java/io/kokuwa/micronaut/logging/http/mdc/AuthenticationMdcFilter.java b/src/main/java/io/kokuwa/micronaut/logging/http/mdc/AuthenticationMdcFilter.java index adc2946..aea7557 100644 --- a/src/main/java/io/kokuwa/micronaut/logging/http/mdc/AuthenticationMdcFilter.java +++ b/src/main/java/io/kokuwa/micronaut/logging/http/mdc/AuthenticationMdcFilter.java @@ -45,7 +45,7 @@ public class AuthenticationMdcFilter extends AbstractMdcFilter { this.name = name.orElse(DEFAULT_NAME); this.attributes = attributes.orElseGet(Set::of); if (name.isPresent() || !this.attributes.isEmpty()) { - log.info("Configured with name {} and attributes {}", this.name, this.attributes); + log.info("Configured with name {} and attributes {}", name, attributes); } } 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 a5a8b85..a59b425 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,6 +3,8 @@ 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; @@ -31,14 +33,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 List headers; + private final Set 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).toList(); + this.headers = headers.stream().map(String::toLowerCase).collect(Collectors.toSet()); log.info("Configured with header names {}", headers); } @@ -46,7 +48,9 @@ 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 524601c..139607c 100644 --- a/src/main/java/io/kokuwa/micronaut/logging/layout/GcpJsonLayout.java +++ b/src/main/java/io/kokuwa/micronaut/logging/layout/GcpJsonLayout.java @@ -1,10 +1,12 @@ 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; /** @@ -42,7 +44,7 @@ public class GcpJsonLayout extends JsonLayout { private void addServiceContext(Map map) { if (serviceContext == null) { - serviceContext = new LinkedHashMap<>(2); + serviceContext = new HashMap<>(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 deleted file mode 100644 index 4665494..0000000 --- a/src/main/java/io/kokuwa/micronaut/logging/layout/JsonLayout.java +++ /dev/null @@ -1,197 +0,0 @@ -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 de87997..e3abfb4 100644 --- a/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterConfigurer.java +++ b/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterConfigurer.java @@ -1,6 +1,5 @@ package io.kokuwa.micronaut.logging.mdc; -import java.util.Collection; import java.util.Set; import org.slf4j.Logger; @@ -12,60 +11,37 @@ 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 -public class MDCTurboFilterConfigurer implements LoggingSystem { +@Internal +public class MDCTurboFilterConfigurer { 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; - this.refresh(); + configure(); } - @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) { + public void configure() { + for (var name : environment.getPropertyEntries(PREFIX)) { 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/native-image.properties b/src/main/resources/META-INF/native-image/io.kokuwa.micronaut/micronaut-logging/native-image.properties deleted file mode 100644 index e1e3f1f..0000000 --- a/src/main/resources/META-INF/native-image/io.kokuwa.micronaut/micronaut-logging/native-image.properties +++ /dev/null @@ -1,2 +0,0 @@ -Args = --initialize-at-build-time=io.kokuwa.micronaut.logging.configurator.RootAutoSelectAppenderAction - 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 deleted file mode 100644 index 3a97089..0000000 --- a/src/main/resources/META-INF/native-image/io.kokuwa.micronaut/micronaut-logging/resource-config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "resources": { - "includes": [ - { - "pattern": "\\Qio/kokuwa/logback/logback-default.xml\\E" - }, - { - "pattern": "\\QMETA-INF/services/ch.qos.logback.classic.spi.Configurator\\E" - } - ] - } -} \ No newline at end of file diff --git a/src/main/resources/io/kokuwa/logback/appender-console.xml b/src/main/resources/io/kokuwa/logback/appender-console.xml new file mode 100644 index 0000000..e4bfb1d --- /dev/null +++ b/src/main/resources/io/kokuwa/logback/appender-console.xml @@ -0,0 +1,12 @@ + + + + + ${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 new file mode 100644 index 0000000..e847d99 --- /dev/null +++ b/src/main/resources/io/kokuwa/logback/appender-gcp.xml @@ -0,0 +1,17 @@ + + + + + + + ${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 new file mode 100644 index 0000000..b850ac7 --- /dev/null +++ b/src/main/resources/io/kokuwa/logback/appender-json.xml @@ -0,0 +1,15 @@ + + + + + + + + true + true + false + + + + + diff --git a/src/main/resources/io/kokuwa/logback/base.xml b/src/main/resources/io/kokuwa/logback/base.xml new file mode 100644 index 0000000..24ae946 --- /dev/null +++ b/src/main/resources/io/kokuwa/logback/base.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/main/resources/io/kokuwa/logback/logback-default.xml b/src/main/resources/io/kokuwa/logback/logback-default.xml index 78fe3f0..1092ea9 100644 --- a/src/main/resources/io/kokuwa/logback/logback-default.xml +++ b/src/main/resources/io/kokuwa/logback/logback-default.xml @@ -1,6 +1,8 @@ + + diff --git a/src/main/resources/io/kokuwa/logback/logback-example.xml b/src/main/resources/io/kokuwa/logback/logback-example.xml new file mode 100644 index 0000000..47deab2 --- /dev/null +++ b/src/main/resources/io/kokuwa/logback/logback-example.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + 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 4587dcb..56b68d0 100644 --- a/src/test/java/io/kokuwa/micronaut/logging/http/AbstractFilterTest.java +++ b/src/test/java/io/kokuwa/micronaut/logging/http/AbstractFilterTest.java @@ -7,21 +7,20 @@ 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.BeforeEach; 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; @@ -36,8 +35,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}. @@ -47,14 +46,24 @@ import io.micronaut.test.extensions.junit5.annotation.MicronautTest; @MicronautTest(rebuildContext = true) public abstract class AbstractFilterTest extends AbstractTest { + private static boolean INIT = false; + @Inject SignatureGeneratorConfiguration signature; @Inject EmbeddedServer embeddedServer; - @DisplayName("0 - trigger rebuild of context") + @DisplayName("0 init") @Test - void rebuild() {} + @BeforeEach + void refresh() { + // https://github.com/micronaut-projects/micronaut-core/issues/5453#issuecomment-864594741 + if (INIT) { + embeddedServer.refresh(); + } else { + INIT = true; + } + } // security @@ -120,7 +129,6 @@ public abstract class AbstractFilterTest extends AbstractTest { } } - @Serdeable public static class TestResponse { private final String path; @@ -131,7 +139,7 @@ public abstract class AbstractFilterTest extends AbstractTest { public TestResponse( @JsonProperty("path") String path, @JsonProperty("level") String level, - @Nullable @JsonProperty("context") Map context) { + @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 3b7ac78..3654d4d 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 69cbc89..c0fd2a2 100644 --- a/src/test/resources/application-test-mdc.yaml +++ b/src/test/resources/application-test-mdc.yaml @@ -1,6 +1,4 @@ logger: - levels: - io.micronaut.logging.PropertiesLoggingLevelsConfigurer: "OFF" mdc: key1: key: key