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.
-
-[](https://central.sonatype.com/artifact/io.kokuwa.micronaut/micronaut-logging)
-[](https://git.kokuwa.io/kokuwaio/micronaut-logging/src/branch/main/LICENSE)
-[](https://git.kokuwa.io/kokuwaio/micronaut-logging/issues)
-[](https://git.kokuwa.io/kokuwaio/micronaut-logging/pulls)
-[](https://ci.kokuwa.io/repos/kokuwaio/micronaut-logging/)
-
-For more documention see: [git.kokuwa.io/kokuwaio/micronaut-logging](https://git.kokuwa.io/kokuwaio/micronaut-logging)
diff --git a/.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
deleted file mode 100644
index 5f08047..0000000
--- a/.markdownlint.yaml
+++ /dev/null
@@ -1,9 +0,0 @@
-# Default state for all rules
-default: true
-
-# MD009 - Trailing spaces
-MD009:
- strict: true
-
-# MD013 - Line length
-MD013: false
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.yaml
deleted file mode 100644
index 21966f2..0000000
--- a/.yamllint.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-extends: default
-
-## see https://yamllint.readthedocs.io/en/stable/rules.html
-rules:
-
- # no need for document start
- document-start: disable
-
- # 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..378e985 100644
--- a/README.md
+++ b/README.md
@@ -1,44 +1,131 @@
# Micronaut Logging support
-Enhanced logging for Micronaut using MDC or request header.
-
-[](https://central.sonatype.com/artifact/io.kokuwa.micronaut/micronaut-logging)
-[](https://git.kokuwa.io/kokuwaio/micronaut-logging/src/branch/main/LICENSE)
-[](https://git.kokuwa.io/kokuwaio/micronaut-logging/issues)
-[](https://git.kokuwa.io/kokuwaio/micronaut-logging/pulls)
-[](https://ci.kokuwa.io/repos/kokuwaio/micronaut-logging/)
-
-Include in your `pom.xml`:
-
-```xml
-
- io.kokuwa.micronaut
- micronaut-logging
- ${version.io.kokuwa.micronaut.logging}
- runtime
-
-
-
- io.micronaut.serde
- micronaut-serde-jsonp
- runtime
-
-```
-
## 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)
-* [set log level based on HTTP request header](docs/features/http_log_level.md)
-* [add HTTP path parts to MDC](docs/features/http_mdc_path.md)
-* [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)
+### Preconfigured Appender
+
+Buildin appender:
+ * console format
+ * stackdriver format (with support for error reporting)
+
+### Set log level based on MDC values
+
+Confguration:
+ * *enabled*: enable MDC filter (`true` is default)
+ * *key*: MDC key, is optional (will use name instead, see example `user` below)
+ * *level*: log level to use (`TRACE` is default)
+ * *loggers*: whitelist of logger names, matches all loggers if empty
+ * *values*: values for matching MDC key, matches all values if empty
+
+Example for setting different values for different values/logger:
+```
+logger:
+ levels:
+ io.kokuwa: INFO
+ mdc:
+ gateway-debug:
+ key: gateway
+ level: DEBUG
+ loggers:
+ - io.kokuwa
+ values:
+ - 6a1bae7f-eb6c-4c81-af9d-dc15396584e2
+ - fb3318f1-2c73-48e9-acd4-a2be3c9f9256
+ gateway-trace:
+ key: gateway
+ level: TRACE
+ loggers:
+ - io.kokuwa
+ - io.micronaut
+ values:
+ - 257802b2-22fe-4dcc-bb99-c1db2a47861f
+```
+
+Example for omiting level and key:
+```
+logger:
+ levels:
+ io.kokuwa: INFO
+ mdc:
+ gateway:
+ loggers:
+ - io.kokuwa
+ values:
+ - 257802b2-22fe-4dcc-bb99-c1db2a47861f
+ - 0a44738b-0c3a-4798-8210-2495485f10b2
+```
+
+Example for minimal configuration:
+```
+logger:
+ levels:
+ io.kokuwa: INFO
+ mdc:
+ user: {}
+```
+
+### Set log level based on HTTP request header
+
+Confguration:
+ * *enabled*: enable HTTP request filter (`true` is default)
+ * *order*: order for [Ordered](https://github.com/micronaut-projects/micronaut-core/blob/master/core/src/main/java/io/micronaut/core/order/Ordered.java) (highest is default)
+ * *pattern*: filter pattern (`/**` is default)
+ * *header*: name of HTTP header (`x-log-level` is default)
+
+Example with default configuration:
+```
+logger:
+ request:
+ header:
+ enabled: true
+ order: -2147483648
+ pattern: /**
+ header: x-log-level
+```
+
+### Add princial for request to MDC
+
+Confguration:
+ * *enabled*: enable HTTP principal filter (`true` is default)
+ * *order*: order for [Ordered](https://github.com/micronaut-projects/micronaut-core/blob/master/core/src/main/java/io/micronaut/core/order/Ordered.java) ([ServerFilterPhase.SECURITY.after()](https://github.com/micronaut-projects/micronaut-core/blob/v2.0.1/http/src/main/java/io/micronaut/http/filter/ServerFilterPhase.java#L54) is default)
+ * *pattern*: filter pattern (`/**` is default)
+ * *key*: name of MDC header (`principal` is default)
+
+Example with default configuration:
+```
+logger:
+ request:
+ principal:
+ enabled: true
+ order: 39250
+ pattern: /**
+ key: principal
+```
+
+## Build & Release
+
+### Dependency updates
+
+Display dependency updates:
+```
+mvn versions:display-property-updates -U
+```
+
+Update dependencies:
+```
+mvn versions:update-properties
+```
+
+### Release locally
+
+Run:
+```
+mvn release:prepare release:perform release:clean -B
+```
## Open Topics
-* configure mdc on refresh event
-* read **serviceName** and **serviceVersion** from yaml
-* support auto select appender with custom `logback.xml`
+ * configure mdc on refresh event
+ * add stackdriver per configuration
+ * add fluent per configuration
+ * read **serviceName** and **serviceVersion** from yaml
diff --git a/docs/features/http_log_level.md b/docs/features/http_log_level.md
deleted file mode 100644
index 59b960d..0000000
--- a/docs/features/http_log_level.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Set log level based on HTTP request header
-
-With this features it is possible to set the log level while processing a request by adding the http header `x-log-level` with value `TRACE`. This log level is propagated to HTTP client requests.
-
-## Properties
-
-Property | Description | Default
--------- | ----------- | -------
-`logger.http.level.enabled` | filter enabled? | `true`
-`logger.http.level.path` | filter path | `/**`
-`logger.http.level.order` | order for [Ordered](https://github.com/micronaut-projects/micronaut-core/blob/v3.2.0/core/src/main/java/io/micronaut/core/order/Ordered.java) | [ServerFilterPhase.FIRST.before()](https://github.com/micronaut-projects/micronaut-core/blob/v3.2.0/http/src/main/java/io/micronaut/http/filter/ServerFilterPhase.java#L34)
-`logger.http.level.header` | name of HTTP header | `x-log-level`
-`logger.http.level.propagation.enabled` | propagation enabled? | `true`
-`logger.http.level.propagation.path` | propagation path | `/**`
-`logger.http.level.propagation.order` | order for [Ordered](https://github.com/micronaut-projects/micronaut-core/blob/v3.2.0/core/src/main/java/io/micronaut/core/order/Ordered.java) | [Order.HIGHEST_PRECEDENCE](https://github.com/micronaut-projects/micronaut-core/blob/v3.2.0/core/src/main/java/io/micronaut/core/order/Ordered.java#L30)
-`logger.http.level.propagation.header` | name of HTTP header | see `logger.http.level.header`
-
-## Examples
-
-Default configuration:
-
-```yaml
-logger:
- http:
- level:
- enabled: true
- order: -1000
- path: /**
- header: x-log-level
- propagation:
- enabled: true
- order: 2147483648
- path: /**
- header: ${logger.http.level.header}
-```
diff --git a/docs/features/http_mdc_authentication.md b/docs/features/http_mdc_authentication.md
deleted file mode 100644
index ff4c4e9..0000000
--- a/docs/features/http_mdc_authentication.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Add authentication information to MDC
-
-This only applies to HTTP requests with successful security authentication.
-
-## Properties
-
-Property | Description | Default
--------- | ----------- | -------
-`logger.http.authentication.enabled` | filter enabled? | `true`
-`logger.http.authentication.path` | filter path | `/**`
-`logger.http.authentication.order` | order for [Ordered](https://github.com/micronaut-projects/micronaut-core/blob/v3.2.0/core/src/main/java/io/micronaut/core/order/Ordered.java) | [ServerFilterPhase.SECURITY.after()](https://github.com/micronaut-projects/micronaut-core/blob/v3.2.0/http/src/main/java/io/micronaut/http/filter/ServerFilterPhase.java#L54)
-`logger.http.authentication.prefix` | prefix to MDC key | ``
-`logger.http.authentication.name` | MDC key of authentication name | `principal`
-`logger.http.authentication.attributes` | authentication attributes to add to MDC, | `[]`
-
-## Examples
-
-Configuration for adding some jwt claims:
-
-```yaml
-logger:
- http:
- authentication:
- prefix: jwt.
- name: sub
- attributes:
- - aud
- - azp
-```
diff --git a/docs/features/http_mdc_header.md b/docs/features/http_mdc_header.md
deleted file mode 100644
index 8a8e9d4..0000000
--- a/docs/features/http_mdc_header.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# Add HTTP headers to MDC
-
-## Properties
-
-Property | Description | Default
--------- | ----------- | -------
-`logger.http.header.enabled` | filter enabled? | `true`
-`logger.http.header.path` | filter path | `/**`
-`logger.http.header.order` | order for [Ordered](https://github.com/micronaut-projects/micronaut-core/blob/v3.2.0/core/src/main/java/io/micronaut/core/order/Ordered.java) | [ServerFilterPhase.FIRST.before()](https://github.com/micronaut-projects/micronaut-core/blob/v3.2.0/http/src/main/java/io/micronaut/http/filter/ServerFilterPhase.java#L34)
-`logger.http.header.prefix` | prefix to MDC key | ``
-`logger.http.header.names` | http header names to add to MDC | `[]`
-
-## Examples
-
-Configuration for b3-propagation:
-
-```yaml
-logger:
- http:
- header:
- prefix: header.
- names:
- - x-request-id
- - x-b3-traceId
- - x-b3-parentspanid
- - x-b3-spanid
- - x-b3-sampled
-```
diff --git a/docs/features/http_mdc_path.md b/docs/features/http_mdc_path.md
deleted file mode 100644
index b5f9f73..0000000
--- a/docs/features/http_mdc_path.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# Add HTTP path parts to MDC
-
-## Properties
-
-Property | Description | Default
--------- | ----------- | -------
-`logger.http.path.enabled` | filter enabled? | `true`
-`logger.http.path.path` | filter path | `/**`
-`logger.http.path.order` | order for [Ordered](https://github.com/micronaut-projects/micronaut-core/blob/v3.2.0/core/src/main/java/io/micronaut/core/order/Ordered.java) | [ServerFilterPhase.FIRST.before()](https://github.com/micronaut-projects/micronaut-core/blob/v3.2.0/http/src/main/java/io/micronaut/http/filter/ServerFilterPhase.java#L34)
-`logger.http.path.prefix` | prefix to MDC key | ``
-`logger.http.path.patterns` | patterns with groups to add to MDC | `[]`
-
-## Examples
-
-Configuration for adding ids:
-
-```yaml
-logger:
- http:
- path:
- prefix: path.
- patterns:
- - \/gateway\/(?[a-f0-9\-]{36})
- - \/gateway\/(?[a-f0-9\-]{36})\/configuration\/(?[a-z]+)
-```
diff --git a/docs/features/logback_appender.md b/docs/features/logback_appender.md
deleted file mode 100644
index d71885b..0000000
--- a/docs/features/logback_appender.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Appender
-
-## Available Appender
-
-* console with jansi for developers
-* gcp logging format (with support for error reporting)
-* json
-
-## AutoSelect appender
-
-1. if `LOGBACK_APPENDER` is set this appender will be used
-2. if GCP is detected gcp appender will be used
-3. if Kubernetes is detected json appender will be used
-4. console appender else
diff --git a/docs/features/logback_default.md b/docs/features/logback_default.md
deleted file mode 100644
index 5b34f1a..0000000
--- a/docs/features/logback_default.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Add default logback.xml
-
-If no `logback.xml` by user is provided a default [logback.xml](../../src/main/resources/io/kokuwa/logback/logback-default.xml) is loaded. Otherwise use custom [logback.xml](../../src/main/resources/io/kokuwa/logback/logback-example.xml):
-
-```xml
-
-
-
-
-
-
-
-
-
-
-```
diff --git a/docs/features/logback_mdc_level.md b/docs/features/logback_mdc_level.md
deleted file mode 100644
index ee1e853..0000000
--- a/docs/features/logback_mdc_level.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# Set log level based on MDC values
-
-This can be used to change the log level based on MDC valus. E.g. change log levels for specific users/services etc.
-
-## Properties
-
-Property | Description | Default
--------- | ----------- | -------
-`logger.mdc.enabled` | MDC enabled? | `true`
-`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 | `[]`
-`logger.mdc..values` | values for matching MDC key, matches all values if empty | `[]`
-
-## Examples
-
-Minimal configuration that logs everything with `TRACE` if MDC `principal` is present:
-
-```yaml
-logger:
- levels:
- io.kokuwa: INFO
- mdc:
- principal: {}
-```
-
-Configuration that logs everything with `TRACE` for logger `io.kokuwa` if MDC `gateway` matches one value:
-
-```yaml
-logger:
- levels:
- io.kokuwa: INFO
- mdc:
- gateway:
- loggers:
- - io.kokuwa
- values:
- - 257802b2-22fe-4dcc-bb99-c1db2a47861f
- - 0a44738b-0c3a-4798-8210-2495485f10b2
-```
-
-Complex example with setting different values for different values/logger:
-
-```yaml
-logger:
- levels:
- io.kokuwa: INFO
- mdc:
- gateway-debug:
- key: gateway
- level: DEBUG
- loggers:
- - io.kokuwa
- values:
- - 6a1bae7f-eb6c-4c81-af9d-dc15396584e2
- - fb3318f1-2c73-48e9-acd4-a2be3c9f9256
- gateway-trace:
- key: gateway
- level: TRACE
- loggers:
- - io.kokuwa
- - io.micronaut
- values:
- - 257802b2-22fe-4dcc-bb99-c1db2a47861f
-```
diff --git a/pom.xml b/pom.xml
index 22f50e6..f4b63d6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,73 +1,80 @@
-
+
4.0.0
+
+ io.kokuwa
+ maven-parent
+ 0.1.0
+
+
+
io.kokuwa.micronaut
micronaut-logging
- 5.0.1-SNAPSHOT
+ 0.0.2
- Logging Support for Micronaut
- Enhanced logging using MDC or request header.
- https://git.kokuwa.io/kokuwaio/micronaut-logging
+ Micronaut Logging Support
+ TODO
+ https://github.com/kokuwaio/micronaut-logging
2020
-
- Kokuwa.io
- http://kokuwa.io
-
- EUPL-1.2
- https://eupl.eu/1.2/en
- repo
+ Apache License 2.0
+ https://www.apache.org/licenses/LICENSE-2.0
-
-
- stephan.schnabel
- Stephan Schnabel
- https://schnabel.org
- stephan@schnabel.org
- Europe/Berlin
-
-
-
- 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
+ 0.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
-
-
-
- sonatype.org
- https://central.sonatype.com/repository/maven-snapshots/
-
-
- 2025-06-27T18:11:48Z
- UTF-8
- 17
+
+
+
+
+
+ 0.1.5
+ 2.0.1
+
+
+
- io.micronaut.platform
- micronaut-platform
- 4.9.0
+ io.micronaut
+ micronaut-bom
+ ${version.io.micronaut}
pom
import
+
+
+
+ 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,18 +82,9 @@
io.micronaut
- micronaut-http
+ micronaut-runtime
provided
-
- io.micronaut.security
- micronaut-security
- provided
-
-
- io.micronaut.serde
- micronaut-serde-api
-
io.micronaut.test
micronaut-test-junit5
@@ -107,360 +105,52 @@
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-jackson
+
+
+ ch.qos.logback.contrib
+ logback-json-classic
- verify
-
-
-
- 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-deploy-plugin
- 3.1.4
-
-
- org.apache.maven.plugins
- maven-gpg-plugin
- 3.2.7
-
-
- 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
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 3.11.2
-
-
- org.apache.maven.plugins
- maven-release-plugin
- 3.1.1
-
- verify
- check
- deploy
- deploy,release
- true
- @{prefix} prepare release @{releaseLabel} [CI SKIP]
- @{project.version}
-
-
-
- org.apache.maven.plugins
- maven-resources-plugin
- 3.3.1
-
- ISO-8859-1
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
- 3.3.1
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
- 3.5.3
-
-
- org.codehaus.mojo
- tidy-maven-plugin
- 1.4.0
-
-
- 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.
-
-
-
-
+
+
+ src/test/resources
+ true
+
+
-
+
org.apache.maven.plugins
- maven-invoker-plugin
-
-
-
- install
- integration-test
- verify
-
-
- ${project.build.directory}/its
- true
- test
- false
- true
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-install-plugin
-
-
- default-install
-
-
-
+ maven-compiler-plugin
+
+
+
+ org.projectlombok
+ lombok
+ ${version.org.projectlombok}
+
+
+ io.micronaut
+ micronaut-inject-java
+ ${version.io.micronaut}
+
+
+
-
-
-
- dev
-
-
- !env.CI
-
-
-
- true
-
-
-
-
- org.codehaus.mojo
- tidy-maven-plugin
-
-
- validate
-
- pom
-
-
-
-
-
- net.revelc.code
- impsort-maven-plugin
-
-
- validate
-
- sort
-
-
-
-
-
- net.revelc.code.formatter
- formatter-maven-plugin
-
-
- validate
-
- format
-
-
-
-
-
-
-
-
- check
-
-
- env.CI
-
-
-
-
-
- org.codehaus.mojo
- tidy-maven-plugin
-
-
- validate
-
- check
-
-
-
-
-
- net.revelc.code
- impsort-maven-plugin
-
-
- validate
-
- check
-
-
-
-
-
- net.revelc.code.formatter
- formatter-maven-plugin
-
-
- validate
-
- validate
-
-
-
-
-
-
-
-
- deploy
-
-
- env.CI
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
-
-
-
- jar
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
-
-
-
- jar
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-gpg-plugin
-
-
-
- sign
-
-
- bc
-
-
-
-
-
-
-
-
-
- release
-
-
-
- org.sonatype.central
- central-publishing-maven-plugin
- true
-
- sonatype.org
- true
- published
-
-
-
-
-
-
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..625191e 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/LogbackUtil.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/LogbackUtil.java
@@ -4,7 +4,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;
-import jakarta.inject.Singleton;
+import javax.inject.Singleton;
import org.slf4j.LoggerFactory;
@@ -12,6 +12,7 @@ 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;
/**
* Utility class for Logback operations.
@@ -21,6 +22,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/layout/GcpJsonLayout.java b/src/main/java/io/kokuwa/micronaut/logging/StackdriverJsonLayout.java
similarity index 62%
rename from src/main/java/io/kokuwa/micronaut/logging/layout/GcpJsonLayout.java
rename to src/main/java/io/kokuwa/micronaut/logging/StackdriverJsonLayout.java
index 524601c..a609ca1 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/layout/GcpJsonLayout.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/StackdriverJsonLayout.java
@@ -1,33 +1,48 @@
-package io.kokuwa.micronaut.logging.layout;
+package io.kokuwa.micronaut.logging;
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.jackson.JacksonJsonFormatter;
+import ch.qos.logback.contrib.json.classic.JsonLayout;
import io.micronaut.core.util.StringUtils;
+import lombok.Getter;
+import lombok.Setter;
/**
- * GCP logging layout.
+ * Stackdriver layout.
*
* @author Stephan Schnabel
* @see "https://cloud.google.com/logging/docs/agent/configuration#process-payload"
* @see "https://cloud.google.com/error-reporting/reference/rest/v1beta1/ServiceContext"
*/
-public class GcpJsonLayout extends JsonLayout {
+@Getter
+@Setter
+public class StackdriverJsonLayout extends JsonLayout {
- private static final String UNDEFINED = "_IS_UNDEFINED";
- private static final String TIME_ATTR_NAME = "time";
+ private static final String TIMESTAMP_ATTR_NAME = "time";
private static final String SEVERITY_ATTR_NAME = "severity";
private Map serviceContext;
private String serviceName;
private String serviceVersion;
+ private boolean includeExceptionInMessage;
+
+ public StackdriverJsonLayout() {
+ appendLineSeparator = true;
+ includeContextName = false;
+ includeMessage = true;
+ includeExceptionInMessage = true;
+ setJsonFormatter(new JacksonJsonFormatter());
+ }
@Override
protected Map toJsonMap(ILoggingEvent event) {
var map = new LinkedHashMap();
- add(TIME_ATTR_NAME, includeTimestamp, Instant.ofEpochMilli(event.getTimeStamp()).toString(), map);
+ add(TIMESTAMP_ATTR_NAME, includeTimestamp, Instant.ofEpochMilli(event.getTimeStamp()).toString(), map);
add(SEVERITY_ATTR_NAME, includeLevel, String.valueOf(event.getLevel()), map);
add(THREAD_ATTR_NAME, includeThreadName, event.getThreadName(), map);
add(CONTEXT_ATTR_NAME, includeContextName, event.getLoggerContextVO().getName(), map);
@@ -35,18 +50,18 @@ public class GcpJsonLayout extends JsonLayout {
addMap(MDC_ATTR_NAME, includeMDC, event.getMDCPropertyMap(), map);
add(FORMATTED_MESSAGE_ATTR_NAME, includeFormattedMessage, event.getFormattedMessage(), map);
add(MESSAGE_ATTR_NAME, includeMessage, event.getMessage(), map);
- addThrowableInfo(EXCEPTION_ATTR_NAME, includeException, event, map);
+ addThrowableInfo(JsonLayout.EXCEPTION_ATTR_NAME, includeException, event, map);
addServiceContext(map);
return map;
}
private void addServiceContext(Map map) {
if (serviceContext == null) {
- serviceContext = new LinkedHashMap<>(2);
- if (StringUtils.isNotEmpty(serviceName) && !serviceName.endsWith(UNDEFINED)) {
+ serviceContext = new HashMap<>(2);
+ if (StringUtils.isNotEmpty(serviceName)) {
serviceContext.put("service", serviceName);
}
- if (StringUtils.isNotEmpty(serviceVersion) && !serviceVersion.endsWith(UNDEFINED)) {
+ if (StringUtils.isNotEmpty(serviceVersion)) {
serviceContext.put("version", serviceVersion);
}
}
@@ -54,12 +69,4 @@ public class GcpJsonLayout extends JsonLayout {
map.put("serviceContext", serviceContext);
}
}
-
- public void setServiceName(String serviceName) {
- this.serviceName = serviceName;
- }
-
- public void setServiceVersion(String serviceVersion) {
- this.serviceVersion = serviceVersion;
- }
}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/configurator/DefaultConfigurator.java b/src/main/java/io/kokuwa/micronaut/logging/configurator/DefaultConfigurator.java
deleted file mode 100644
index 3b1a51a..0000000
--- a/src/main/java/io/kokuwa/micronaut/logging/configurator/DefaultConfigurator.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package io.kokuwa.micronaut.logging.configurator;
-
-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;
-
-/**
- * Use logback-default.xml if no configuration is provided by user.
- *
- * @author Stephan Schnabel
- */
-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;
- }
-
- 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;
- }
-
- try {
- addInfo("Use logback.xml from io.kokuwa:micronaut-logging");
- var configurator = new MicronautJoranConfigurator();
- configurator.setContext(loggerContext);
- 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;
- }
-}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/configurator/MicronautJoranConfigurator.java b/src/main/java/io/kokuwa/micronaut/logging/configurator/MicronautJoranConfigurator.java
deleted file mode 100644
index a1010d7..0000000
--- a/src/main/java/io/kokuwa/micronaut/logging/configurator/MicronautJoranConfigurator.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package io.kokuwa.micronaut.logging.configurator;
-
-import ch.qos.logback.classic.joran.JoranConfigurator;
-import ch.qos.logback.core.joran.spi.ElementSelector;
-import ch.qos.logback.core.joran.spi.RuleStore;
-
-/**
- * Add custom actions.
- *
- * @author Stephan Schnabel
- */
-public class MicronautJoranConfigurator extends JoranConfigurator {
-
- @Override
- public void addElementSelectorAndActionAssociations(RuleStore rs) {
- super.addElementSelectorAndActionAssociations(rs);
- rs.addRule(new ElementSelector("configuration/root/autoAppender"), () -> new RootAutoSelectAppenderAction());
- }
-}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/configurator/RootAutoSelectAppenderAction.java b/src/main/java/io/kokuwa/micronaut/logging/configurator/RootAutoSelectAppenderAction.java
deleted file mode 100644
index 1d0db03..0000000
--- a/src/main/java/io/kokuwa/micronaut/logging/configurator/RootAutoSelectAppenderAction.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package io.kokuwa.micronaut.logging.configurator;
-
-import java.util.Optional;
-
-import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.PatternLayout;
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.ConsoleAppender;
-import ch.qos.logback.core.Layout;
-import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
-import ch.qos.logback.core.joran.action.Action;
-import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext;
-import io.kokuwa.micronaut.logging.layout.GcpJsonLayout;
-import io.kokuwa.micronaut.logging.layout.JsonLayout;
-import io.micronaut.core.util.StringUtils;
-
-/**
- * Auto select appender by environment.
- *
- * @author Stephan Schnabel
- */
-public class RootAutoSelectAppenderAction extends Action {
-
- private static final boolean IS_KUBERNETES = StringUtils.isNotEmpty(System.getenv("KUBERNETES_SERVICE_HOST"));
- private static final boolean IS_GCP = StringUtils.isNotEmpty(System.getenv("GOOGLE_CLOUD_PROJECT"));
-
- private static final String APPENDER_CONSOLE = "CONSOLE";
- 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) {
-
- var rootLogger = LoggerContext.class.cast(context).getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
- var rootLoggerAppenders = rootLogger.iteratorForAppenders();
- if (rootLoggerAppenders.hasNext()) {
- addWarn("Skip because appender already found: " + rootLoggerAppenders.next().getName());
- return;
- }
-
- var envAppender = env(LOGBACK_APPENDER, null);
- if (envAppender != null) {
- setAppender(rootLogger, envAppender);
- return;
- }
-
- if (IS_KUBERNETES) {
- setAppender(rootLogger, APPENDER_JSON);
- return;
- }
- if (IS_GCP) {
- setAppender(rootLogger, APPENDER_GCP);
- return;
- }
- setAppender(rootLogger, APPENDER_CONSOLE);
- }
-
- @Override
- public void end(SaxEventInterpretationContext ic, String name) {}
-
- private void setAppender(Logger rootLogger, String appenderName) {
- addInfo("Use appender: " + appenderName);
-
- var layout = switch (appenderName) {
- case APPENDER_JSON -> json();
- case APPENDER_GCP -> gcp();
- case APPENDER_CONSOLE -> console();
- default -> {
- addError("Appender " + appenderName + " not found. Using console ...");
- yield console();
- }
- };
- layout.start();
-
- var encoder = new LayoutWrappingEncoder();
- encoder.setContext(context);
- encoder.setLayout(layout);
- encoder.start();
-
- var appender = new ConsoleAppender();
- appender.setContext(context);
- appender.setName(appenderName);
- appender.setEncoder(encoder);
- appender.start();
-
- rootLogger.addAppender(appender);
- }
-
- private Layout console() {
- var layout = new PatternLayout();
- layout.setContext(context);
- layout.setPattern(env(LOGBACK_PATTERN, LOGBACK_PATTERN_DEFAULT));
- return layout;
- }
-
- private Layout json() {
- var layout = new JsonLayout();
- layout.setContext(context);
- return layout;
- }
-
- private Layout gcp() {
- var layout = new GcpJsonLayout();
- layout.setContext(context);
- layout.setServiceName(env("SERVICE_NAME", null));
- layout.setServiceVersion(env("SERVICE_VERSION", null));
- return layout;
- }
-
- private String env(String name, String defaultValue) {
- var envValue = Optional.ofNullable(System.getenv(name)).map(String::trim).filter(StringUtils::isNotEmpty);
- var finalValue = envValue.orElse(defaultValue);
- if (envValue.isPresent()) {
- addInfo("Use provided config: " + name + "=" + finalValue);
- } else {
- addInfo("Use default config: " + name + "=" + finalValue);
- }
- return finalValue;
- }
-}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/http/AbstractMdcFilter.java b/src/main/java/io/kokuwa/micronaut/logging/http/AbstractMdcFilter.java
deleted file mode 100644
index b4634be..0000000
--- a/src/main/java/io/kokuwa/micronaut/logging/http/AbstractMdcFilter.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package io.kokuwa.micronaut.logging.http;
-
-import java.util.Map;
-
-import org.reactivestreams.Publisher;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.slf4j.MDC;
-
-import io.micronaut.core.async.publisher.Publishers;
-import io.micronaut.http.HttpRequest;
-import io.micronaut.http.MutableHttpResponse;
-import io.micronaut.http.filter.HttpServerFilter;
-import io.micronaut.http.filter.ServerFilterChain;
-
-/**
- * Base for all MDC related http filters.
- *
- * @author Stephan Schnabel
- */
-public abstract class AbstractMdcFilter implements HttpServerFilter {
-
- protected final Logger log = LoggerFactory.getLogger(getClass());
- protected final int order;
- protected final String prefix;
-
- protected AbstractMdcFilter(Integer order, String prefix) {
- this.order = order;
- this.prefix = prefix;
- }
-
- @Override
- public int getOrder() {
- return order;
- }
-
- protected Publisher> doFilter(
- HttpRequest> request,
- ServerFilterChain chain,
- Map mdc) {
-
- if (mdc.isEmpty()) {
- return chain.proceed(request);
- }
-
- mdc.forEach((key, value) -> MDC.put(addPrefix(key), value));
- return Publishers.map(chain.proceed(request), response -> {
- mdc.keySet().forEach(key -> MDC.remove(addPrefix(key)));
- return response;
- });
- }
-
- private String addPrefix(String key) {
- return prefix == null ? key : prefix + key;
- }
-}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/http/level/LogLevelClientFilter.java b/src/main/java/io/kokuwa/micronaut/logging/http/level/LogLevelClientFilter.java
deleted file mode 100644
index 511829d..0000000
--- a/src/main/java/io/kokuwa/micronaut/logging/http/level/LogLevelClientFilter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package io.kokuwa.micronaut.logging.http.level;
-
-import java.util.Optional;
-
-import org.reactivestreams.Publisher;
-
-import io.micronaut.context.annotation.Requires;
-import io.micronaut.context.annotation.Value;
-import io.micronaut.core.util.StringUtils;
-import io.micronaut.http.HttpResponse;
-import io.micronaut.http.MutableHttpRequest;
-import io.micronaut.http.annotation.Filter;
-import io.micronaut.http.context.ServerRequestContext;
-import io.micronaut.http.filter.ClientFilterChain;
-import io.micronaut.http.filter.HttpClientFilter;
-
-/**
- * Propagates log-level from server request to client.
- *
- * @author Stephan Schnabel
- */
-@Requires(beans = LogLevelServerFilter.class)
-@Requires(property = LogLevelClientFilter.PREFIX + ".enabled", notEquals = StringUtils.FALSE)
-@Filter("${" + LogLevelClientFilter.PREFIX + ".path:/**}")
-public class LogLevelClientFilter implements HttpClientFilter {
-
- public static final String PREFIX = "logger.http.level.propagation";
- public static final int DEFAULT_ORDER = HIGHEST_PRECEDENCE;
-
- private final String serverHeader;
- private final String propagationHeader;
- private final int order;
-
- public LogLevelClientFilter(
- @Value("${" + LogLevelServerFilter.PREFIX + ".header}") Optional serverHeader,
- @Value("${" + PREFIX + ".header}") Optional propagationHeader,
- @Value("${" + PREFIX + ".order}") Optional order) {
- this.serverHeader = serverHeader.orElse(LogLevelServerFilter.DEFAULT_HEADER);
- this.propagationHeader = propagationHeader.orElse(this.serverHeader);
- this.order = order.orElse(DEFAULT_ORDER);
- }
-
- @Override
- public int getOrder() {
- return order;
- }
-
- @Override
- public Publisher extends HttpResponse>> doFilter(MutableHttpRequest> targetRequest, ClientFilterChain chain) {
- ServerRequestContext.currentRequest()
- .flatMap(currentRequest -> currentRequest.getHeaders().getFirst(serverHeader))
- .ifPresent(level -> targetRequest.getHeaders().add(propagationHeader, level));
- return chain.proceed(targetRequest);
- }
-}
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
deleted file mode 100644
index 6626fee..0000000
--- a/src/main/java/io/kokuwa/micronaut/logging/http/level/LogLevelServerFilter.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package io.kokuwa.micronaut.logging.http.level;
-
-import java.util.Map;
-import java.util.Optional;
-
-import jakarta.annotation.PostConstruct;
-import jakarta.annotation.PreDestroy;
-
-import org.reactivestreams.Publisher;
-
-import ch.qos.logback.classic.turbo.TurboFilter;
-import io.kokuwa.micronaut.logging.LogbackUtil;
-import io.kokuwa.micronaut.logging.http.AbstractMdcFilter;
-import io.micronaut.context.annotation.Requires;
-import io.micronaut.context.annotation.Value;
-import io.micronaut.core.util.StringUtils;
-import io.micronaut.http.HttpRequest;
-import io.micronaut.http.MutableHttpResponse;
-import io.micronaut.http.annotation.Filter;
-import io.micronaut.http.filter.ServerFilterChain;
-import io.micronaut.http.filter.ServerFilterPhase;
-import io.micronaut.runtime.context.scope.Refreshable;
-
-/**
- * Http request logging filter.
- *
- * @author Stephan Schnabel
- */
-@Refreshable
-@Requires(property = LogLevelServerFilter.PREFIX + ".enabled", notEquals = StringUtils.FALSE)
-@Filter("${" + LogLevelServerFilter.PREFIX + ".path:/**}")
-public class LogLevelServerFilter extends AbstractMdcFilter {
-
- public static final String PREFIX = "logger.http.level";
- public static final String DEFAULT_HEADER = "x-log-level";
- public static final int DEFAULT_ORDER = ServerFilterPhase.FIRST.before();
- public static final String MDC_KEY = "level";
- public static final String MDC_FILTER = PREFIX;
-
- private final LogbackUtil logback;
- private final String header;
-
- public LogLevelServerFilter(
- LogbackUtil logback,
- @Value("${" + PREFIX + ".header}") Optional header,
- @Value("${" + PREFIX + ".order}") Optional order) {
- super(order.orElse(DEFAULT_ORDER), null);
- this.logback = logback;
- this.header = header.orElse(DEFAULT_HEADER);
- }
-
- @PostConstruct
- void startTurbofilter() {
- logback.getTurboFilter(LogLevelTurboFilter.class, MDC_FILTER, LogLevelTurboFilter::new).start();
- }
-
- @PreDestroy
- void stopTurbofilter() {
- logback.getTurboFilter(LogLevelTurboFilter.class, MDC_FILTER).ifPresent(TurboFilter::stop);
- }
-
- @Override
- public Publisher> doFilter(HttpRequest> request, ServerFilterChain chain) {
- return request.getHeaders().getFirst(header)
- .map(level -> doFilter(request, chain, Map.of(MDC_KEY, level)))
- .orElseGet(() -> chain.proceed(request));
- }
-}
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
deleted file mode 100644
index adc2946..0000000
--- a/src/main/java/io/kokuwa/micronaut/logging/http/mdc/AuthenticationMdcFilter.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package io.kokuwa.micronaut.logging.http.mdc;
-
-import java.util.HashMap;
-import java.util.Optional;
-import java.util.Set;
-
-import org.reactivestreams.Publisher;
-
-import io.kokuwa.micronaut.logging.http.AbstractMdcFilter;
-import io.micronaut.context.annotation.Requires;
-import io.micronaut.context.annotation.Value;
-import io.micronaut.core.util.StringUtils;
-import io.micronaut.http.HttpRequest;
-import io.micronaut.http.MutableHttpResponse;
-import io.micronaut.http.annotation.Filter;
-import io.micronaut.http.filter.ServerFilterChain;
-import io.micronaut.http.filter.ServerFilterPhase;
-import io.micronaut.runtime.context.scope.Refreshable;
-import io.micronaut.security.authentication.Authentication;
-
-/**
- * Filter to add claims from authentication to MDC.
- *
- * @author Stephan Schnabel
- */
-@Refreshable
-@Requires(classes = Authentication.class)
-@Requires(property = AuthenticationMdcFilter.PREFIX + ".enabled", notEquals = StringUtils.FALSE)
-@Filter("${" + AuthenticationMdcFilter.PREFIX + ".path:/**}")
-public class AuthenticationMdcFilter extends AbstractMdcFilter {
-
- public static final String PREFIX = "logger.http.authentication";
- public static final String DEFAULT_NAME = "principal";
- public static final int DEFAULT_ORDER = ServerFilterPhase.SECURITY.after();
-
- private final String name;
- private final Set attributes;
-
- public AuthenticationMdcFilter(
- @Value("${" + PREFIX + ".name}") Optional name,
- @Value("${" + PREFIX + ".attributes}") Optional> attributes,
- @Value("${" + PREFIX + ".prefix}") Optional prefix,
- @Value("${" + PREFIX + ".order}") Optional order) {
- super(order.orElse(DEFAULT_ORDER), prefix.orElse(null));
- 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);
- }
- }
-
- @Override
- public Publisher> doFilter(HttpRequest> request, ServerFilterChain chain) {
-
- // get authentication
-
- var authenticationOptional = request.getUserPrincipal(Authentication.class);
- if (authenticationOptional.isEmpty()) {
- return chain.proceed(request);
- }
- var authentication = authenticationOptional.get();
- var authenticationAttributes = authentication.getAttributes();
-
- // add mdc
-
- var mdc = new HashMap();
- mdc.put(name, authentication.getName());
- for (var attibuteName : attributes) {
- var attibuteValue = authenticationAttributes.get(attibuteName);
- if (attibuteValue != null) {
- mdc.put(attibuteName, String.valueOf(attibuteValue));
- }
- }
-
- return doFilter(request, chain, mdc);
- }
-}
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
deleted file mode 100644
index a5a8b85..0000000
--- a/src/main/java/io/kokuwa/micronaut/logging/http/mdc/HeaderMdcFilter.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package io.kokuwa.micronaut.logging.http.mdc;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Optional;
-
-import org.reactivestreams.Publisher;
-
-import io.kokuwa.micronaut.logging.http.AbstractMdcFilter;
-import io.micronaut.context.annotation.Requires;
-import io.micronaut.context.annotation.Value;
-import io.micronaut.core.util.StringUtils;
-import io.micronaut.http.HttpRequest;
-import io.micronaut.http.MutableHttpResponse;
-import io.micronaut.http.annotation.Filter;
-import io.micronaut.http.filter.ServerFilterChain;
-import io.micronaut.http.filter.ServerFilterPhase;
-import io.micronaut.runtime.context.scope.Refreshable;
-
-/**
- * Filter to add http headers to MDC.
- *
- * @author Stephan Schnabel
- */
-@Refreshable
-@Requires(property = HeaderMdcFilter.PREFIX + ".enabled", notEquals = StringUtils.FALSE)
-@Requires(property = HeaderMdcFilter.PREFIX + ".names")
-@Filter("${" + HeaderMdcFilter.PREFIX + ".path:/**}")
-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;
-
- 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();
- log.info("Configured with header names {}", headers);
- }
-
- @Override
- 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)));
- }
- return doFilter(request, chain, mdc);
- }
-}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/http/mdc/PathMdcFilter.java b/src/main/java/io/kokuwa/micronaut/logging/http/mdc/PathMdcFilter.java
deleted file mode 100644
index 848e34d..0000000
--- a/src/main/java/io/kokuwa/micronaut/logging/http/mdc/PathMdcFilter.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package io.kokuwa.micronaut.logging.http.mdc;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
-import org.reactivestreams.Publisher;
-
-import io.kokuwa.micronaut.logging.http.AbstractMdcFilter;
-import io.micronaut.context.annotation.Requires;
-import io.micronaut.context.annotation.Value;
-import io.micronaut.core.util.StringUtils;
-import io.micronaut.http.HttpRequest;
-import io.micronaut.http.MutableHttpResponse;
-import io.micronaut.http.annotation.Filter;
-import io.micronaut.http.filter.ServerFilterChain;
-import io.micronaut.http.filter.ServerFilterPhase;
-import io.micronaut.runtime.context.scope.Refreshable;
-
-/**
- * Filter to add request path parts to MDC.
- *
- * @author Stephan Schnabel
- */
-@Refreshable
-@Requires(property = PathMdcFilter.PREFIX + ".enabled", notEquals = StringUtils.FALSE)
-@Requires(property = PathMdcFilter.PREFIX + ".patterns")
-@Filter("${" + PathMdcFilter.PREFIX + ".path:/**}")
-public class PathMdcFilter extends AbstractMdcFilter {
-
- public static final String PREFIX = "logger.http.path";
- public static final int DEFAULT_ORDER = ServerFilterPhase.FIRST.before();
- public static final Pattern PATTERN_GROUPS = Pattern.compile("\\(\\?<([a-zA-Z][a-zA-Z0-9]+)>");
-
- private final Map> patternsWithGroups;
-
- public PathMdcFilter(
- @Value("${" + PREFIX + ".patterns}") List patterns,
- @Value("${" + PREFIX + ".prefix}") Optional prefix,
- @Value("${" + PREFIX + ".order}") Optional order) {
- super(order.orElse(DEFAULT_ORDER), prefix.orElse(null));
- this.patternsWithGroups = new HashMap<>();
- for (var patternString : patterns) {
- try {
- var pattern = Pattern.compile(patternString);
- var groupMatcher = PATTERN_GROUPS.matcher(pattern.toString());
- var groups = new HashSet();
- while (groupMatcher.find()) {
- groups.add(groupMatcher.group(1));
- }
-
- if (groups.isEmpty()) {
- log.warn("Path {} is missing groups.", patternString);
- } else {
- log.info("Added path {} with groups {}.", patternString, groups);
- patternsWithGroups.put(pattern, groups);
- }
- } catch (PatternSyntaxException e) {
- log.warn("Path {} is invalid.", patternString);
- }
- }
- }
-
- @Override
- public Publisher> doFilter(HttpRequest> request, ServerFilterChain chain) {
-
- var mdc = new HashMap();
- var path = request.getPath();
-
- for (var patternWithGroup : patternsWithGroups.entrySet()) {
- var matcher = patternWithGroup.getKey().matcher(path);
- if (matcher.matches()) {
- for (var group : patternWithGroup.getValue()) {
- mdc.put(group, matcher.group(group));
- }
- }
- }
-
- return doFilter(request, chain, mdc);
- }
-}
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/MDCTurboFilter.java b/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilter.java
index db4d805..c6f01b1 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilter.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilter.java
@@ -50,13 +50,7 @@ public class MDCTurboFilter extends TurboFilter {
}
@Override
- public FilterReply decide(
- Marker marker,
- Logger logger,
- Level eventLevel,
- String format,
- Object[] params,
- Throwable t) {
+ public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
if (logger == null || !isStarted()) {
return FilterReply.NEUTRAL;
@@ -73,6 +67,6 @@ public class MDCTurboFilter extends TurboFilter {
return FilterReply.NEUTRAL;
}
- return eventLevel.isGreaterOrEqual(this.level) ? FilterReply.ACCEPT : FilterReply.NEUTRAL;
+ return level.isGreaterOrEqual(this.level) ? FilterReply.ACCEPT : FilterReply.NEUTRAL;
}
}
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..300b57e 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterConfigurer.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterConfigurer.java
@@ -1,71 +1,45 @@
package io.kokuwa.micronaut.logging.mdc;
-import java.util.Collection;
import java.util.Set;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import ch.qos.logback.classic.Level;
import io.kokuwa.micronaut.logging.LogbackUtil;
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;
+import lombok.extern.slf4j.Slf4j;
/**
* Configure MDC filter.
*
* @author Stephan Schnabel
*/
-@BootstrapContextCompatible
@Requires(beans = LogbackUtil.class)
@Requires(property = MDCTurboFilterConfigurer.PREFIX)
-@Requires(property = MDCTurboFilterConfigurer.PREFIX + ".enabled", notEquals = StringUtils.FALSE)
+@Requires(property = MDCTurboFilterConfigurer.ENABLED, notEquals = "false")
+@BootstrapContextCompatible
@Context
-public class MDCTurboFilterConfigurer implements LoggingSystem {
+@Internal
+@Slf4j
+public class MDCTurboFilterConfigurer {
public static final String PREFIX = "logger.mdc";
-
- private static final Logger log = LoggerFactory.getLogger(MDCTurboFilterConfigurer.class);
+ public static final String ENABLED = PREFIX + ".enabled";
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/java/io/kokuwa/micronaut/logging/request/HeaderLoggingHttpFilter.java b/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingHttpFilter.java
new file mode 100644
index 0000000..bed5fae
--- /dev/null
+++ b/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingHttpFilter.java
@@ -0,0 +1,75 @@
+package io.kokuwa.micronaut.logging.request;
+
+import java.util.Optional;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.reactivestreams.Publisher;
+import org.slf4j.MDC;
+
+import ch.qos.logback.classic.turbo.TurboFilter;
+import io.kokuwa.micronaut.logging.LogbackUtil;
+import io.micronaut.context.annotation.Requires;
+import io.micronaut.context.annotation.Value;
+import io.micronaut.http.HttpRequest;
+import io.micronaut.http.MutableHttpResponse;
+import io.micronaut.http.annotation.Filter;
+import io.micronaut.http.filter.HttpServerFilter;
+import io.micronaut.http.filter.ServerFilterChain;
+import io.micronaut.http.filter.ServerFilterPhase;
+import io.micronaut.runtime.server.EmbeddedServer;
+
+/**
+ * Http request logging filter.
+ *
+ * @author Stephan Schnabel
+ */
+@Requires(beans = EmbeddedServer.class)
+@Requires(property = HeaderLoggingHttpFilter.ENABLED, notEquals = "false")
+@Filter("${" + HeaderLoggingHttpFilter.PREFIX + ".pattern:" + HeaderLoggingHttpFilter.DEFAULT_PATTERN + ":/**}")
+public class HeaderLoggingHttpFilter implements HttpServerFilter {
+
+ public static final String PREFIX = "logger.request.header";
+ public static final String ENABLED = PREFIX + ".enabled";
+ public static final String MDC_FILTER = PREFIX + ".filter";
+ public static final String MDC_KEY = "level";
+
+ public static final String DEFAULT_HEADER = "x-log-level";
+ public static final String DEFAULT_PATTERN = "/**";
+ public static final int DEFAULT_ORDER = ServerFilterPhase.FIRST.before();
+
+ private final LogbackUtil logback;
+ private final String header;
+ private final int order;
+
+ public HeaderLoggingHttpFilter(
+ LogbackUtil logback,
+ @Value("${" + PREFIX + ".header:" + DEFAULT_HEADER + "}") String header,
+ @Value("${" + PREFIX + ".order}") Optional order) {
+ this.logback = logback;
+ this.header = header;
+ this.order = order.orElse(DEFAULT_ORDER);
+ }
+
+ @PostConstruct
+ void startTurbofilter() {
+ logback.getTurboFilter(HeaderLoggingTurboFilter.class, MDC_FILTER, HeaderLoggingTurboFilter::new).start();
+ }
+
+ @PreDestroy
+ void stopTurbofilter() {
+ logback.getTurboFilter(HeaderLoggingTurboFilter.class, MDC_FILTER).ifPresent(TurboFilter::stop);
+ }
+
+ @Override
+ public int getOrder() {
+ return order;
+ }
+
+ @Override
+ public Publisher> doFilter(HttpRequest> request, ServerFilterChain chain) {
+ request.getHeaders().getFirst(header).ifPresent(level -> MDC.put(MDC_KEY, level));
+ return chain.proceed(request);
+ }
+}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/http/level/LogLevelTurboFilter.java b/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingTurboFilter.java
similarity index 80%
rename from src/main/java/io/kokuwa/micronaut/logging/http/level/LogLevelTurboFilter.java
rename to src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingTurboFilter.java
index 57df67f..17e42ea 100644
--- a/src/main/java/io/kokuwa/micronaut/logging/http/level/LogLevelTurboFilter.java
+++ b/src/main/java/io/kokuwa/micronaut/logging/request/HeaderLoggingTurboFilter.java
@@ -1,4 +1,4 @@
-package io.kokuwa.micronaut.logging.http.level;
+package io.kokuwa.micronaut.logging.request;
import org.slf4j.MDC;
import org.slf4j.Marker;
@@ -13,7 +13,7 @@ import ch.qos.logback.core.spi.FilterReply;
*
* @author Stephan Schnabel
*/
-public class LogLevelTurboFilter extends TurboFilter {
+public class HeaderLoggingTurboFilter extends TurboFilter {
@Override
public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
@@ -22,7 +22,7 @@ public class LogLevelTurboFilter extends TurboFilter {
return FilterReply.NEUTRAL;
}
- var value = MDC.get(LogLevelServerFilter.MDC_KEY);
+ var value = MDC.get(HeaderLoggingHttpFilter.MDC_KEY);
if (value == null) {
return FilterReply.NEUTRAL;
}
diff --git a/src/main/java/io/kokuwa/micronaut/logging/request/PrincipalHttpFilter.java b/src/main/java/io/kokuwa/micronaut/logging/request/PrincipalHttpFilter.java
new file mode 100644
index 0000000..80848e2
--- /dev/null
+++ b/src/main/java/io/kokuwa/micronaut/logging/request/PrincipalHttpFilter.java
@@ -0,0 +1,55 @@
+package io.kokuwa.micronaut.logging.request;
+
+import java.util.Optional;
+
+import org.reactivestreams.Publisher;
+import org.slf4j.MDC;
+
+import io.micronaut.context.annotation.Requires;
+import io.micronaut.context.annotation.Value;
+import io.micronaut.http.HttpRequest;
+import io.micronaut.http.MutableHttpResponse;
+import io.micronaut.http.annotation.Filter;
+import io.micronaut.http.filter.HttpServerFilter;
+import io.micronaut.http.filter.ServerFilterChain;
+import io.micronaut.http.filter.ServerFilterPhase;
+import io.micronaut.runtime.server.EmbeddedServer;
+
+/**
+ * Http request principal filter.
+ *
+ * @author Stephan Schnabel
+ */
+@Requires(beans = EmbeddedServer.class)
+@Requires(property = PrincipalHttpFilter.ENABLED, notEquals = "false")
+@Filter("${" + PrincipalHttpFilter.PREFIX + ".pattern:" + PrincipalHttpFilter.DEFAULT_PATTERN + ":/**}")
+public class PrincipalHttpFilter implements HttpServerFilter {
+
+ public static final String PREFIX = "logger.request.principal";
+ public static final String ENABLED = PREFIX + ".enabled";
+
+ public static final String DEFAULT_KEY = "principal";
+ public static final String DEFAULT_PATTERN = "/**";
+ public static final int DEFAULT_ORDER = ServerFilterPhase.SECURITY.after();
+
+ private final String key;
+ private final int order;
+
+ public PrincipalHttpFilter(
+ @Value("${" + PREFIX + ".key:" + DEFAULT_KEY + "}") String key,
+ @Value("${" + PREFIX + ".order}") Optional order) {
+ this.key = key;
+ this.order = order.orElse(DEFAULT_ORDER);
+ }
+
+ @Override
+ public int getOrder() {
+ return order;
+ }
+
+ @Override
+ public Publisher> doFilter(HttpRequest> request, ServerFilterChain chain) {
+ request.getUserPrincipal().ifPresent(princial -> MDC.put(key, princial.getName()));
+ return chain.proceed(request);
+ }
+}
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/META-INF/services/ch.qos.logback.classic.spi.Configurator b/src/main/resources/META-INF/services/ch.qos.logback.classic.spi.Configurator
deleted file mode 100644
index 1f9f2da..0000000
--- a/src/main/resources/META-INF/services/ch.qos.logback.classic.spi.Configurator
+++ /dev/null
@@ -1 +0,0 @@
-io.kokuwa.micronaut.logging.configurator.DefaultConfigurator
diff --git a/src/main/resources/io/kokuwa/logback/logback-default.xml b/src/main/resources/io/kokuwa/logback/logback-default.xml
deleted file mode 100644
index 78fe3f0..0000000
--- a/src/main/resources/io/kokuwa/logback/logback-default.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000..42a34f7
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+ true
+
+ %cyan(%d{HH:mm:ss.SSS}) %gray(%-6.6thread) %highlight(%-5level) %magenta(%32logger{32}) %mdc %msg%n
+
+
+
+
+
+ ${serviceName}
+ ${serviceVersion}
+
+
+
+
+
+
+
+
+
diff --git a/src/test/java/io/kokuwa/micronaut/logging/AbstractTest.java b/src/test/java/io/kokuwa/micronaut/logging/AbstractTest.java
index ebcc5e7..f63e4c2 100644
--- a/src/test/java/io/kokuwa/micronaut/logging/AbstractTest.java
+++ b/src/test/java/io/kokuwa/micronaut/logging/AbstractTest.java
@@ -2,11 +2,11 @@ package io.kokuwa.micronaut.logging;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.MethodOrderer.Alphanumeric;
import org.junit.jupiter.api.TestMethodOrder;
import org.slf4j.MDC;
-import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
+import io.micronaut.test.annotation.MicronautTest;
/**
* Base for tests regarding logging.
@@ -14,7 +14,7 @@ import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
* @author Stephan Schnabel
*/
@MicronautTest
-@TestMethodOrder(MethodOrderer.DisplayName.class)
+@TestMethodOrder(Alphanumeric.class)
public abstract class AbstractTest {
@BeforeEach
diff --git a/src/test/java/io/kokuwa/micronaut/logging/http/AbstractFilterTest.java b/src/test/java/io/kokuwa/micronaut/logging/http/AbstractFilterTest.java
deleted file mode 100644
index 4587dcb..0000000
--- a/src/test/java/io/kokuwa/micronaut/logging/http/AbstractFilterTest.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package io.kokuwa.micronaut.logging.http;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-
-import java.util.Map;
-import java.util.function.Consumer;
-
-import jakarta.inject.Inject;
-
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.slf4j.MDC;
-
-import ch.qos.logback.classic.Level;
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.nimbusds.jose.JOSEException;
-import com.nimbusds.jwt.JWTClaimsSet;
-import 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;
-import io.micronaut.http.HttpStatus;
-import io.micronaut.http.annotation.Controller;
-import io.micronaut.http.annotation.Get;
-import io.micronaut.http.annotation.PathVariable;
-import io.micronaut.http.client.DefaultHttpClientConfiguration;
-import io.micronaut.http.client.HttpClient;
-import io.micronaut.http.filter.HttpServerFilter;
-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;
-
-/**
- * Test for {@link HttpServerFilter}.
- *
- * @author Stephan Schnabel
- */
-@MicronautTest(rebuildContext = true)
-public abstract class AbstractFilterTest extends AbstractTest {
-
- @Inject
- SignatureGeneratorConfiguration signature;
- @Inject
- EmbeddedServer embeddedServer;
-
- @DisplayName("0 - trigger rebuild of context")
- @Test
- void rebuild() {}
-
- // security
-
- public String token(String subject) {
- return token(subject, claims -> {});
- }
-
- public String token(String subject, Consumer manipulator) {
- var claims = new JWTClaimsSet.Builder().subject(subject);
- manipulator.accept(claims);
- try {
- return HttpHeaderValues.AUTHORIZATION_PREFIX_BEARER + " " + signature.sign(claims.build()).serialize();
- } catch (JOSEException e) {
- fail(e);
- return null;
- }
- }
-
- // request
-
- public TestResponse get(String path, Map headers) {
-
- var request = HttpRequest.GET(path);
- headers.forEach((name, value) -> request.header(name, value));
- var configuration = new DefaultHttpClientConfiguration();
- configuration.setLoggerName("io.kokuwa.TestClient");
- var response = HttpClient
- .create(embeddedServer.getURL(), configuration)
- .toBlocking().exchange(request, TestResponse.class);
- assertEquals(HttpStatus.OK, response.getStatus(), "status");
- assertTrue(response.getBody().isPresent(), "body");
- assertTrue(CollectionUtils.isEmpty(MDC.getCopyOfContextMap()), "mdc leaked: " + MDC.getCopyOfContextMap());
-
- return response.body();
- }
-
- @Secured({ SecurityRule.IS_ANONYMOUS, SecurityRule.IS_AUTHENTICATED })
- @Controller
- public static class TestController {
-
- private static final Logger log = LoggerFactory.getLogger(TestController.class);
-
- @Get("/{+path}")
- TestResponse run(@PathVariable String path) {
-
- var level = Level.OFF;
- if (log.isTraceEnabled()) {
- level = Level.TRACE;
- } else if (log.isDebugEnabled()) {
- level = Level.DEBUG;
- } else if (log.isInfoEnabled()) {
- level = Level.INFO;
- } else if (log.isWarnEnabled()) {
- level = Level.WARN;
- } else if (log.isErrorEnabled()) {
- level = Level.ERROR;
- }
-
- var mdc = MDC.getCopyOfContextMap();
- log.info("Found MDC: {}", mdc);
-
- return new TestResponse(path, level.toString(), mdc);
- }
- }
-
- @Serdeable
- public static class TestResponse {
-
- private final String path;
- private final String level;
- private final Map context;
-
- @JsonCreator
- public TestResponse(
- @JsonProperty("path") String path,
- @JsonProperty("level") String level,
- @Nullable @JsonProperty("context") Map context) {
- this.path = path;
- this.level = level;
- this.context = context == null ? Map.of() : context;
- }
-
- public String getPath() {
- return path;
- }
-
- public String getLevel() {
- return level;
- }
-
- public Map getContext() {
- return context;
- }
- }
-}
diff --git a/src/test/java/io/kokuwa/micronaut/logging/http/level/LogLevelServerFilterTest.java b/src/test/java/io/kokuwa/micronaut/logging/http/level/LogLevelServerFilterTest.java
deleted file mode 100644
index c4db1ef..0000000
--- a/src/test/java/io/kokuwa/micronaut/logging/http/level/LogLevelServerFilterTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package io.kokuwa.micronaut.logging.http.level;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.util.Map;
-
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import ch.qos.logback.classic.Level;
-import io.kokuwa.micronaut.logging.http.AbstractFilterTest;
-import io.micronaut.context.annotation.Property;
-
-/**
- * Test for {@link LogLevelServerFilter}.
- *
- * @author Stephan Schnabel
- */
-@DisplayName("http: set log level via http request")
-public class LogLevelServerFilterTest extends AbstractFilterTest {
-
- @DisplayName("noop: disabled")
- @Test
- @Property(name = "logger.http.level.enabled", value = "false")
- void noopDisabled() {
- assertLevel(Level.INFO, "TRACE");
- }
-
- @DisplayName("noop: header missing")
- @Test
- void noopHeaderMissing() {
- assertLevel(Level.INFO, null);
- }
-
- @DisplayName("noop: header invalid, use DEBUG as default from logback")
- @Test
- void noopHeaderInvalid() {
- assertLevel(Level.DEBUG, "TRCE");
- }
-
- @DisplayName("level: trace (below default)")
- @Test
- void levelTrace() {
- assertLevel(Level.TRACE, "TRACE");
- }
-
- @DisplayName("level: debug (below default)")
- @Test
- void levelDebug() {
- assertLevel(Level.DEBUG, "DEBUG");
- }
-
- @DisplayName("level: info (is default)")
- @Test
- void levelInfo() {
- assertLevel(Level.INFO, "INFO");
- }
-
- @DisplayName("level: warn (above default)")
- @Test
- void levelWarn() {
- assertLevel(Level.INFO, "WARN");
- }
-
- @DisplayName("config: custom header name")
- @Test
- @Property(name = "logger.http.level.header", value = "FOO")
- void configHeaderWarn() {
- assertLevel(Level.TRACE, "FOO", "TRACE");
- }
-
- private void assertLevel(Level expectedLevel, String value) {
- assertLevel(expectedLevel, LogLevelServerFilter.DEFAULT_HEADER, value);
- }
-
- private void assertLevel(Level expectedLevel, String name, String value) {
- var headers = value == null ? Map.of() : Map.of(name, value);
- assertEquals(expectedLevel.toString(), get("/level", headers).getLevel());
- }
-}
diff --git a/src/test/java/io/kokuwa/micronaut/logging/http/mdc/AuthenticationMdcFilterTest.java b/src/test/java/io/kokuwa/micronaut/logging/http/mdc/AuthenticationMdcFilterTest.java
deleted file mode 100644
index d10b673..0000000
--- a/src/test/java/io/kokuwa/micronaut/logging/http/mdc/AuthenticationMdcFilterTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package io.kokuwa.micronaut.logging.http.mdc;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.util.List;
-import java.util.Map;
-
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import io.kokuwa.micronaut.logging.http.AbstractFilterTest;
-import io.micronaut.context.annotation.Property;
-import io.micronaut.http.HttpHeaders;
-
-/**
- * Test for {@link AuthenticationMdcFilter}.
- *
- * @author Stephan Schnabel
- */
-@DisplayName("http: mdc from authentication")
-public class AuthenticationMdcFilterTest extends AbstractFilterTest {
-
- @DisplayName("noop: disabled")
- @Test
- @Property(name = "logger.http.authentication.enabled", value = "false")
- void noopDisabled() {
- assertEquals(Map.of(), getContext(true));
- }
-
- @DisplayName("noop: token missing")
- @Test
- void noopTokenMissing() {
- assertEquals(Map.of(), getContext(false));
- }
-
- @DisplayName("mdc: default config")
- @Test
- void mdcWithDefault() {
- assertEquals(Map.of("principal", "mySubject"), getContext(true));
- }
-
- @DisplayName("mdc: with name")
- @Test
- @Property(name = "logger.http.authentication.name", value = "sub")
- void mdcWithName() {
- assertEquals(Map.of("sub", "mySubject"), getContext(true));
- }
-
- @DisplayName("mdc: with attribute keys")
- @Test
- @Property(name = "logger.http.authentication.attributes", value = "azp,aud")
- void mdcWithAttributes() {
- assertEquals(Map.of("principal", "mySubject", "aud", "[a, b]", "azp", "myAzp"), getContext(true));
- }
-
- @DisplayName("mdc: with prefix")
- @Test
- @Property(name = "logger.http.authentication.name", value = "sub")
- @Property(name = "logger.http.authentication.attributes", value = "azp")
- @Property(name = "logger.http.authentication.prefix", value = "auth.")
- void mdcWithPrefix() {
- assertEquals(Map.of("auth.sub", "mySubject", "auth.azp", "myAzp"), getContext(true));
- }
-
- private Map getContext(boolean token) {
- return get("/security", token
- ? Map.of(HttpHeaders.AUTHORIZATION, token("mySubject", claims -> claims
- .issuer("nope")
- .claim("azp", "myAzp")
- .audience(List.of("a", "b"))))
- : Map.of()).getContext();
- }
-}
diff --git a/src/test/java/io/kokuwa/micronaut/logging/http/mdc/HeaderMdcFilterTest.java b/src/test/java/io/kokuwa/micronaut/logging/http/mdc/HeaderMdcFilterTest.java
deleted file mode 100644
index 489870f..0000000
--- a/src/test/java/io/kokuwa/micronaut/logging/http/mdc/HeaderMdcFilterTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package io.kokuwa.micronaut.logging.http.mdc;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.util.Map;
-
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import io.kokuwa.micronaut.logging.http.AbstractFilterTest;
-import io.micronaut.context.annotation.Property;
-
-/**
- * Test for {@link HeaderMdcFilter}.
- *
- * @author Stephan Schnabel
- */
-@DisplayName("http: mdc from headers")
-public class HeaderMdcFilterTest extends AbstractFilterTest {
-
- @DisplayName("noop: empty configuration")
- @Test
- void noopEmptyConfiguration() {
- assertContext(Map.of(), Map.of("foo", "bar"));
- }
-
- @DisplayName("noop: disabled")
- @Test
- @Property(name = "logger.http.header.enabled", value = "false")
- @Property(name = "logger.http.header.names", value = "foo")
- void noopDisabled() {
- assertContext(Map.of(), Map.of("foo", "bar"));
- }
-
- @DisplayName("mdc: mismatch")
- @Test
- @Property(name = "logger.http.header.names", value = "foo")
- void mdcMismatch() {
- assertContext(Map.of(), Map.of("nope", "bar"));
- }
-
- @DisplayName("mdc: match without prefix")
- @Test
- @Property(name = "logger.http.header.names", value = "foo")
- void mdcMatchWithoutPrefix() {
- assertContext(Map.of("foo", "bar"), Map.of("foo", "bar", "nope", "bar"));
- }
-
- @DisplayName("mdc: match with prefix")
- @Test
- @Property(name = "logger.http.header.names", value = "foo")
- @Property(name = "logger.http.header.prefix", value = "header.")
- void mdcMatchWithPrefix() {
- assertContext(Map.of("header.foo", "bar"), Map.of("foo", "bar", "nope", "bar"));
- }
-
- private void assertContext(Map expectedMdcs, Map headers) {
- assertEquals(expectedMdcs, get("/header", headers).getContext());
- }
-}
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
deleted file mode 100644
index 3b7ac78..0000000
--- a/src/test/java/io/kokuwa/micronaut/logging/http/mdc/PathMdcFilterTest.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package io.kokuwa.micronaut.logging.http.mdc;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.util.Map;
-import java.util.UUID;
-
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-import io.kokuwa.micronaut.logging.http.AbstractFilterTest;
-import io.micronaut.context.annotation.Property;
-
-/**
- * Test for {@link PathMdcFilter}.
- *
- * @author Stephan Schnabel
- */
-@DisplayName("http: mdc from path")
-public class PathMdcFilterTest extends AbstractFilterTest {
-
- @DisplayName("noop: empty configuration")
- @Test
- void noopEmptyConfiguration() {
- assertContext(Map.of(), "/foo/bar");
- }
-
- @DisplayName("noop: disabled")
- @Test
- @Property(name = "logger.http.path.enabled", value = "false")
- @Property(name = "logger.http.path.patterns", value = "\\/foo\\/(?[0-9]+)")
- void noopDisabled() {
- assertContext(Map.of(), "/foo/123");
- }
-
- @DisplayName("noop: misconfigured")
- @Test
- @Property(name = "logger.http.path.patterns", value = "\\A{")
- void noopMisconfigured() {
- assertContext(Map.of(), "/foo/123");
- }
-
- @DisplayName("noop: no group")
- @Test
- @Property(name = "logger.http.path.patterns", value = "\\/foo/[0-9]+")
- void noopGroups() {
- assertContext(Map.of(), "/foo/123");
- }
-
- @DisplayName("mdc: mismatch")
- @Test
- @Property(name = "logger.http.path.patterns", value = "\\/foo\\/(?[0-9]+)")
- void mdcMismatch() {
- assertContext(Map.of(), "/nope");
- assertContext(Map.of(), "/foo/abc");
- }
-
- @DisplayName("mdc: match with single group")
- @Test
- @Property(name = "logger.http.path.patterns", value = "\\/foo\\/(?[0-9]+)")
- void mdcMatchWithSingleGroup() {
- assertContext(Map.of("foo", "123"), "/foo/123");
- }
-
- @DisplayName("mdc: match with single group and prefix")
- @Test
- @Property(name = "logger.http.path.names", value = "foo")
- @Property(name = "logger.http.path.patterns", value = "\\/foo\\/(?[0-9]+)")
- @Property(name = "logger.http.path.prefix", value = "path.")
- void mdcMatchWithSingleGroupAndPrefix() {
- assertContext(Map.of("path.foo", "123"), "/foo/123");
- }
-
- @DisplayName("mdc: match with single group and misconfigured")
- @Test
- @Property(name = "logger.http.path.names", value = "foo")
- @Property(name = "logger.http.path.patterns", value = "\\/foo\\/(?[0-9]+),\\A{")
- @Property(name = "logger.http.path.prefix", value = "path.")
- void mdcMatchWithSingleGroupAndMisconfigured() {
- assertContext(Map.of("path.foo", "123"), "/foo/123");
- }
-
- @DisplayName("mdc: match with multiple group")
- @Test
- @Property(name = "logger.http.path.patterns", value = "/foo/(?[0-9]+)/bar/(?[0-9]+)")
- void mdcMatchWithmultipleGroup() {
- assertContext(Map.of("foo", "123", "bar", "456"), "/foo/123/bar/456");
- }
-
- @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]+)""")
- void mdcMatchExample() {
- var uuid = UUID.randomUUID().toString();
- assertContext(Map.of("gatewayId", uuid), "/gateway/" + uuid);
- assertContext(Map.of("gatewayId", uuid, "config", "abc"), "/gateway/" + uuid + "/configuration/abc");
- }
-
- private void assertContext(Map expectedMdcs, String path) {
- assertEquals(expectedMdcs, get(path, Map.of()).getContext());
- }
-}
diff --git a/src/test/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterTest.java b/src/test/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterTest.java
index 186c2a3..e964d2b 100644
--- a/src/test/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterTest.java
+++ b/src/test/java/io/kokuwa/micronaut/logging/mdc/MDCTurboFilterTest.java
@@ -10,14 +10,14 @@ import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import io.kokuwa.micronaut.logging.AbstractTest;
-import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
+import io.micronaut.test.annotation.MicronautTest;
/**
* Test for {@link MDCTurboFilterConfigurer}.
*
* @author Stephan Schnabel
*/
-@DisplayName("mdc based log levels")
+@DisplayName("mdc")
@MicronautTest(environments = "test-mdc")
public class MDCTurboFilterTest extends AbstractTest {
diff --git a/src/test/java/io/kokuwa/micronaut/logging/request/CompositeTest.java b/src/test/java/io/kokuwa/micronaut/logging/request/CompositeTest.java
new file mode 100644
index 0000000..26e766d
--- /dev/null
+++ b/src/test/java/io/kokuwa/micronaut/logging/request/CompositeTest.java
@@ -0,0 +1,41 @@
+package io.kokuwa.micronaut.logging.request;
+
+import javax.inject.Inject;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import ch.qos.logback.classic.Level;
+import io.kokuwa.micronaut.logging.AbstractTest;
+import io.micronaut.test.annotation.MicronautTest;
+
+/**
+ * Test for MDC and request filter combined.
+ *
+ * @author Stephan Schnabel
+ */
+@DisplayName("request-composite")
+@MicronautTest(environments = "test-composite")
+public class CompositeTest extends AbstractTest {
+
+ @Inject
+ TestClient client;
+
+ @DisplayName("default level")
+ @Test
+ void defaultLogging() {
+ client.assertLevel(Level.INFO, client.token("somebody"), null);
+ }
+
+ @DisplayName("level set by mdc")
+ @Test
+ void headerFromMdc() {
+ client.assertLevel(Level.DEBUG, client.token("horst"), null);
+ }
+
+ @DisplayName("level set by header (overriding mdc)")
+ @Test
+ void headerFromHeader() {
+ client.assertLevel(Level.TRACE, client.token("horst"), "TRACE");
+ }
+}
diff --git a/src/test/java/io/kokuwa/micronaut/logging/request/RequestHeaderTest.java b/src/test/java/io/kokuwa/micronaut/logging/request/RequestHeaderTest.java
new file mode 100644
index 0000000..b939b95
--- /dev/null
+++ b/src/test/java/io/kokuwa/micronaut/logging/request/RequestHeaderTest.java
@@ -0,0 +1,57 @@
+package io.kokuwa.micronaut.logging.request;
+
+import javax.inject.Inject;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import ch.qos.logback.classic.Level;
+import io.kokuwa.micronaut.logging.AbstractTest;
+
+/**
+ * Test for {@link HeaderLoggingHttpFilter}.
+ *
+ * @author Stephan Schnabel
+ */
+@DisplayName("request-header")
+public class RequestHeaderTest extends AbstractTest {
+
+ @Inject
+ TestClient client;
+
+ @DisplayName("header missing")
+ @Test
+ void headerMissing() {
+ client.assertLevel(Level.INFO, null, null);
+ }
+
+ @DisplayName("header invalid, use DEBUG as default from logback")
+ @Test
+ void headerInvalid() {
+ client.assertLevel(Level.DEBUG, null, "TRCE");
+ }
+
+ @DisplayName("level trace (below default)")
+ @Test
+ void headerLevelTrace() {
+ client.assertLevel(Level.TRACE, null, "TRACE");
+ }
+
+ @DisplayName("level debug (below default)")
+ @Test
+ void headerLevelDebug() {
+ client.assertLevel(Level.DEBUG, null, "DEBUG");
+ }
+
+ @DisplayName("level info (is default)")
+ @Test
+ void headerLevelInfo() {
+ client.assertLevel(Level.INFO, null, "INFO");
+ }
+
+ @DisplayName("level warn (above default)")
+ @Test
+ void headerLevelWarn() {
+ client.assertLevel(Level.INFO, null, "WARN");
+ }
+}
diff --git a/src/test/java/io/kokuwa/micronaut/logging/request/RequestPrincipalTest.java b/src/test/java/io/kokuwa/micronaut/logging/request/RequestPrincipalTest.java
new file mode 100644
index 0000000..f8f1fcc
--- /dev/null
+++ b/src/test/java/io/kokuwa/micronaut/logging/request/RequestPrincipalTest.java
@@ -0,0 +1,44 @@
+package io.kokuwa.micronaut.logging.request;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import javax.inject.Inject;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import io.kokuwa.micronaut.logging.AbstractTest;
+
+/**
+ * Test for {@link PrincipalHttpFilter}.
+ *
+ * @author Stephan Schnabel
+ */
+@DisplayName("request-principal")
+public class RequestPrincipalTest extends AbstractTest {
+
+ @Inject
+ TestClient client;
+
+ @DisplayName("token missing")
+ @Test
+ void tokenMissing() {
+ assertPrincipal(null, null);
+ }
+
+ @DisplayName("token invalid")
+ @Test
+ void tokenInvalid() {
+ assertPrincipal(null, "meh");
+ }
+
+ @DisplayName("token valid")
+ @Test
+ void tokenValid() {
+ assertPrincipal("meh", client.token("meh"));
+ }
+
+ private void assertPrincipal(String expectedPrincipal, String actualTokenValue) {
+ assertEquals(expectedPrincipal, client.get(actualTokenValue, null).getPrincipal());
+ }
+}
diff --git a/src/test/java/io/kokuwa/micronaut/logging/request/TestClient.java b/src/test/java/io/kokuwa/micronaut/logging/request/TestClient.java
new file mode 100644
index 0000000..b44495a
--- /dev/null
+++ b/src/test/java/io/kokuwa/micronaut/logging/request/TestClient.java
@@ -0,0 +1,64 @@
+package io.kokuwa.micronaut.logging.request;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jwt.JWTClaimsSet;
+
+import ch.qos.logback.classic.Level;
+import io.kokuwa.micronaut.logging.request.TestController.TestResponse;
+import io.micronaut.http.HttpRequest;
+import io.micronaut.http.HttpStatus;
+import io.micronaut.http.client.HttpClient;
+import io.micronaut.http.client.annotation.Client;
+import io.micronaut.security.token.jwt.signature.SignatureGeneratorConfiguration;
+
+/**
+ * Contoller for testing {@link HeaderLoggingHttpFilter} and {@link PrincipalHttpFilter}.
+ *
+ * @author Stephan Schnabel
+ */
+@Singleton
+public class TestClient {
+
+ @Inject
+ @Client("/")
+ HttpClient client;
+ @Inject
+ SignatureGeneratorConfiguration signature;
+
+ String token(String subject) {
+ try {
+ return signature.sign(new JWTClaimsSet.Builder().subject(subject).build()).serialize();
+ } catch (JOSEException e) {
+ fail("failed to create token");
+ return null;
+ }
+ }
+
+ TestResponse get(String token, String header) {
+
+ var request = HttpRequest.GET("/");
+ if (token != null) {
+ request.bearerAuth(token);
+ }
+ if (header != null) {
+ request.getHeaders().add(HeaderLoggingHttpFilter.DEFAULT_HEADER, header);
+ }
+
+ var response = client.toBlocking().exchange(request, TestResponse.class);
+ assertEquals(HttpStatus.OK, response.getStatus(), "status");
+ assertTrue(response.getBody().isPresent(), "body");
+
+ return response.body();
+ }
+
+ void assertLevel(Level expectedLevel, String actualTokenValue, String actualHeaderValue) {
+ assertEquals(expectedLevel.toString(), get(actualTokenValue, actualHeaderValue).getLevel());
+ }
+}
diff --git a/src/test/java/io/kokuwa/micronaut/logging/request/TestController.java b/src/test/java/io/kokuwa/micronaut/logging/request/TestController.java
new file mode 100644
index 0000000..3d3d6c9
--- /dev/null
+++ b/src/test/java/io/kokuwa/micronaut/logging/request/TestController.java
@@ -0,0 +1,52 @@
+package io.kokuwa.micronaut.logging.request;
+
+import org.slf4j.MDC;
+
+import ch.qos.logback.classic.Level;
+import io.micronaut.http.annotation.Controller;
+import io.micronaut.http.annotation.Get;
+import io.micronaut.security.annotation.Secured;
+import io.micronaut.security.rules.SecurityRule;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Controller for testing {@link HeaderLoggingHttpFilter} and {@link PrincipalHttpFilter}.
+ *
+ * @author Stephan Schnabel
+ */
+@Secured({ SecurityRule.IS_ANONYMOUS, SecurityRule.IS_AUTHENTICATED })
+@Controller
+@Slf4j
+public class TestController {
+
+ @Get("/")
+ TestResponse run() {
+
+ var principal = MDC.get(PrincipalHttpFilter.DEFAULT_KEY);
+ var level = Level.OFF;
+ if (log.isTraceEnabled()) {
+ level = Level.TRACE;
+ } else if (log.isDebugEnabled()) {
+ level = Level.DEBUG;
+ } else if (log.isInfoEnabled()) {
+ level = Level.INFO;
+ } else if (log.isWarnEnabled()) {
+ level = Level.WARN;
+ } else if (log.isErrorEnabled()) {
+ level = Level.ERROR;
+ }
+
+ return new TestResponse(level.toString(), principal);
+ }
+
+ @Data
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class TestResponse {
+ private String level;
+ private String principal;
+ }
+}
diff --git a/src/test/resources/META-INF/build-info.properties b/src/test/resources/META-INF/build-info.properties
new file mode 100644
index 0000000..5401a6c
--- /dev/null
+++ b/src/test/resources/META-INF/build-info.properties
@@ -0,0 +1,2 @@
+serviceName: ${project.artifactId}
+serviceVersion: ${project.version}
diff --git a/src/test/resources/application-test-composite.yaml b/src/test/resources/application-test-composite.yaml
new file mode 100644
index 0000000..7ba34db
--- /dev/null
+++ b/src/test/resources/application-test-composite.yaml
@@ -0,0 +1,8 @@
+logger:
+ mdc:
+ principal:
+ level: DEBUG
+ loggers:
+ - io.kokuwa
+ values:
+ - horst
diff --git a/src/test/resources/application-test-mdc.yaml b/src/test/resources/application-test-mdc.yaml
index 69cbc89..ef6bfc5 100644
--- a/src/test/resources/application-test-mdc.yaml
+++ b/src/test/resources/application-test-mdc.yaml
@@ -1,28 +1,26 @@
logger:
- levels:
- io.micronaut.logging.PropertiesLoggingLevelsConfigurer: "OFF"
mdc:
key1:
key: key
level: DEBUG
loggers:
- - io.kokuwa.a
- - io.kokuwa.b
+ - io.kokuwa.a
+ - io.kokuwa.b
values:
- - value-1
- - value-2
+ - value-1
+ - value-2
key2:
key: key
level: TRACE
loggers:
- - io.kokuwa.b
- - io.kokuwa.c
+ - io.kokuwa.b
+ - io.kokuwa.c
values:
- - value-2
+ - value-2
key:
level: TRACE
loggers:
- - io.kokuwa
+ - io.kokuwa
values:
- - value-3
+ - value-3
user: {}
diff --git a/src/test/resources/application-test.yaml b/src/test/resources/application-test.yaml
index 867b23e..42aa67e 100644
--- a/src/test/resources/application-test.yaml
+++ b/src/test/resources/application-test.yaml
@@ -7,3 +7,10 @@ micronaut:
generator:
secret: pleaseChangeThisSecretForANewOne
jws-algorithm: HS256
+ http:
+ client:
+ logger-name: io.kokuwa.Test
+
+logger:
+ levels:
+ io.kokuwa.Test: TRACE