From c9246c7a7432b6701bed80fa0c120536f15f1b7a Mon Sep 17 00:00:00 2001 From: Marc Fletcher Date: Sun, 10 Jan 2021 13:47:48 +0000 Subject: [PATCH 01/23] Added core implementation. --- .gitignore | 27 +- ...Eclipse_EBX_Code_Style_Imports.importorder | 11 + ...ipse_EBX_Code_Style_formatter_settings.xml | 295 ++++++++++++++++++ ...llij_EBX_Code_Style_formatter_settings.xml | 226 ++++++++++++++ CodeStyle/README.md | 100 ++++++ CodeStyle/checkstyle.xml | 284 +++++++++++++++++ README.md | 64 +++- licenseheader.txt | 16 + pom.xml | 141 +++++++++ .../logging/SyslogAppenderWithAppendix.java | 58 ++++ .../echobox/logging/ThreadIdConverter.java | 49 +++ .../com/echobox/logging/TwoPartLayout.java | 80 +++++ 12 files changed, 1326 insertions(+), 25 deletions(-) create mode 100644 CodeStyle/Eclipse_EBX_Code_Style_Imports.importorder create mode 100644 CodeStyle/Eclipse_EBX_Code_Style_formatter_settings.xml create mode 100644 CodeStyle/Intellij_EBX_Code_Style_formatter_settings.xml create mode 100644 CodeStyle/README.md create mode 100644 CodeStyle/checkstyle.xml create mode 100644 licenseheader.txt create mode 100644 pom.xml create mode 100644 src/main/java/com/echobox/logging/SyslogAppenderWithAppendix.java create mode 100644 src/main/java/com/echobox/logging/ThreadIdConverter.java create mode 100644 src/main/java/com/echobox/logging/TwoPartLayout.java diff --git a/.gitignore b/.gitignore index a1c2a23..917f1dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,4 @@ -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* +/bin/ +/target/ +.idea/ +*.iml diff --git a/CodeStyle/Eclipse_EBX_Code_Style_Imports.importorder b/CodeStyle/Eclipse_EBX_Code_Style_Imports.importorder new file mode 100644 index 0000000..59c42ba --- /dev/null +++ b/CodeStyle/Eclipse_EBX_Code_Style_Imports.importorder @@ -0,0 +1,11 @@ +#Organize Import Order +#Tue Apr 05 15:57:16 BST 2016 +7=java +5=sun +6=io +4=org +3=net +2=mockit +1=com +0=sh +8=javax diff --git a/CodeStyle/Eclipse_EBX_Code_Style_formatter_settings.xml b/CodeStyle/Eclipse_EBX_Code_Style_formatter_settings.xml new file mode 100644 index 0000000..5cd9901 --- /dev/null +++ b/CodeStyle/Eclipse_EBX_Code_Style_formatter_settings.xml @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CodeStyle/Intellij_EBX_Code_Style_formatter_settings.xml b/CodeStyle/Intellij_EBX_Code_Style_formatter_settings.xml new file mode 100644 index 0000000..2871283 --- /dev/null +++ b/CodeStyle/Intellij_EBX_Code_Style_formatter_settings.xml @@ -0,0 +1,226 @@ + + diff --git a/CodeStyle/README.md b/CodeStyle/README.md new file mode 100644 index 0000000..e4add0b --- /dev/null +++ b/CodeStyle/README.md @@ -0,0 +1,100 @@ +FOR ECLIPSE: +=========== + +To install the correct formatter settings in Eclipse: +----------------------------------------------------- + +- Window -> Preferences -> Java -> Code style -> Formatter : +- And then import the file: +- echobox.main/CodeStyle/"Eclipse_EBX_Code_Style_formatter_settings.XML" +- Then in the "Organize imports" tab : +- Window -> Preferences -> Java -> Code style -> Organize imports +- And then import the file: +- echobox.main/CodeStyle/"Eclipse_EBX_Code_Style_Imports.importorder" + + +You can now use the formatter by either highlighting the code you want to format, or the entire +file, and Press ctrl-shift-F. This will automatically format the code so that it complies with the +EchoBox Style guide. + +To format the import statements simply press ctrl-shift-O which will Organize the imports and +place them in the correct order. + +To format code correctly: **Ctrl-Shift-F** +To format Imports correctly: **Ctrl-Shift-O** + +***Use the formatter!!!!*** + + +TO Configure the Eclipse "check style" plug-in: +----------------------------------------------- + +When first importing the maven project you should be prompted to install +the Eclipse "check style" plug-in. This will act as a kind of "compiler" and underline code which +does not follow the check style standard, allowing you to fix violations as you go. + +If you are not prompted to install this plug-in reimport the project. + +When the plug-in is installed it defaults to the "Google style guide". + +To change this to the "EchoBox style guide": + +- Window -> Preferences -> checkStyle : +- Click : "NEW" on the right-hand side +- Then in the drop-down menu select "External configuration file" +- In location select echobox.main/CodeStyle/"checkstyle.xml" +- you can name this anything, I suggest "EbxStyle". +- Click : OK +- Next click on this new configurations and click "Set as default" + +Now the Eclipse check style plug-in is configured with the "EchoBox style guide" and should +behave correctly. + + + + +FOR Intellj-IDEA: +================= + +To install the correct formatter settings in Intellj-IDEA: +---------------------------------------------------------- + +- File -> Settings -> Code style -> Java , Click: Manage -> import -> Intellj-IDEA code style XML: +- And then import the file: +- echobox.main/CodeStyle/"Intellij_EBX_Code_Style_formatter_settings" + + +You can now use the formatter by either highlighting the code you want to format, or the entire +file, and Press Ctrl-Alt-L. This will automatically format the code so that it complies with the +EchoBox Style guide. + +To format the import statements simply press Ctrl-Alt-O which will optimise the imports and +place them in the correct order. + +To format code correctly: **Ctrl-Alt-L** +To format Imports correctly: **Ctrl-Alt-O** + +***Use the formatter!!!!*** + + +TO Configure the Intellj "check style" plug-in: +------------------------------------------------ + +to Install the Intellj "check style" plug-in go to: + +- Settings -> Plug-ins / +- Click on the "Browse repositories" button at the bottom. +- And then enter "CheckStyle-IDEA" +- Click install + +Then to configure this plug-in to conform with "EBXStyle" + +- Settings -> Other Settings -> checkstyle +- click on the green plus button +- Add in the description "ebx_checks" +- Add the checkstyle.xml File found in echobox.main\CodeStyle\checkstyle.xml +- Tick the "Treat checkstyle errors as warnings" box +- click Apply -> OK + +Now any violations of the checkstyle rules will be highlighted as a warning live in the code you +write. diff --git a/CodeStyle/checkstyle.xml b/CodeStyle/checkstyle.xml new file mode 100644 index 0000000..7ed4735 --- /dev/null +++ b/CodeStyle/checkstyle.xml @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index 05bed27..5ac9115 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,62 @@ -# ebx-logging-sdk -Helpful logging extensions +# ebx-structuredlogging-sdk + +Logging is a critical pillar of service observability. Occasionally it's desirable to +include structured information and depending on the logging solution these can then be +more easily graphed, analysed etc, for example with +[loggly](https://www.loggly.com/blog/introducing-support-for-percentiles-and-other-statistics/). + +This library intends to make including such structured logging as easy as possible by allowing +structured arguments to be included in `ch.qos.logback.classic.net.SyslogAppender`. + +## How to use + +1. Include this sdk (assuming maven): + +``` + + com.echobox + ebx-structuredlogging-sdk + 1.0.0 + +``` + +2. Update the relevant project `logback.xml` file to include the extended `SyslogAppender` config: + +``` + + + + + +localhost +USER +[%logger] %nopex + + + + { "threadId": "%tid-%thread", "message": "%msg", "exception":"%rEx{30}" } + + + + + +``` + +The pattern can be modified as required, see [here](http://logback.qos.ch/manual/layouts.html#ClassicPatternLayout). + +3. Start including `net.logstash.logback.argument.StructuredArguments` where required: + +``` +Map loggingMap = new HashMap<>(); +loggingMap.put("executionTimeMS", endTimeMS - startTimeMS); +logger.debug("Completed execution in MS {}", StructuredArguments.entries(loggingMap)); +``` + +or + +``` +logger.warn(... +``` + +etc. \ No newline at end of file diff --git a/licenseheader.txt b/licenseheader.txt new file mode 100644 index 0000000..ae6f28c --- /dev/null +++ b/licenseheader.txt @@ -0,0 +1,16 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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/pom.xml b/pom.xml new file mode 100644 index 0000000..a351ca4 --- /dev/null +++ b/pom.xml @@ -0,0 +1,141 @@ + + + 4.0.0 + com.echobox + ebx-structuredlogging-sdk + 1.0.0 + jar + + + UTF-8 + UTF-8 + 1.8 + 1.8 + true + + + + + org.slf4j + slf4j-api + 1.7.30 + + + org.slf4j + slf4j-ext + 1.7.30 + + + ch.qos.logback + logback-classic + 1.2.3 + + + + net.logstash.logback + logstash-logback-encoder + 6.4 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + true + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + org.apache.maven.surefire + surefire-junit47 + 3.0.0-M5 + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + + attach-javadocs + package + + jar + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.1.1 + + + validate + validate + + CodeStyle/checkstyle.xml + true + false + false + true + basedir=${project.basedir} + + + check + + + + + + com.puppycrawl.tools + checkstyle + 8.29 + + + com.github.sevntu-checkstyle + sevntu-checks + 1.35.0 + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.13.0 + + + cpd + validate + + cpd + + + 50 + + + + cpd-check + validate + + cpd-check + + + true + + + + + + + diff --git a/src/main/java/com/echobox/logging/SyslogAppenderWithAppendix.java b/src/main/java/com/echobox/logging/SyslogAppenderWithAppendix.java new file mode 100644 index 0000000..4d67bcd --- /dev/null +++ b/src/main/java/com/echobox/logging/SyslogAppenderWithAppendix.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging; + +import ch.qos.logback.classic.net.SyslogAppender; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Layout; + +/** + * A variant {@link SyslogAppender} admitting a specified {@code Layout} that will be attached to + * the end of each message. + * + * @author MarcF + */ +public class SyslogAppenderWithAppendix extends SyslogAppender { + /** + * The layout to append to each message. + */ + protected Layout appendixLayout; + + @Override + public Layout buildLayout() { + // First layout is just the base layout: + Layout syslogLayout = super.buildLayout(); + + // Second layout comes from this class, probably set in a config file. + TwoPartLayout layout = new TwoPartLayout<>(syslogLayout, appendixLayout); + + layout.setContext(getContext()); + layout.start(); + + return layout; + } + + /** + * Public setter to allow the layout to be set from a config file. + * + * @param appendixLayout the appendix layout + */ + public void setAppendixLayout(Layout appendixLayout) { + this.appendixLayout = appendixLayout; + } +} diff --git a/src/main/java/com/echobox/logging/ThreadIdConverter.java b/src/main/java/com/echobox/logging/ThreadIdConverter.java new file mode 100644 index 0000000..a9d1a5d --- /dev/null +++ b/src/main/java/com/echobox/logging/ThreadIdConverter.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging; + +import ch.qos.logback.classic.pattern.ClassicConverter; +import ch.qos.logback.classic.spi.ILoggingEvent; + +/** + * A converter used in logging to create a unique thread id + * + * @author MarcF + */ +public class ThreadIdConverter extends ClassicConverter { + + private static int nextId = 0; + private static final ThreadLocal threadId = new ThreadLocal() { + + @Override + protected String initialValue() { + int nextId = nextId(); + return String.format("%05d", nextId); + } + }; + + private static synchronized int nextId() { + nextId = (nextId + 1) % 99999; + return nextId; + } + + @Override + public String convert(ILoggingEvent event) { + return threadId.get(); + } +} diff --git a/src/main/java/com/echobox/logging/TwoPartLayout.java b/src/main/java/com/echobox/logging/TwoPartLayout.java new file mode 100644 index 0000000..6649240 --- /dev/null +++ b/src/main/java/com/echobox/logging/TwoPartLayout.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.Layout; +import ch.qos.logback.core.LayoutBase; + +/** + * A wrapper for a pair of Layouts. + * + * When {@link #doLayout(Object)} is called on an event, it applies each layout to the event and + * returns the concatenation of the results. + * + * @param The type parameter for the Layout + * + * @author MarcF + */ +public class TwoPartLayout extends LayoutBase { + + /** + * The first layout, which will make up the beginning of each message. + */ + protected Layout first; + + /** + * The second layout, which will make up the end of each message. + */ + protected Layout second; + + /** + * Construct a new {@code TwoPartLayout} from the provided {@code Layout}s. + * + * @param first the first + * @param second the second + */ + public TwoPartLayout(Layout first, Layout second) { + this.first = first; + this.second = second; + } + + /* + * (non-Javadoc) + * + * @see ch.qos.logback.core.Layout#doLayout(java.lang.Object) + */ + @Override + public String doLayout(E event) { + return first.doLayout(event) + second.doLayout(event); + } + + @Override + public void setContext(Context context) { + first.setContext(context); + second.setContext(context); + super.setContext(context); + } + + @Override + public void start() { + first.start(); + second.start(); + super.start(); + } +} From 42c67e4ccec685ae85600b743ede7dad25a1f23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreira?= Date: Wed, 27 Jan 2021 16:07:16 +0000 Subject: [PATCH 02/23] TEC-11009 Initial Travis-CI setup (#1) * TEC-11009 Initial Travis-CI setup * TEC-11009 Add missing Maven config file * TEC-11009 Update Travis configuration and project files * TEC-11009 Update .gitignore * TEC-11009 Add PR template * TEC-11009 Update Changelog and pom.xml files * TEC-11009 Update secure key for current repo * TEC-11009 Fix pom.xml file --- .github/pull_request_template.md | 29 ++ .gitignore | 26 +- .maven.xml | 23 ++ .travis.yml | 59 +++ CHANGELOG.md | 5 + CONTRIBUTING.md | 37 ++ .../Build-Scripts/build_sdk_travis.sh | 27 ++ .../Build-Scripts/export_mvn_version.sh | 33 ++ .../Build-Scripts/validate_build.sh | 39 ++ NOTICE.txt | 2 + README.md | 1 + pom.xml | 371 +++++++++++------- 12 files changed, 519 insertions(+), 133 deletions(-) create mode 100644 .github/pull_request_template.md create mode 100644 .maven.xml create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 Infrastructure/Build-Scripts/build_sdk_travis.sh create mode 100644 Infrastructure/Build-Scripts/export_mvn_version.sh create mode 100644 Infrastructure/Build-Scripts/validate_build.sh create mode 100644 NOTICE.txt diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..c6265fa --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,29 @@ +### Description of Changes + +What has been changed? If this is more than bug fixes we should consider incrementing the minor +version number. For non backwards compatible changes we need to increment the major version number. + +### Documentation + +Provide links to all relevant documentation that should be updated before asking for the PR to be reviewed. If this section is not relevant please write 'Not Applicable' rather than deleting the section. + +### Risks & Impacts + +The potential risks of this change as a bullet pointed list and how it might impact the wider sdk. Please consider how easily it would be to rollback these changes if they cause problems. Are there breaking changes? + +### Testing + +How have the changes been tested and the potential risks mitigated? + +### Compare (For layered PRs) + +Generate compare URL from https://github.com/ebx/ebx-structuredlogging-sdk/compare so that it's easily accessible. This is ONLY REQUIRED FOR COMPLICATED, DEPENDENT OR LAYERED PRs. Feel free to delete this section if not required. + +## Final Checklist + +Please tick once completed. + +- [ ] Build passes. +- [ ] Versioning considered (the version number in this PR is inline with semantic +versioning requirements). +- [ ] Change log has been updated. \ No newline at end of file diff --git a/.gitignore b/.gitignore index 917f1dd..d1ed17f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,28 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + /bin/ /target/ .idea/ -*.iml +*.iml \ No newline at end of file diff --git a/.maven.xml b/.maven.xml new file mode 100644 index 0000000..d954cda --- /dev/null +++ b/.maven.xml @@ -0,0 +1,23 @@ + + + + + ossrh + ${env.SONATYPE_USERNAME} + ${env.SONATYPE_PASSWORD} + + + + + + ossrh + + true + + + ${env.GPG_EXECUTABLE} + ${env.GPG_PASSPHRASE} + + + + diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b28f25e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,59 @@ +language: java +dist: trusty +sudo: false # faster builds + +# safelist +branches: + only: + - master + - dev + +env: + global: + - DEV_BRANCH=dev + - RELEASE_BRANCH=master + - REPO=ebx/ebx-structuredlogging-sdk + - NO_COLOUR='\033[0m' + - RED_COLOUR='\033[0;31m' + - GREEN_COLOUR='\033[0;32m' + +before_script: + - export SOURCE_BRANCH_NAME=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi) + - echo $GPG_SECRET_KEYS | base64 --decode | $GPG_EXECUTABLE --import || echo "Failed to import GPG_SECRET_KEYS (probably because this branch is a PR)." + - echo $GPG_OWNERTRUST | base64 --decode | $GPG_EXECUTABLE --import-ownertrust || echo "Failed to import GPG_OWNERTRUST (probably because this branch is a PR)." + - source Infrastructure/Build-Scripts/export_mvn_version.sh + - source Infrastructure/Build-Scripts/validate_build.sh + +script: + - source Infrastructure/Build-Scripts/build_sdk_travis.sh + +after_failure: + - cat target/surefire-reports/*.txt + +## Prepare the release for Github +## Ensure we have a suitable git tag for the release based on the verison number +before_deploy: + # Set up git user name and tag this commit + - git config --local user.name "MarcFletcher" + - git config --local user.email "marc@echobox.com" + - export DEPLOY_TAG=v$MVN_VERSION + - git tag $DEPLOY_TAG + +## Create the release in Github +deploy: + provider: releases + api_key: + secure: vUHGrM4IGMwUhGzzHSRIk/CvB6xCLsee49Mci7hnge+qkHHMOWdfZxQkFSzQua53ekEEO73rPam3pqpIkHvYHIjLt1h08J85g7pXDWDu0/QLimMhI5YVdP1cGgQlrZ8SQM8AbenUIVqQCvAtHfV7qOnsSG472zRFmG2WEgNGyPVxg/kFCfP7de+C1LY8yVilsDKQip7ZMGFhInhEvE2VvR3ja+iBe23/+lSB8Ucfx4BezBHIynOzVY5REHuL0fstGy5vpxyCJ4gj/9jJxQ3X9S1W+hMyT22c8BG1wPpQn3jW80PcSctD4kXpLZuQXDbvqugyeYt4oeUwSMde1InLs44AAU2LGcCQidvpPRD1G6gZ11wvReKlUFiFT53c1Vs4Hq4kd26dvBK5dqF5WcAXklDD8QVmMvmkyxs6GatSS2VcVr6VDlZ/pnMdG8ZAS4yGln2DVLa7ZonCmuZBJvGCiompp9Smm5TZiLWxcKPYw0sICuZY/ecbHV+ZEdkEcjdMRg8uxyReuxjaeJZbQ+JqVANqfbpXzGVL8FpE9+aJerA/ScuKdrJkyse4hnXBbBqF3Go/9Ky9gvyuEF8piPbo9uR7FDvlkdz5deYFq9x/upQ9zs2Q3KTTKYpQP1VcOmFCAVZNIMqqMeTj0yNiZtSY20mfI1uDqUcH6H9GpbOD2Gk= + file: + - target/ebx-structuredlogging-sdk-$MVN_VERSION.jar + - target/ebx-structuredlogging-sdk-$MVN_VERSION-javadoc.jar + - target/ebx-structuredlogging-sdk-$MVN_VERSION-sources.jar + skip_cleanup: true + on: + repo: $REPO + branch: $RELEASE_BRANCH + name: v$MVN_VERSION + +cache: + directories: + - ~/.m2/repository diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..63094f9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,5 @@ +# ebx-structuredlogging-sdk Changelog + +## 1.0.0 (Jan 1, 2014) + +* Initial release diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..3304f26 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,37 @@ +# Contributing to ebx-structuredlogging-sdk + +Contributing code is an essential part of open source and we try to make this as easy as possible. There are several ways you can contribute to ebx-structuredlogging-sdk. Here are some guidelines for creating new issues and sending us pull requests. Please read them carefully before contributing. + +## How to create a new issue + +We like new issues and are very keen to hear your problems, ideas and proposals. After analyzing them, they are categorized and assigned to a milestone. To make this part easier you should give us some information. Please read the checklist and try to mark as many entries as possible. + +**Issue checklist:** +* Check the closed issues and don't open duplicates +* Explain your idea or problem in plain English +* Provide a JSON snippet if possible (values may be obfuscated but similar to the original) +* Tell us why this is beneficial and what the advantage is for the users +* Explain your use case, it's easier to understand a proposal if we have some background knowledge + +## How to create a pull request + +Pull requests (PR) are a very important way to contribute code to the library. We have guidelines for sending us a PR, because changes to the source code are even more fundamental than sending a new issue. This is an overview of our prerequisites. + +**PR checklist:** +* Please ensure you have an associated [github issue](https://github.com/ebx/ebx-structuredlogging-sdk/issues) to hand, this needs to be included in the PR. If a suitable issue doesn't already exist feel free to create one, as described above. +* The code must be formatted with our code formatter (have a look at the [CodeStyle folder](https://github.com/ebx/ebx-structuredlogging-sdk/tree/master/CodeStyle)). If you perform a local *mvn verify* before creating the PR your changes will already be getting validated for style. +* The code layout should conform to our general design standards (if you feel it's necessary to go against the grain, please ask us first!). +* You should complete the PR template and please format your PR title as follows: + + GH-[Issue#] [Summary of change or issue title] + + for example: + + GH-123 Fixed NPE exception when resvoling an organisation + +* The pull request should be mergeable, i.e. no conflicts. +* Junit tests required for any functional change must be included. +* The pull request should be targetted at the `dev` branch. If you raise it against `master` the PR will fail to build. +* Please try to keep PR commits in a logical order incase we need to review each commit seperately, but generally speaking the fewer commits the better. +* Your PR will have to build succesfully against our CI (we use [Travis CI](https://travis-ci.org/ebx/ebx-structuredlogging-sdk)). +* **Important Note**: If your PR contains breaking changes you must include a MAJOR version bump in the PR. diff --git a/Infrastructure/Build-Scripts/build_sdk_travis.sh b/Infrastructure/Build-Scripts/build_sdk_travis.sh new file mode 100644 index 0000000..5e242fe --- /dev/null +++ b/Infrastructure/Build-Scripts/build_sdk_travis.sh @@ -0,0 +1,27 @@ +#!/bin/bash +## +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +## + +## For DEV and MASTER deploy to maven central (DEV will always be a snapshot) +## All other builds are simply verified +if [ "$SOURCE_BRANCH_NAME" == "$RELEASE_BRANCH" ] || [ "$SOURCE_BRANCH_NAME" == "$DEV_BRANCH" ]; then + printf "${GREEN_COLOUR}Performing deploy build to maven central.${NO_COLOUR}\n" + mvn clean deploy --settings .maven.xml -B -U -Prelease +else + printf "${GREEN_COLOUR}Performing a PR verify build. Releases are only created from $DEV_BRANCH and $RELEASE_BRANCH branches.${NO_COLOUR}\n" + mvn clean verify +fi diff --git a/Infrastructure/Build-Scripts/export_mvn_version.sh b/Infrastructure/Build-Scripts/export_mvn_version.sh new file mode 100644 index 0000000..ad32e4d --- /dev/null +++ b/Infrastructure/Build-Scripts/export_mvn_version.sh @@ -0,0 +1,33 @@ +#!/bin/bash +## +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +## + +export MVN_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout|grep -v '\[') +## If this is not master we dynamically set the version to a snapshot +if [ "$SOURCE_BRANCH_NAME" != "$RELEASE_BRANCH" ]; then + mvn versions:set -q -DnewVersion=$MVN_VERSION-SNAPSHOT + export MVN_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout|grep -v '\[') + printf "${GREEN_COLOUR}Build version modified to $MVN_VERSION as this is not the $RELEASE_BRANCH branch.${NO_COLOUR}\n" +else + printf "${GREEN_COLOUR}Build version not modified as this is the $RELEASE_BRANCH branch.${NO_COLOUR}\n" +fi + +#Ensure the project verison is valid +if ! [[ $MVN_VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then + printf "${RED_COLOUR}The extracted project version '$MVN_VERSION' was not valid.${NO_COLOUR}\n" + travis_terminate 1; +fi diff --git a/Infrastructure/Build-Scripts/validate_build.sh b/Infrastructure/Build-Scripts/validate_build.sh new file mode 100644 index 0000000..ca06501 --- /dev/null +++ b/Infrastructure/Build-Scripts/validate_build.sh @@ -0,0 +1,39 @@ +#!/bin/bash +## +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +## + +if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then + printf "${GREEN_COLOUR}Building base branch $SOURCE_BRANCH_NAME which is at version $MVN_VERSION.${NO_COLOUR}\n" +else + #Get the PR title + export PR_TITLE=$(curl -s https://api.github.com/repos/$REPO/pulls/$TRAVIS_PULL_REQUEST | grep -Po '(?<="title":[[:space:]]")[^"]*(?=",)') + + printf "${GREEN_COLOUR}Building PR #$TRAVIS_PULL_REQUEST '$PR_TITLE' from branch $SOURCE_BRANCH_NAME (into $TRAVIS_BRANCH)${NO_COLOUR}\n" + + ##Disabled as travis keeps getting rate limited by github + ##Ensure the PR name matches our expected format + #if ! [[ $PR_TITLE =~ ^[A-Z]{2,4}-[0-9]+[[:space:]].+$ ]]; then + # printf "${RED_COLOUR}PR title '$PR_TITLE' does not match the expected format 'GH-[xxxx] [description]'.${NO_COLOUR}\n" + # travis_terminate 1; + #fi + + #Ensure PR cannot be into master, unless it's coming from dev + if [ "$TRAVIS_BRANCH" == "$RELEASE_BRANCH" ] && [ "$SOURCE_BRANCH_NAME" != "$DEV_BRANCH" ]; then + printf "${RED_COLOUR}Build failed as PR target is master. Please ensure you use $DEV_BRANCH as the target.${NO_COLOUR}\n" + travis_terminate 1; + fi +fi diff --git a/NOTICE.txt b/NOTICE.txt new file mode 100644 index 0000000..57f4cf8 --- /dev/null +++ b/NOTICE.txt @@ -0,0 +1,2 @@ +ebx-structuredlogging-sdk +Copyright 2020 Echobox diff --git a/README.md b/README.md index 5ac9115..cd13d3b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +[![Maven Central](https://img.shields.io/maven-central/v/com.echobox/ebx-structuredlogging-sdk.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.echobox%22%20AND%20a:%22ebx-structuredlogging-sdk%22) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://raw.githubusercontent.com/ebx/ebx-structuredlogging-sdk/master/LICENSE) [![Build Status](https://travis-ci.org/ebx/ebx-structuredlogging-sdk.svg?branch=dev)](https://travis-ci.org/ebx/ebx-structuredlogging-sdk) # ebx-structuredlogging-sdk Logging is a critical pillar of service observability. Occasionally it's desirable to diff --git a/pom.xml b/pom.xml index a351ca4..ff4fe3b 100644 --- a/pom.xml +++ b/pom.xml @@ -1,141 +1,248 @@ - 4.0.0 - com.echobox - ebx-structuredlogging-sdk - 1.0.0 - jar + 4.0.0 - - UTF-8 - UTF-8 - 1.8 - 1.8 - true - + ebx-structuredlogging-sdk + ebx-structuredlogging-sdk intends to make including structured logging data as easy as possible. + https://github.com/ebx/ebx-structuredlogging-sdk + + com.echobox + ebx-structuredlogging-sdk + 1.0.0 + jar - - - org.slf4j - slf4j-api - 1.7.30 - - - org.slf4j - slf4j-ext - 1.7.30 - - - ch.qos.logback - logback-classic - 1.2.3 - - - - net.logstash.logback - logstash-logback-encoder - 6.4 - - + + UTF-8 + UTF-8 + 1.8 + 1.8 + - + + + Apache License, Version 2.0 + https://raw.githubusercontent.com/ebx/ebx-structuredlogging-sdk/master/LICENSE + repo + + + + + scm:git:https://github.com/ebx/ebx-structuredlogging-sdk + https://github.com/ebx/ebx-structuredlogging-sdk + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + + Echobox + http://www.echobox.com + + + + + + org.slf4j + slf4j-api + 1.7.30 + + + org.slf4j + slf4j-ext + 1.7.30 + + + ch.qos.logback + logback-classic + 1.2.3 + + + + net.logstash.logback + logstash-logback-encoder + 6.4 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + true + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M5 + + + org.apache.maven.surefire + surefire-junit47 + 3.0.0-M5 + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + + attach-javadocs + package + + jar + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.1.1 + + + validate + validate + + CodeStyle/checkstyle.xml + true + true + true + basedir=${project.basedir} + + + check + + + + + + com.puppycrawl.tools + checkstyle + 8.29 + + + com.github.sevntu-checkstyle + sevntu-checks + 1.35.0 + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.13.0 + + + cpd + validate + + cpd + + + 50 + + + + cpd-check + validate + + cpd-check + + + true + + + + + + + + + + + release + + + release + + + + - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - true - - - - org.apache.maven.plugins - maven-surefire-plugin - 3.0.0-M5 - - - org.apache.maven.surefire - surefire-junit47 - 3.0.0-M5 - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.2.0 - - - attach-javadocs - package - - jar - - - - - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.1.1 - - - validate - validate - - CodeStyle/checkstyle.xml - true - false - false - true - basedir=${project.basedir} - - - check - - - - - - com.puppycrawl.tools - checkstyle - 8.29 - - - com.github.sevntu-checkstyle - sevntu-checks - 1.35.0 - - - - - org.apache.maven.plugins - maven-pmd-plugin - 3.13.0 - - - cpd - validate - - cpd - - - 50 - - - - cpd-check - validate - - cpd-check - - - true - - - - + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.8 + true + + ossrh + https://oss.sonatype.org/ + true + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + + attach-javadocs + + jar + + + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + - + + + + From 69bb57e7cf741edf3e70b18e520fa36118d10b4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreira?= Date: Wed, 10 Feb 2021 16:05:44 +0000 Subject: [PATCH 03/23] TEC-11009 Update README with contribution instructions (#3) --- README.md | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cd13d3b..28b4549 100644 --- a/README.md +++ b/README.md @@ -60,4 +60,41 @@ or logger.warn(... ``` -etc. \ No newline at end of file +etc. + +## Getting in touch + +* **[GitHub Issues](https://github.com/ebx/ebx-structuredlogging-sdk/issues/new)**: If you have ideas, bugs, +or problems with our library, just open a new issue. + +## Contributing + +If you would like to get involved please follow the instructions +[here](https://github.com/ebx/ebx-structuredlogging-sdk/tree/master/CONTRIBUTING.md) + +## Releases + +We use [semantic versioning](https://semver.org/). + +All merges into DEV will automatically get released as a maven central snapshot, which can be easily +included in any downstream dependencies that always desire the latest changes (see above for +'Most Up To Date' installation). + +Each merge into the MASTER branch will automatically get released to Maven central and github +releases, using the current library version. As such, following every merge to master, the version +number of the dev branch should be incremented and will represent 'Work In Progress' towards the +next release. + +Please use a merge (not rebase) commit when merging dev into master to perform the release. + +To create a full release to Maven central please follow these steps: +1. Ensure the `CHANGELOG.md` is up to date with all the changes in the release, if not please raise +a suitable PR into `DEV`. Typically the change log should be updated as we go. +3. Create a PR from `DEV` into `MASTER`. Ensure the version in the `pom.xml` is the +correct version to be released. Merging this PR into `MASTER` will automatically create the maven +and github releases. Please note that a release is final, it can not be undone/deleted/overwritten. +5. Once the public release has been successful create a final PR into `DEV` that contains an +incremented `pom.xml` version to ensure the correct snapshot gets updated on subsequent merges +into `DEV`. This PR should also include: + * An update to the `README.md` latest stable release version number. + * A 'Work In Progress' entry for the next anticipated release in `CHANGELOG.md`. \ No newline at end of file From 9891573cf522f239c48ff7f9999a81aeba786ccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreira?= Date: Thu, 9 Sep 2021 17:06:47 +0100 Subject: [PATCH 04/23] TEC-13023 Update release token for new TravisCI release version (#4) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b28f25e..2ce21c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,12 +43,12 @@ before_deploy: deploy: provider: releases api_key: - secure: vUHGrM4IGMwUhGzzHSRIk/CvB6xCLsee49Mci7hnge+qkHHMOWdfZxQkFSzQua53ekEEO73rPam3pqpIkHvYHIjLt1h08J85g7pXDWDu0/QLimMhI5YVdP1cGgQlrZ8SQM8AbenUIVqQCvAtHfV7qOnsSG472zRFmG2WEgNGyPVxg/kFCfP7de+C1LY8yVilsDKQip7ZMGFhInhEvE2VvR3ja+iBe23/+lSB8Ucfx4BezBHIynOzVY5REHuL0fstGy5vpxyCJ4gj/9jJxQ3X9S1W+hMyT22c8BG1wPpQn3jW80PcSctD4kXpLZuQXDbvqugyeYt4oeUwSMde1InLs44AAU2LGcCQidvpPRD1G6gZ11wvReKlUFiFT53c1Vs4Hq4kd26dvBK5dqF5WcAXklDD8QVmMvmkyxs6GatSS2VcVr6VDlZ/pnMdG8ZAS4yGln2DVLa7ZonCmuZBJvGCiompp9Smm5TZiLWxcKPYw0sICuZY/ecbHV+ZEdkEcjdMRg8uxyReuxjaeJZbQ+JqVANqfbpXzGVL8FpE9+aJerA/ScuKdrJkyse4hnXBbBqF3Go/9Ky9gvyuEF8piPbo9uR7FDvlkdz5deYFq9x/upQ9zs2Q3KTTKYpQP1VcOmFCAVZNIMqqMeTj0yNiZtSY20mfI1uDqUcH6H9GpbOD2Gk= + secure: kTnvdNJQI8ji6h7A5SREMRnSeYnE+u40dcjN9qk2kK0hLfpM8ZGdyDdwSG8Nz4hLUnJDgais8wCcr/NFYwfRjZG1tb9YCAWzsTerC7y9Zs80WhNI9dmZdr0+RILlS2Cu6nFmurpH90c+w/y5ClEXB5Ip/PDhh0W9wHKMGXmgsvhk5TBNPCaxGNp+z+i6IWPpE2sYSBFk3gkbTLZ2wswjgZ6AAfhy/doOZxBQwQwoZ6fNuVPW54E5JJUI71xQnjupHjYqjcv0dHhkr0B3u9fy0S6SbWMhfhRCnl52KdXBti/v/JTsLkCx6GlfNpc4JsmsSnec2iYEVpH+wTeIiTj+LJ3BPx6YjbHu104cVSkhU16d40s6ioNTawp0XVDDcHTOLI85wjRfXzfMqOlfy23TR9Ec+NFVicqdnzMiXGRMWXUv+gnJn7U52v6qWofUf3Tzao0wOuH0dVANJkrib4mKS3OseBvfqpZmKvujvjALkljBrttU4SHrMrFbeWVvETnsBUTdEHqao6j0echWxASSlrtV7AzJtQ0f4qtuNUhpVmsw/sOzmXo4WUQUgffPXoiGSYU1Bs71xejwC2z8yLsN6rMOY5LGtTltO2QphnVYwz+IKQS2SonVuroMCW7f3ZP5ZsyUDCk1tUCsOpfGksKiyrv2xHtskvY+W5eGz/TP8Ow= file: - target/ebx-structuredlogging-sdk-$MVN_VERSION.jar - target/ebx-structuredlogging-sdk-$MVN_VERSION-javadoc.jar - target/ebx-structuredlogging-sdk-$MVN_VERSION-sources.jar - skip_cleanup: true + edge: true on: repo: $REPO branch: $RELEASE_BRANCH From 5257006fecdf453dc840da7ce034f3a0ea0031f7 Mon Sep 17 00:00:00 2001 From: Dougal Rea <73436291+dougalrea@users.noreply.github.com> Date: Wed, 3 May 2023 14:03:31 +0100 Subject: [PATCH 05/23] SL-5990 Roll out CircleCI deployment infrastructure to structuredlogging-sdk (#6) * SL-5990 Roll out CircleCI deployment infrastructure to structuredlogging-sdk * Update pom.xml * Update pom.xml --- .circleci/config.yml | 67 +++++++++++++++++++ .travis.yml | 59 ---------------- .../Build-Scripts/export_mvn_version.sh | 33 --------- Infrastructure/Build-Scripts/mvn_deploy.sh | 57 ++++++++++++++++ .../{build_sdk_travis.sh => mvn_verify.sh} | 17 +++-- .../Build-Scripts/validate_build.sh | 24 ++----- pom.xml | 11 ++- 7 files changed, 149 insertions(+), 119 deletions(-) create mode 100644 .circleci/config.yml delete mode 100644 .travis.yml delete mode 100644 Infrastructure/Build-Scripts/export_mvn_version.sh create mode 100644 Infrastructure/Build-Scripts/mvn_deploy.sh rename Infrastructure/Build-Scripts/{build_sdk_travis.sh => mvn_verify.sh} (60%) diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..0ed048f --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,67 @@ +version: 2.1 +orbs: + gh: circleci/github-cli@2.1.0 + +workflows: + version: 2 + pr_build: + when: + not: + or: + - equal: [ dev, << pipeline.git.branch >> ] + - equal: [ master, << pipeline.git.branch >> ] + jobs: + # Performs a verify build for PRs + - validate: + context: + - Non-sensitive Env Vars + - maven_verify: + context: Non-sensitive Env Vars + requires: + - validate + + stage_or_release_build: + when: + or: + - equal: [ dev, << pipeline.git.branch >> ] + - equal: [ master, << pipeline.git.branch >> ] + jobs: + # Deploys to maven central for dev (snapshot) and master builds + - validate: + context: + - Non-sensitive Env Vars + - maven_deploy: + context: + - Open Source Release Credentials + - Non-sensitive Env Vars + requires: + - validate + +jobs: + validate: + machine: + image: ubuntu-2204:2023.02.1 + steps: + - checkout + - run: + name: "List installed packages" + command: apt list --installed + - run: + name: "Validate build" + command: source Infrastructure/Build-Scripts/validate_build.sh + maven_verify: + machine: + image: ubuntu-2204:2023.02.1 + steps: + - checkout + - run: + name: "Perform Maven Verify" + command: source Infrastructure/Build-Scripts/mvn_verify.sh + maven_deploy: + machine: + image: ubuntu-2204:2023.02.1 + steps: + - checkout + - run: + name: "Deploy to Maven Central" + command: source Infrastructure/Build-Scripts/mvn_deploy.sh diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2ce21c6..0000000 --- a/.travis.yml +++ /dev/null @@ -1,59 +0,0 @@ -language: java -dist: trusty -sudo: false # faster builds - -# safelist -branches: - only: - - master - - dev - -env: - global: - - DEV_BRANCH=dev - - RELEASE_BRANCH=master - - REPO=ebx/ebx-structuredlogging-sdk - - NO_COLOUR='\033[0m' - - RED_COLOUR='\033[0;31m' - - GREEN_COLOUR='\033[0;32m' - -before_script: - - export SOURCE_BRANCH_NAME=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then echo $TRAVIS_BRANCH; else echo $TRAVIS_PULL_REQUEST_BRANCH; fi) - - echo $GPG_SECRET_KEYS | base64 --decode | $GPG_EXECUTABLE --import || echo "Failed to import GPG_SECRET_KEYS (probably because this branch is a PR)." - - echo $GPG_OWNERTRUST | base64 --decode | $GPG_EXECUTABLE --import-ownertrust || echo "Failed to import GPG_OWNERTRUST (probably because this branch is a PR)." - - source Infrastructure/Build-Scripts/export_mvn_version.sh - - source Infrastructure/Build-Scripts/validate_build.sh - -script: - - source Infrastructure/Build-Scripts/build_sdk_travis.sh - -after_failure: - - cat target/surefire-reports/*.txt - -## Prepare the release for Github -## Ensure we have a suitable git tag for the release based on the verison number -before_deploy: - # Set up git user name and tag this commit - - git config --local user.name "MarcFletcher" - - git config --local user.email "marc@echobox.com" - - export DEPLOY_TAG=v$MVN_VERSION - - git tag $DEPLOY_TAG - -## Create the release in Github -deploy: - provider: releases - api_key: - secure: kTnvdNJQI8ji6h7A5SREMRnSeYnE+u40dcjN9qk2kK0hLfpM8ZGdyDdwSG8Nz4hLUnJDgais8wCcr/NFYwfRjZG1tb9YCAWzsTerC7y9Zs80WhNI9dmZdr0+RILlS2Cu6nFmurpH90c+w/y5ClEXB5Ip/PDhh0W9wHKMGXmgsvhk5TBNPCaxGNp+z+i6IWPpE2sYSBFk3gkbTLZ2wswjgZ6AAfhy/doOZxBQwQwoZ6fNuVPW54E5JJUI71xQnjupHjYqjcv0dHhkr0B3u9fy0S6SbWMhfhRCnl52KdXBti/v/JTsLkCx6GlfNpc4JsmsSnec2iYEVpH+wTeIiTj+LJ3BPx6YjbHu104cVSkhU16d40s6ioNTawp0XVDDcHTOLI85wjRfXzfMqOlfy23TR9Ec+NFVicqdnzMiXGRMWXUv+gnJn7U52v6qWofUf3Tzao0wOuH0dVANJkrib4mKS3OseBvfqpZmKvujvjALkljBrttU4SHrMrFbeWVvETnsBUTdEHqao6j0echWxASSlrtV7AzJtQ0f4qtuNUhpVmsw/sOzmXo4WUQUgffPXoiGSYU1Bs71xejwC2z8yLsN6rMOY5LGtTltO2QphnVYwz+IKQS2SonVuroMCW7f3ZP5ZsyUDCk1tUCsOpfGksKiyrv2xHtskvY+W5eGz/TP8Ow= - file: - - target/ebx-structuredlogging-sdk-$MVN_VERSION.jar - - target/ebx-structuredlogging-sdk-$MVN_VERSION-javadoc.jar - - target/ebx-structuredlogging-sdk-$MVN_VERSION-sources.jar - edge: true - on: - repo: $REPO - branch: $RELEASE_BRANCH - name: v$MVN_VERSION - -cache: - directories: - - ~/.m2/repository diff --git a/Infrastructure/Build-Scripts/export_mvn_version.sh b/Infrastructure/Build-Scripts/export_mvn_version.sh deleted file mode 100644 index ad32e4d..0000000 --- a/Infrastructure/Build-Scripts/export_mvn_version.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -## -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You 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. -## - -export MVN_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout|grep -v '\[') -## If this is not master we dynamically set the version to a snapshot -if [ "$SOURCE_BRANCH_NAME" != "$RELEASE_BRANCH" ]; then - mvn versions:set -q -DnewVersion=$MVN_VERSION-SNAPSHOT - export MVN_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout|grep -v '\[') - printf "${GREEN_COLOUR}Build version modified to $MVN_VERSION as this is not the $RELEASE_BRANCH branch.${NO_COLOUR}\n" -else - printf "${GREEN_COLOUR}Build version not modified as this is the $RELEASE_BRANCH branch.${NO_COLOUR}\n" -fi - -#Ensure the project verison is valid -if ! [[ $MVN_VERSION =~ ^[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then - printf "${RED_COLOUR}The extracted project version '$MVN_VERSION' was not valid.${NO_COLOUR}\n" - travis_terminate 1; -fi diff --git a/Infrastructure/Build-Scripts/mvn_deploy.sh b/Infrastructure/Build-Scripts/mvn_deploy.sh new file mode 100644 index 0000000..018bcc7 --- /dev/null +++ b/Infrastructure/Build-Scripts/mvn_deploy.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# shellcheck disable=SC2059 +set -euo pipefail +## +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +## + +## For DEV and MASTER deploy to maven central (DEV will deploy a snapshot) +## All other builds (eg PR builds) are verified by separate script mvn_verify.sh +export JAVA_HOME="/usr" + +get_mvn_version() { + mvn help:evaluate -Dexpression=project.version -q -DforceStdout|grep -v '\[' +} + +if [ "${CIRCLE_BRANCH}" != "${DEV_BRANCH}" ] && [ "${CIRCLE_BRANCH}" != "${RELEASE_BRANCH}" ]; then + # Exit with error if this is not dev or master branch + printf "${RED_COLOUR}Deployments to maven central should only be triggered from ${DEV_BRANCH} and ${RELEASE_BRANCH} branches.${NO_COLOUR}\n" + exit 1 +else + printf "${GREEN_COLOUR}Performing deploy build to maven central.${NO_COLOUR}\n" + mvn_version=$(get_mvn_version) + + # If this is not master we dynamically set the version to a snapshot + if [ "${CIRCLE_BRANCH}" != "${RELEASE_BRANCH}" ]; then + printf "${GREEN_COLOUR}Appending '-SNAPSHOT' to version as this is not the ${RELEASE_BRANCH} branch.${NO_COLOUR}\n" + mvn versions:set -q -DnewVersion="${mvn_version}-SNAPSHOT" + + mvn_version=$(get_mvn_version) + printf "${GREEN_COLOUR}Build version modified to ${mvn_version}.${NO_COLOUR}\n" + fi + + # Ensure the project verison is valid + if ! [[ ${mvn_version} =~ ^[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then + printf "${RED_COLOUR}The extracted project version '${mvn_version}' was not valid.${NO_COLOUR}\n" + exit 1; + fi + + echo "${GPG_SECRET_KEYS}" | base64 --decode | $GPG_EXECUTABLE --import --batch --passphrase "${GPG_PASSPHRASE}" || echo "Failed to import GPG_SECRET_KEYS." + echo "${GPG_OWNERTRUST}" | base64 --decode | $GPG_EXECUTABLE --import-ownertrust --batch --passphrase "${GPG_PASSPHRASE}" || echo "Failed to import GPG_OWNERTRUST." + + # Deploy to maven central + mvn clean deploy --settings .maven.xml -B -U -Prelease +fi diff --git a/Infrastructure/Build-Scripts/build_sdk_travis.sh b/Infrastructure/Build-Scripts/mvn_verify.sh similarity index 60% rename from Infrastructure/Build-Scripts/build_sdk_travis.sh rename to Infrastructure/Build-Scripts/mvn_verify.sh index 5e242fe..4cd4067 100644 --- a/Infrastructure/Build-Scripts/build_sdk_travis.sh +++ b/Infrastructure/Build-Scripts/mvn_verify.sh @@ -1,4 +1,6 @@ #!/bin/bash +set -euo pipefail +# shellcheck disable=SC2059 ## # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with @@ -16,12 +18,15 @@ # limitations under the License. ## -## For DEV and MASTER deploy to maven central (DEV will always be a snapshot) -## All other builds are simply verified -if [ "$SOURCE_BRANCH_NAME" == "$RELEASE_BRANCH" ] || [ "$SOURCE_BRANCH_NAME" == "$DEV_BRANCH" ]; then - printf "${GREEN_COLOUR}Performing deploy build to maven central.${NO_COLOUR}\n" - mvn clean deploy --settings .maven.xml -B -U -Prelease +## For PR builds, perform maven verify. Exit with error if dev or master +## as these are handled separately in mvn_deploy.sh +export JAVA_HOME="/usr" + +if [ "$CIRCLE_BRANCH" == "${DEV_BRANCH}" ] || [ "$CIRCLE_BRANCH" == "${RELEASE_BRANCH}" ]; then + printf "${RED_COLOUR}ERROR: PR builds should not be triggered by ${DEV_BRANCH} or ${RELEASE_BRANCH} branches.${NO_COLOUR}\n" + exit 1 else - printf "${GREEN_COLOUR}Performing a PR verify build. Releases are only created from $DEV_BRANCH and $RELEASE_BRANCH branches.${NO_COLOUR}\n" + printf "${GREEN_COLOUR}Performing a PR verify build on PR #${CIRCLE_PULL_REQUEST##*/}.${NO_COLOUR}\n" + java --version mvn clean verify fi diff --git a/Infrastructure/Build-Scripts/validate_build.sh b/Infrastructure/Build-Scripts/validate_build.sh index ca06501..71069e2 100644 --- a/Infrastructure/Build-Scripts/validate_build.sh +++ b/Infrastructure/Build-Scripts/validate_build.sh @@ -1,4 +1,6 @@ #!/bin/bash +set -euo pipefail +# shellcheck disable=SC2059 ## # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with @@ -16,24 +18,8 @@ # limitations under the License. ## -if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then - printf "${GREEN_COLOUR}Building base branch $SOURCE_BRANCH_NAME which is at version $MVN_VERSION.${NO_COLOUR}\n" +if [ "${CIRCLE_BRANCH}" == "${RELEASE_BRANCH}" ] || [ "${CIRCLE_BRANCH}" == "${DEV_BRANCH}" ]; then + printf "${GREEN_COLOUR}Building base branch $CIRCLE_BRANCH.${NO_COLOUR}\n" else - #Get the PR title - export PR_TITLE=$(curl -s https://api.github.com/repos/$REPO/pulls/$TRAVIS_PULL_REQUEST | grep -Po '(?<="title":[[:space:]]")[^"]*(?=",)') - - printf "${GREEN_COLOUR}Building PR #$TRAVIS_PULL_REQUEST '$PR_TITLE' from branch $SOURCE_BRANCH_NAME (into $TRAVIS_BRANCH)${NO_COLOUR}\n" - - ##Disabled as travis keeps getting rate limited by github - ##Ensure the PR name matches our expected format - #if ! [[ $PR_TITLE =~ ^[A-Z]{2,4}-[0-9]+[[:space:]].+$ ]]; then - # printf "${RED_COLOUR}PR title '$PR_TITLE' does not match the expected format 'GH-[xxxx] [description]'.${NO_COLOUR}\n" - # travis_terminate 1; - #fi - - #Ensure PR cannot be into master, unless it's coming from dev - if [ "$TRAVIS_BRANCH" == "$RELEASE_BRANCH" ] && [ "$SOURCE_BRANCH_NAME" != "$DEV_BRANCH" ]; then - printf "${RED_COLOUR}Build failed as PR target is master. Please ensure you use $DEV_BRANCH as the target.${NO_COLOUR}\n" - travis_terminate 1; - fi + printf "${GREEN_COLOUR}Building PR #${CIRCLE_PULL_REQUEST##*/} '${CIRCLE_PULL_REQUEST}' from branch ${CIRCLE_BRANCH} (into ${DEV_BRANCH})${NO_COLOUR}\n" fi diff --git a/pom.xml b/pom.xml index ff4fe3b..4b898e5 100644 --- a/pom.xml +++ b/pom.xml @@ -189,7 +189,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.6.13 true ossrh @@ -229,7 +229,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.6 + 3.0.1 sign-artifacts @@ -237,6 +237,13 @@ sign + + + + --pinentry-mode + loopback + + From 60b83ef86e6a0b341953ffae5f2683fcbad16a85 Mon Sep 17 00:00:00 2001 From: Edd Spencer Date: Wed, 3 May 2023 14:48:30 +0100 Subject: [PATCH 06/23] SL-5978 Create escalation logger class (#5) * SL-5978 initial class structure * SL-5978 Add tests * SL-5978 Update CHANGELOG * SL-5978 Polish * SL-5978 Review fixes --------- Co-authored-by: Edd Spencer --- CHANGELOG.md | 4 + README.md | 2 +- pom.xml | 16 +- .../logging/escalator/EscalationAction.java | 33 ++ .../logging/escalator/EscalationLogger.java | 455 ++++++++++++++++++ .../logging/escalator/EscalationTrigger.java | 34 ++ .../logging/escalator/LoggingLevel.java | 46 ++ .../escalator/EscalationLoggerTest.java | 97 ++++ 8 files changed, 685 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/echobox/logging/escalator/EscalationAction.java create mode 100644 src/main/java/com/echobox/logging/escalator/EscalationLogger.java create mode 100644 src/main/java/com/echobox/logging/escalator/EscalationTrigger.java create mode 100644 src/main/java/com/echobox/logging/escalator/LoggingLevel.java create mode 100644 src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 63094f9..896b7bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,3 +3,7 @@ ## 1.0.0 (Jan 1, 2014) * Initial release + +## 1.1.0 (May 2, 2023) + +* Create EscalationLogger class to all for automatic escalation based off of log messages. diff --git a/README.md b/README.md index 28b4549..e05415d 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ structured arguments to be included in `ch.qos.logback.classic.net.SyslogAppende com.echobox ebx-structuredlogging-sdk - 1.0.0 + 1.1.0 ``` diff --git a/pom.xml b/pom.xml index 4b898e5..ed1d8a9 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ com.echobox ebx-structuredlogging-sdk - 1.0.0 + 1.1.0 jar @@ -72,6 +72,20 @@ logstash-logback-encoder 6.4 + + + + org.junit.jupiter + junit-jupiter + 5.9.3 + test + + + org.mockito + mockito-core + 5.2.0 + test + diff --git a/src/main/java/com/echobox/logging/escalator/EscalationAction.java b/src/main/java/com/echobox/logging/escalator/EscalationAction.java new file mode 100644 index 0000000..233fe17 --- /dev/null +++ b/src/main/java/com/echobox/logging/escalator/EscalationAction.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging.escalator; + +/** + * Interface to do an escalation action once the desired trigger threshold has been met + * + * @author eddspencer + */ +public interface EscalationAction { + + /** + * An escalation has been triggered with the given keys + * + * @param keys the keys + */ + void escalate(Object... keys); +} diff --git a/src/main/java/com/echobox/logging/escalator/EscalationLogger.java b/src/main/java/com/echobox/logging/escalator/EscalationLogger.java new file mode 100644 index 0000000..8c286f3 --- /dev/null +++ b/src/main/java/com/echobox/logging/escalator/EscalationLogger.java @@ -0,0 +1,455 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging.escalator; + +import org.slf4j.Logger; +import org.slf4j.Marker; + +/** + * Logger wrapper that will escalate to another action if a certain trigger function passes on a + * logger. For example, if 10 debug messages of the same text are made within 10min an + * escalation could be made. + * + * N.B. the original message is still logged even when an escalation is made. + * + * @author eddspencer + */ +public class EscalationLogger implements Logger { + + private final Logger logger; + private final EscalationTrigger trigger; + private final EscalationAction action; + + public EscalationLogger(Logger logger, EscalationTrigger trigger, EscalationAction action) { + this.logger = logger; + this.trigger = trigger; + this.action = action; + } + + private void checkForEscalation(LoggingLevel level, Object... keys) { + if (trigger.markAndTrigger(level, keys)) { + action.escalate(keys); + } + } + + @Override + public String getName() { + return logger.getName(); + } + + @Override + public boolean isTraceEnabled() { + return logger.isTraceEnabled(); + } + + @Override + public boolean isTraceEnabled(Marker marker) { + return logger.isTraceEnabled(marker); + } + + @Override + public void trace(String msg) { + checkForEscalation(LoggingLevel.TRACE, msg); + + logger.trace(msg); + } + + @Override + public void trace(String format, Object arg) { + checkForEscalation(LoggingLevel.TRACE, format, arg); + + logger.trace(format, arg); + } + + @Override + public void trace(String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.TRACE, format, arg1, arg2); + + logger.trace(format, arg1, arg2); + } + + @Override + public void trace(String format, Object... arguments) { + checkForEscalation(LoggingLevel.TRACE, format, arguments); + + logger.trace(format, arguments); + } + + @Override + public void trace(String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.TRACE, msg, throwable); + + logger.trace(msg, throwable); + } + + @Override + public void trace(Marker marker, String msg) { + checkForEscalation(LoggingLevel.TRACE, marker, msg); + + logger.trace(marker, msg); + } + + @Override + public void trace(Marker marker, String format, Object arg) { + checkForEscalation(LoggingLevel.TRACE, marker, format, arg); + + logger.trace(marker, format, arg); + } + + @Override + public void trace(Marker marker, String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.TRACE, marker, format, arg1, arg2); + + logger.trace(marker, format, arg1, arg2); + } + + @Override + public void trace(Marker marker, String format, Object... argArray) { + checkForEscalation(LoggingLevel.TRACE, marker, format, argArray); + + logger.trace(marker, format, argArray); + } + + @Override + public void trace(Marker marker, String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.TRACE, marker, msg, throwable); + + logger.trace(marker, msg, throwable); + } + + @Override + public boolean isDebugEnabled() { + return logger.isDebugEnabled(); + } + + @Override + public boolean isDebugEnabled(Marker marker) { + return logger.isDebugEnabled(marker); + } + + @Override + public void debug(String msg) { + checkForEscalation(LoggingLevel.DEBUG, msg); + + logger.debug(msg); + } + + @Override + public void debug(String format, Object arg) { + checkForEscalation(LoggingLevel.DEBUG, format, arg); + + logger.debug(format, arg); + } + + @Override + public void debug(String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.DEBUG, format, arg1, arg2); + + logger.debug(format, arg1, arg2); + } + + @Override + public void debug(String format, Object... arguments) { + checkForEscalation(LoggingLevel.DEBUG, format, arguments); + + logger.debug(format, arguments); + } + + @Override + public void debug(String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.DEBUG, msg, throwable); + + logger.debug(msg, throwable); + } + + @Override + public void debug(Marker marker, String msg) { + checkForEscalation(LoggingLevel.DEBUG, marker, msg); + + logger.debug(marker, msg); + } + + @Override + public void debug(Marker marker, String format, Object arg) { + checkForEscalation(LoggingLevel.DEBUG, marker, format, arg); + + logger.debug(marker, format, arg); + } + + @Override + public void debug(Marker marker, String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.DEBUG, marker, arg1, arg2); + + logger.debug(marker, format, arg1, arg2); + } + + @Override + public void debug(Marker marker, String format, Object... arguments) { + checkForEscalation(LoggingLevel.DEBUG, marker, format, arguments); + + logger.debug(marker, format, arguments); + } + + @Override + public void debug(Marker marker, String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.DEBUG, marker, msg, throwable); + + logger.debug(marker, msg, throwable); + } + + @Override + public boolean isInfoEnabled() { + return logger.isInfoEnabled(); + } + + @Override + public boolean isInfoEnabled(Marker marker) { + return logger.isInfoEnabled(marker); + } + + @Override + public void info(String msg) { + checkForEscalation(LoggingLevel.INFO, msg); + + logger.info(msg); + } + + @Override + public void info(String format, Object arg) { + checkForEscalation(LoggingLevel.INFO, format, arg); + + logger.info(format, arg); + } + + @Override + public void info(String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.INFO, arg1, arg2); + + logger.info(format, arg1, arg2); + } + + @Override + public void info(String format, Object... arguments) { + checkForEscalation(LoggingLevel.INFO, format, arguments); + + logger.info(format, arguments); + } + + @Override + public void info(String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.INFO, msg, throwable); + + logger.info(msg, throwable); + } + + @Override + public void info(Marker marker, String msg) { + checkForEscalation(LoggingLevel.INFO, marker, msg); + + logger.info(marker, msg); + } + + @Override + public void info(Marker marker, String format, Object arg) { + checkForEscalation(LoggingLevel.INFO, marker, arg); + + logger.info(marker, format, arg); + } + + @Override + public void info(Marker marker, String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.INFO, marker, arg1, arg2); + + logger.info(marker, format, arg1, arg2); + } + + @Override + public void info(Marker marker, String format, Object... arguments) { + checkForEscalation(LoggingLevel.INFO, marker, format, arguments); + + logger.info(marker, format, arguments); + } + + @Override + public void info(Marker marker, String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.INFO, marker, msg, throwable); + + logger.info(marker, msg, throwable); + } + + @Override + public boolean isWarnEnabled() { + return logger.isWarnEnabled(); + } + + @Override + public boolean isWarnEnabled(Marker marker) { + return logger.isWarnEnabled(marker); + } + + @Override + public void warn(String msg) { + checkForEscalation(LoggingLevel.WARN, msg); + + logger.warn(msg); + } + + @Override + public void warn(String format, Object arg) { + checkForEscalation(LoggingLevel.WARN, format, arg); + + logger.warn(format, arg); + } + + @Override + public void warn(String format, Object... arguments) { + checkForEscalation(LoggingLevel.WARN, format, arguments); + + logger.warn(format, arguments); + } + + @Override + public void warn(String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.WARN, format, arg1, arg2); + + logger.warn(format, arg1, arg2); + } + + @Override + public void warn(String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.WARN, msg, throwable); + + logger.warn(msg, throwable); + } + + @Override + public void warn(Marker marker, String msg) { + checkForEscalation(LoggingLevel.WARN, marker, msg); + + logger.warn(marker, msg); + } + + @Override + public void warn(Marker marker, String format, Object arg) { + checkForEscalation(LoggingLevel.WARN, marker, format, arg); + + logger.warn(marker, format, arg); + } + + @Override + public void warn(Marker marker, String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.WARN, marker, format, arg1, arg2); + + logger.warn(marker, format, arg1, arg2); + } + + @Override + public void warn(Marker marker, String format, Object... arguments) { + checkForEscalation(LoggingLevel.WARN, marker, format, arguments); + + logger.warn(marker, format, arguments); + } + + @Override + public void warn(Marker marker, String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.WARN, marker, msg, throwable); + + logger.warn(marker, msg, throwable); + } + + @Override + public boolean isErrorEnabled() { + return logger.isErrorEnabled(); + } + + @Override + public boolean isErrorEnabled(Marker marker) { + return logger.isErrorEnabled(marker); + } + + @Override + public void error(String msg) { + checkForEscalation(LoggingLevel.ERROR, msg); + + logger.error(msg); + } + + @Override + public void error(String format, Object arg) { + checkForEscalation(LoggingLevel.ERROR, format, arg); + + logger.error(format, arg); + } + + @Override + public void error(String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.ERROR, format, arg1, arg2); + + logger.error(format, arg1, arg2); + } + + @Override + public void error(String format, Object... arguments) { + checkForEscalation(LoggingLevel.ERROR, format, arguments); + + logger.error(format, arguments); + } + + @Override + public void error(String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.ERROR, msg, throwable); + + logger.error(msg, throwable); + } + + @Override + public void error(Marker marker, String msg) { + checkForEscalation(LoggingLevel.ERROR, marker, msg); + + logger.error(marker, msg); + } + + @Override + public void error(Marker marker, String format, Object arg) { + checkForEscalation(LoggingLevel.ERROR, marker, format, arg); + + logger.error(marker, format, arg); + } + + @Override + public void error(Marker marker, String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.ERROR, marker, format, arg1, arg2); + + logger.error(marker, format, arg1, arg2); + } + + @Override + public void error(Marker marker, String format, Object... arguments) { + checkForEscalation(LoggingLevel.ERROR, marker, format, arguments); + + logger.error(marker, format, arguments); + } + + @Override + public void error(Marker marker, String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.ERROR, marker, msg, throwable); + + logger.error(marker, msg, throwable); + } + +} diff --git a/src/main/java/com/echobox/logging/escalator/EscalationTrigger.java b/src/main/java/com/echobox/logging/escalator/EscalationTrigger.java new file mode 100644 index 0000000..b98620d --- /dev/null +++ b/src/main/java/com/echobox/logging/escalator/EscalationTrigger.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging.escalator; + +/** + * Interface to mark an event and return if this should result in an escalation + * + * @author eddspencer + */ +public interface EscalationTrigger { + /** + * Mark the logging event for the given keys and check if escalation is triggered + * + * @param level the level + * @param keys the keys + * @return whether to trigger and escalation + */ + boolean markAndTrigger(LoggingLevel level, Object... keys); +} diff --git a/src/main/java/com/echobox/logging/escalator/LoggingLevel.java b/src/main/java/com/echobox/logging/escalator/LoggingLevel.java new file mode 100644 index 0000000..3ef9d34 --- /dev/null +++ b/src/main/java/com/echobox/logging/escalator/LoggingLevel.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging.escalator; + +/** + * Logging levels to use in tracking events + * + * @author eddspencer + */ +enum LoggingLevel { + /** + * TRACE logging level + */ + TRACE, + /** + * DEBUG logging level + */ + DEBUG, + /** + * INFO logging level + */ + INFO, + /** + * WARN logging level + */ + WARN, + /** + * ERROR logging level + */ + ERROR; +} diff --git a/src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java b/src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java new file mode 100644 index 0000000..40f6d0e --- /dev/null +++ b/src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging.escalator; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.slf4j.Logger; + +class EscalationLoggerTest { + + private EscalationTrigger trigger; + private EscalationAction action; + private EscalationLogger escalationLogger; + + @BeforeEach + public void setup() { + trigger = Mockito.mock(EscalationTrigger.class); + action = Mockito.mock(EscalationAction.class); + + final Logger logger = Mockito.mock(Logger.class); + escalationLogger = new EscalationLogger(logger, trigger, action); + } + + @Test + public void notEscalateButTriggered() { + escalationLogger.debug("This is a test"); + + verify(action, times(0)).escalate("This is a test"); + } + + @Test + public void escalateTRACE() { + when(trigger.markAndTrigger(LoggingLevel.TRACE, "This is a {}", "test")).thenReturn(true); + + escalationLogger.trace("This is a {}", "test"); + + verify(action).escalate("This is a {}", "test"); + } + + @Test + public void escalateDEBUG() { + when(trigger.markAndTrigger(LoggingLevel.DEBUG, "This is a test")).thenReturn(true); + + escalationLogger.debug("This is a test"); + + verify(action).escalate("This is a test"); + } + + @Test + public void escalateINFO() { + when(trigger.markAndTrigger(LoggingLevel.INFO, "This is a test")).thenReturn(true); + + escalationLogger.info("This is a test"); + + verify(action).escalate("This is a test"); + } + + @Test + public void escalateWARN() { + when(trigger.markAndTrigger(LoggingLevel.WARN, "This is a test")).thenReturn(true); + + escalationLogger.warn("This is a test"); + + verify(action).escalate("This is a test"); + } + + @Test + public void escalateERROR() { + Exception error = new Exception("Error"); + when(trigger.markAndTrigger(LoggingLevel.ERROR, "This is a test", error)).thenReturn(true); + + escalationLogger.error("This is a test", error); + + verify(action).escalate("This is a test", error); + } + +} \ No newline at end of file From 6e9eb5e49f0c5ef759d0554a50f63fdb3bf43432 Mon Sep 17 00:00:00 2001 From: Edd Spencer Date: Tue, 9 May 2023 10:35:18 +0100 Subject: [PATCH 07/23] SL-5978 Create TimeBasedEscalationTrigger to use with EscalationLogger. (#7) * SL-5978 initial class structure * SL-5978 Add tests * SL-5978 Update CHANGELOG * SL-5978 Polish * SL-5978 Review fixes * SL-5978 Create TimeBasedEscalationTrigger to use with escalation logger * SL-5978 Update changelog * SL-5978 Polish * SL-5978 Add event key filter * SL-5978 Add event count * SL-5978 Ensure gets reset if min interval is passed * SL-5978 Review updates * SL-5978 Rename minInterval to refreshInterval --------- Co-authored-by: Edd Spencer --- CHANGELOG.md | 3 +- .../escalator/TimeBasedEscalationTrigger.java | 159 ++++++++++++++++++ .../TimeBasedEscalationTriggerTest.java | 135 +++++++++++++++ 3 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java create mode 100644 src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 896b7bd..a536b1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Initial release -## 1.1.0 (May 2, 2023) +## 1.1.0 (May 4, 2023) * Create EscalationLogger class to all for automatic escalation based off of log messages. +* Create TimeBasedEscalationTrigger to use with EscalationLogger. diff --git a/src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java b/src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java new file mode 100644 index 0000000..398f9b7 --- /dev/null +++ b/src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging.escalator; + +import java.util.Arrays; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +/** + * Implementation of the escalation trigger that triggers and escalation when a particular event + * has been happening at least a minimum amount of times at a given interval for a given period. i + * .e. has been happening consistently for a period of time and over X events in that period. + * + * Uses a {@link ConcurrentHashMap} to store these times in memory. + * + * @author eddspencer + */ +public class TimeBasedEscalationTrigger implements EscalationTrigger { + + private final Supplier unixTimeNow; + private final long minEventCount; + private final int refreshIntervalSecs; + private final int escalationPeriodSecs; + + private final Map cache = new ConcurrentHashMap<>(); + private Predicate keyFilter = key -> true; + + public TimeBasedEscalationTrigger(Supplier unixTimeNow, long minEventCount, + int rereshIntervalSecs, int escalationPeriodSecs) { + this.unixTimeNow = unixTimeNow; + this.minEventCount = minEventCount; + this.refreshIntervalSecs = rereshIntervalSecs; + this.escalationPeriodSecs = escalationPeriodSecs; + } + + public TimeBasedEscalationTrigger(long minEventCount, int refreshIntervalSecs, + int escalationPeriodSecs) { + this.unixTimeNow = () -> System.currentTimeMillis() / 1000; + this.minEventCount = minEventCount; + this.refreshIntervalSecs = refreshIntervalSecs; + this.escalationPeriodSecs = escalationPeriodSecs; + } + + /** + * Sets a filter to only match specific object arguments when generating the even key + * + * @param keyFilter the predicate to use to filter arguments for use in event key + * @return this + */ + public TimeBasedEscalationTrigger withEventKeyFilter(Predicate keyFilter) { + this.keyFilter = keyFilter; + return this; + } + + @Override + public boolean markAndTrigger(LoggingLevel level, Object... keys) { + final String key = createEventKey(level, keys); + final long now = unixTimeNow.get(); + + final AtomicBoolean escalate = new AtomicBoolean(false); + cache.compute(key, (k, eventInfo) -> { + // If we have no other events just cache this one + if (eventInfo == null) { + return new EventInfo(now, now, 1); + } + + final long eventCount = eventInfo.eventCount + 1; + final boolean escalationPeriodPassed = + now - eventInfo.firstSeenUnixTime >= escalationPeriodSecs; + final boolean withinInterval = now - eventInfo.lastSeenUnixTime <= refreshIntervalSecs; + final boolean eventCountExceeded = eventCount >= minEventCount; + + // Trigger escalation and reset event if enough time has passed and event count hit + if (escalationPeriodPassed && withinInterval && eventCountExceeded) { + escalate.set(true); + return null; + } + + // Reset the info if we are outside the refresh interval + if (!withinInterval) { + return new EventInfo(now, now, 1); + } + + // Otherwise update event info + return new EventInfo(eventInfo.firstSeenUnixTime, now, eventCount); + }); + + return escalate.get(); + } + + /** + * Converts the logging level and objects provided to the logger to a unique key that + * identifies the type of event + * + * @param level the logging level + * @param eventArgs the arguments sent to the logging event + * @return the unique key for the event + */ + protected String createEventKey(LoggingLevel level, Object[] eventArgs) { + return String.format("%s::%s", level, + Arrays.stream(eventArgs).filter(keyFilter).map(Object::toString) + .collect(Collectors.joining("_"))); + } + + /** + * Event information for the time based event cache + * + * @author eddspencer + */ + private static class EventInfo { + private final long firstSeenUnixTime; + private final long lastSeenUnixTime; + private final long eventCount; + + private EventInfo(long firstSeenUnixTime, long lastSeenUnixTime, long eventCount) { + this.firstSeenUnixTime = firstSeenUnixTime; + this.lastSeenUnixTime = lastSeenUnixTime; + this.eventCount = eventCount; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + EventInfo eventInfo = (EventInfo) obj; + return firstSeenUnixTime == eventInfo.firstSeenUnixTime + && lastSeenUnixTime == eventInfo.lastSeenUnixTime; + } + + @Override + public int hashCode() { + return Objects.hash(firstSeenUnixTime, lastSeenUnixTime); + } + } +} diff --git a/src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java b/src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java new file mode 100644 index 0000000..fd166eb --- /dev/null +++ b/src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java @@ -0,0 +1,135 @@ +package com.echobox.logging.escalator; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class TimeBasedEscalationTriggerTest { + + private TimeBasedEscalationTrigger trigger; + private long now; + + @BeforeEach + public void setup() { + trigger = new TimeBasedEscalationTrigger(() -> now, 3, 30, 60); + } + + @Test + public void doesNotEscalateOnFirstEvent() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void doesNotEscalateIfNotEnoughTimePassed() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void doesEscalateIfEnoughTimePassed() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void doesNotEscalateIfEnoughTimePassedButFailsMinInterval() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 40; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void doesNotEscalateIfNotEnoughEventsHaveHappened() { + trigger = new TimeBasedEscalationTrigger(() -> now, 4, 30, 60); + + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void allowsEventKeyToBeOverwritten() { + trigger = new TimeBasedEscalationTrigger(() -> now, 2, 30, 60) { + @Override + protected String createEventKey(LoggingLevel level, Object[] eventArgs) { + return "same-key"; + } + }; + + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "other")); + } + + @Test + public void allowsFilteringOfEventArguments() { + trigger = new TimeBasedEscalationTrigger(() -> now, 2, 30, 60) + .withEventKeyFilter(arg -> arg instanceof Exception); + + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1", new Exception("error"))); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event2", new Exception("error"))); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event3", new Exception("error"))); + } + + @Test + public void resetOnEventEscalation() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void resetWhenEventIsMissed() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 40; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void canKeepTrackOfMultipleEventsByLevel() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + assertFalse(trigger.markAndTrigger(LoggingLevel.ERROR, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.ERROR, "event")); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.ERROR, "event")); + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void canKeepTrackOfMultipleEventsByKey() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1")); + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event2")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1")); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1")); + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event2")); + } +} \ No newline at end of file From 255cc9ebdf223b0b2583376cd5fc68e386e3b67b Mon Sep 17 00:00:00 2001 From: Edd Spencer Date: Tue, 9 May 2023 13:30:56 +0100 Subject: [PATCH 08/23] Dev fix (#9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Release v1.0.0 (#2) * Added core implementation. * TEC-11009 Initial Travis-CI setup (#1) * TEC-11009 Initial Travis-CI setup * TEC-11009 Add missing Maven config file * TEC-11009 Update Travis configuration and project files * TEC-11009 Update .gitignore * TEC-11009 Add PR template * TEC-11009 Update Changelog and pom.xml files * TEC-11009 Update secure key for current repo * TEC-11009 Fix pom.xml file Co-authored-by: João Moreira * Remove unnecessary files --------- Co-authored-by: MarcF Co-authored-by: João Moreira Co-authored-by: Edd Spencer From 0a64658b9dd73d27466fd2c155ca0135edd099ef Mon Sep 17 00:00:00 2001 From: Jack Ellis <76243490+jack7ellis@users.noreply.github.com> Date: Wed, 21 Jun 2023 15:04:03 +0100 Subject: [PATCH 09/23] SL-6587 - Remove Escalation classes. Now part of ebx-escalationlogging-sdk. (#11) --- CHANGELOG.md | 5 + README.md | 2 +- pom.xml | 16 +- .../logging/escalator/EscalationAction.java | 33 -- .../logging/escalator/EscalationLogger.java | 455 ------------------ .../logging/escalator/EscalationTrigger.java | 34 -- .../logging/escalator/LoggingLevel.java | 46 -- .../escalator/TimeBasedEscalationTrigger.java | 159 ------ .../escalator/EscalationLoggerTest.java | 97 ---- .../TimeBasedEscalationTriggerTest.java | 135 ------ 10 files changed, 7 insertions(+), 975 deletions(-) delete mode 100644 src/main/java/com/echobox/logging/escalator/EscalationAction.java delete mode 100644 src/main/java/com/echobox/logging/escalator/EscalationLogger.java delete mode 100644 src/main/java/com/echobox/logging/escalator/EscalationTrigger.java delete mode 100644 src/main/java/com/echobox/logging/escalator/LoggingLevel.java delete mode 100644 src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java delete mode 100644 src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java delete mode 100644 src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index a536b1b..a355e60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,3 +8,8 @@ * Create EscalationLogger class to all for automatic escalation based off of log messages. * Create TimeBasedEscalationTrigger to use with EscalationLogger. + +## 2.0.0 (June 21, 2023) + +* Remove EscalationLogger and TimeBasedEscalationTrigger classes. These are now part of + ebx-escalatedlogging-sdk. diff --git a/README.md b/README.md index e05415d..54f0937 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ structured arguments to be included in `ch.qos.logback.classic.net.SyslogAppende com.echobox ebx-structuredlogging-sdk - 1.1.0 + 2.0.0 ``` diff --git a/pom.xml b/pom.xml index ed1d8a9..f435a9e 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ com.echobox ebx-structuredlogging-sdk - 1.1.0 + 2.0.0 jar @@ -72,20 +72,6 @@ logstash-logback-encoder 6.4 - - - - org.junit.jupiter - junit-jupiter - 5.9.3 - test - - - org.mockito - mockito-core - 5.2.0 - test - diff --git a/src/main/java/com/echobox/logging/escalator/EscalationAction.java b/src/main/java/com/echobox/logging/escalator/EscalationAction.java deleted file mode 100644 index 233fe17..0000000 --- a/src/main/java/com/echobox/logging/escalator/EscalationAction.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -package com.echobox.logging.escalator; - -/** - * Interface to do an escalation action once the desired trigger threshold has been met - * - * @author eddspencer - */ -public interface EscalationAction { - - /** - * An escalation has been triggered with the given keys - * - * @param keys the keys - */ - void escalate(Object... keys); -} diff --git a/src/main/java/com/echobox/logging/escalator/EscalationLogger.java b/src/main/java/com/echobox/logging/escalator/EscalationLogger.java deleted file mode 100644 index 8c286f3..0000000 --- a/src/main/java/com/echobox/logging/escalator/EscalationLogger.java +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -package com.echobox.logging.escalator; - -import org.slf4j.Logger; -import org.slf4j.Marker; - -/** - * Logger wrapper that will escalate to another action if a certain trigger function passes on a - * logger. For example, if 10 debug messages of the same text are made within 10min an - * escalation could be made. - * - * N.B. the original message is still logged even when an escalation is made. - * - * @author eddspencer - */ -public class EscalationLogger implements Logger { - - private final Logger logger; - private final EscalationTrigger trigger; - private final EscalationAction action; - - public EscalationLogger(Logger logger, EscalationTrigger trigger, EscalationAction action) { - this.logger = logger; - this.trigger = trigger; - this.action = action; - } - - private void checkForEscalation(LoggingLevel level, Object... keys) { - if (trigger.markAndTrigger(level, keys)) { - action.escalate(keys); - } - } - - @Override - public String getName() { - return logger.getName(); - } - - @Override - public boolean isTraceEnabled() { - return logger.isTraceEnabled(); - } - - @Override - public boolean isTraceEnabled(Marker marker) { - return logger.isTraceEnabled(marker); - } - - @Override - public void trace(String msg) { - checkForEscalation(LoggingLevel.TRACE, msg); - - logger.trace(msg); - } - - @Override - public void trace(String format, Object arg) { - checkForEscalation(LoggingLevel.TRACE, format, arg); - - logger.trace(format, arg); - } - - @Override - public void trace(String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.TRACE, format, arg1, arg2); - - logger.trace(format, arg1, arg2); - } - - @Override - public void trace(String format, Object... arguments) { - checkForEscalation(LoggingLevel.TRACE, format, arguments); - - logger.trace(format, arguments); - } - - @Override - public void trace(String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.TRACE, msg, throwable); - - logger.trace(msg, throwable); - } - - @Override - public void trace(Marker marker, String msg) { - checkForEscalation(LoggingLevel.TRACE, marker, msg); - - logger.trace(marker, msg); - } - - @Override - public void trace(Marker marker, String format, Object arg) { - checkForEscalation(LoggingLevel.TRACE, marker, format, arg); - - logger.trace(marker, format, arg); - } - - @Override - public void trace(Marker marker, String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.TRACE, marker, format, arg1, arg2); - - logger.trace(marker, format, arg1, arg2); - } - - @Override - public void trace(Marker marker, String format, Object... argArray) { - checkForEscalation(LoggingLevel.TRACE, marker, format, argArray); - - logger.trace(marker, format, argArray); - } - - @Override - public void trace(Marker marker, String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.TRACE, marker, msg, throwable); - - logger.trace(marker, msg, throwable); - } - - @Override - public boolean isDebugEnabled() { - return logger.isDebugEnabled(); - } - - @Override - public boolean isDebugEnabled(Marker marker) { - return logger.isDebugEnabled(marker); - } - - @Override - public void debug(String msg) { - checkForEscalation(LoggingLevel.DEBUG, msg); - - logger.debug(msg); - } - - @Override - public void debug(String format, Object arg) { - checkForEscalation(LoggingLevel.DEBUG, format, arg); - - logger.debug(format, arg); - } - - @Override - public void debug(String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.DEBUG, format, arg1, arg2); - - logger.debug(format, arg1, arg2); - } - - @Override - public void debug(String format, Object... arguments) { - checkForEscalation(LoggingLevel.DEBUG, format, arguments); - - logger.debug(format, arguments); - } - - @Override - public void debug(String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.DEBUG, msg, throwable); - - logger.debug(msg, throwable); - } - - @Override - public void debug(Marker marker, String msg) { - checkForEscalation(LoggingLevel.DEBUG, marker, msg); - - logger.debug(marker, msg); - } - - @Override - public void debug(Marker marker, String format, Object arg) { - checkForEscalation(LoggingLevel.DEBUG, marker, format, arg); - - logger.debug(marker, format, arg); - } - - @Override - public void debug(Marker marker, String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.DEBUG, marker, arg1, arg2); - - logger.debug(marker, format, arg1, arg2); - } - - @Override - public void debug(Marker marker, String format, Object... arguments) { - checkForEscalation(LoggingLevel.DEBUG, marker, format, arguments); - - logger.debug(marker, format, arguments); - } - - @Override - public void debug(Marker marker, String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.DEBUG, marker, msg, throwable); - - logger.debug(marker, msg, throwable); - } - - @Override - public boolean isInfoEnabled() { - return logger.isInfoEnabled(); - } - - @Override - public boolean isInfoEnabled(Marker marker) { - return logger.isInfoEnabled(marker); - } - - @Override - public void info(String msg) { - checkForEscalation(LoggingLevel.INFO, msg); - - logger.info(msg); - } - - @Override - public void info(String format, Object arg) { - checkForEscalation(LoggingLevel.INFO, format, arg); - - logger.info(format, arg); - } - - @Override - public void info(String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.INFO, arg1, arg2); - - logger.info(format, arg1, arg2); - } - - @Override - public void info(String format, Object... arguments) { - checkForEscalation(LoggingLevel.INFO, format, arguments); - - logger.info(format, arguments); - } - - @Override - public void info(String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.INFO, msg, throwable); - - logger.info(msg, throwable); - } - - @Override - public void info(Marker marker, String msg) { - checkForEscalation(LoggingLevel.INFO, marker, msg); - - logger.info(marker, msg); - } - - @Override - public void info(Marker marker, String format, Object arg) { - checkForEscalation(LoggingLevel.INFO, marker, arg); - - logger.info(marker, format, arg); - } - - @Override - public void info(Marker marker, String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.INFO, marker, arg1, arg2); - - logger.info(marker, format, arg1, arg2); - } - - @Override - public void info(Marker marker, String format, Object... arguments) { - checkForEscalation(LoggingLevel.INFO, marker, format, arguments); - - logger.info(marker, format, arguments); - } - - @Override - public void info(Marker marker, String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.INFO, marker, msg, throwable); - - logger.info(marker, msg, throwable); - } - - @Override - public boolean isWarnEnabled() { - return logger.isWarnEnabled(); - } - - @Override - public boolean isWarnEnabled(Marker marker) { - return logger.isWarnEnabled(marker); - } - - @Override - public void warn(String msg) { - checkForEscalation(LoggingLevel.WARN, msg); - - logger.warn(msg); - } - - @Override - public void warn(String format, Object arg) { - checkForEscalation(LoggingLevel.WARN, format, arg); - - logger.warn(format, arg); - } - - @Override - public void warn(String format, Object... arguments) { - checkForEscalation(LoggingLevel.WARN, format, arguments); - - logger.warn(format, arguments); - } - - @Override - public void warn(String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.WARN, format, arg1, arg2); - - logger.warn(format, arg1, arg2); - } - - @Override - public void warn(String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.WARN, msg, throwable); - - logger.warn(msg, throwable); - } - - @Override - public void warn(Marker marker, String msg) { - checkForEscalation(LoggingLevel.WARN, marker, msg); - - logger.warn(marker, msg); - } - - @Override - public void warn(Marker marker, String format, Object arg) { - checkForEscalation(LoggingLevel.WARN, marker, format, arg); - - logger.warn(marker, format, arg); - } - - @Override - public void warn(Marker marker, String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.WARN, marker, format, arg1, arg2); - - logger.warn(marker, format, arg1, arg2); - } - - @Override - public void warn(Marker marker, String format, Object... arguments) { - checkForEscalation(LoggingLevel.WARN, marker, format, arguments); - - logger.warn(marker, format, arguments); - } - - @Override - public void warn(Marker marker, String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.WARN, marker, msg, throwable); - - logger.warn(marker, msg, throwable); - } - - @Override - public boolean isErrorEnabled() { - return logger.isErrorEnabled(); - } - - @Override - public boolean isErrorEnabled(Marker marker) { - return logger.isErrorEnabled(marker); - } - - @Override - public void error(String msg) { - checkForEscalation(LoggingLevel.ERROR, msg); - - logger.error(msg); - } - - @Override - public void error(String format, Object arg) { - checkForEscalation(LoggingLevel.ERROR, format, arg); - - logger.error(format, arg); - } - - @Override - public void error(String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.ERROR, format, arg1, arg2); - - logger.error(format, arg1, arg2); - } - - @Override - public void error(String format, Object... arguments) { - checkForEscalation(LoggingLevel.ERROR, format, arguments); - - logger.error(format, arguments); - } - - @Override - public void error(String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.ERROR, msg, throwable); - - logger.error(msg, throwable); - } - - @Override - public void error(Marker marker, String msg) { - checkForEscalation(LoggingLevel.ERROR, marker, msg); - - logger.error(marker, msg); - } - - @Override - public void error(Marker marker, String format, Object arg) { - checkForEscalation(LoggingLevel.ERROR, marker, format, arg); - - logger.error(marker, format, arg); - } - - @Override - public void error(Marker marker, String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.ERROR, marker, format, arg1, arg2); - - logger.error(marker, format, arg1, arg2); - } - - @Override - public void error(Marker marker, String format, Object... arguments) { - checkForEscalation(LoggingLevel.ERROR, marker, format, arguments); - - logger.error(marker, format, arguments); - } - - @Override - public void error(Marker marker, String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.ERROR, marker, msg, throwable); - - logger.error(marker, msg, throwable); - } - -} diff --git a/src/main/java/com/echobox/logging/escalator/EscalationTrigger.java b/src/main/java/com/echobox/logging/escalator/EscalationTrigger.java deleted file mode 100644 index b98620d..0000000 --- a/src/main/java/com/echobox/logging/escalator/EscalationTrigger.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -package com.echobox.logging.escalator; - -/** - * Interface to mark an event and return if this should result in an escalation - * - * @author eddspencer - */ -public interface EscalationTrigger { - /** - * Mark the logging event for the given keys and check if escalation is triggered - * - * @param level the level - * @param keys the keys - * @return whether to trigger and escalation - */ - boolean markAndTrigger(LoggingLevel level, Object... keys); -} diff --git a/src/main/java/com/echobox/logging/escalator/LoggingLevel.java b/src/main/java/com/echobox/logging/escalator/LoggingLevel.java deleted file mode 100644 index 3ef9d34..0000000 --- a/src/main/java/com/echobox/logging/escalator/LoggingLevel.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -package com.echobox.logging.escalator; - -/** - * Logging levels to use in tracking events - * - * @author eddspencer - */ -enum LoggingLevel { - /** - * TRACE logging level - */ - TRACE, - /** - * DEBUG logging level - */ - DEBUG, - /** - * INFO logging level - */ - INFO, - /** - * WARN logging level - */ - WARN, - /** - * ERROR logging level - */ - ERROR; -} diff --git a/src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java b/src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java deleted file mode 100644 index 398f9b7..0000000 --- a/src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -package com.echobox.logging.escalator; - -import java.util.Arrays; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -/** - * Implementation of the escalation trigger that triggers and escalation when a particular event - * has been happening at least a minimum amount of times at a given interval for a given period. i - * .e. has been happening consistently for a period of time and over X events in that period. - * - * Uses a {@link ConcurrentHashMap} to store these times in memory. - * - * @author eddspencer - */ -public class TimeBasedEscalationTrigger implements EscalationTrigger { - - private final Supplier unixTimeNow; - private final long minEventCount; - private final int refreshIntervalSecs; - private final int escalationPeriodSecs; - - private final Map cache = new ConcurrentHashMap<>(); - private Predicate keyFilter = key -> true; - - public TimeBasedEscalationTrigger(Supplier unixTimeNow, long minEventCount, - int rereshIntervalSecs, int escalationPeriodSecs) { - this.unixTimeNow = unixTimeNow; - this.minEventCount = minEventCount; - this.refreshIntervalSecs = rereshIntervalSecs; - this.escalationPeriodSecs = escalationPeriodSecs; - } - - public TimeBasedEscalationTrigger(long minEventCount, int refreshIntervalSecs, - int escalationPeriodSecs) { - this.unixTimeNow = () -> System.currentTimeMillis() / 1000; - this.minEventCount = minEventCount; - this.refreshIntervalSecs = refreshIntervalSecs; - this.escalationPeriodSecs = escalationPeriodSecs; - } - - /** - * Sets a filter to only match specific object arguments when generating the even key - * - * @param keyFilter the predicate to use to filter arguments for use in event key - * @return this - */ - public TimeBasedEscalationTrigger withEventKeyFilter(Predicate keyFilter) { - this.keyFilter = keyFilter; - return this; - } - - @Override - public boolean markAndTrigger(LoggingLevel level, Object... keys) { - final String key = createEventKey(level, keys); - final long now = unixTimeNow.get(); - - final AtomicBoolean escalate = new AtomicBoolean(false); - cache.compute(key, (k, eventInfo) -> { - // If we have no other events just cache this one - if (eventInfo == null) { - return new EventInfo(now, now, 1); - } - - final long eventCount = eventInfo.eventCount + 1; - final boolean escalationPeriodPassed = - now - eventInfo.firstSeenUnixTime >= escalationPeriodSecs; - final boolean withinInterval = now - eventInfo.lastSeenUnixTime <= refreshIntervalSecs; - final boolean eventCountExceeded = eventCount >= minEventCount; - - // Trigger escalation and reset event if enough time has passed and event count hit - if (escalationPeriodPassed && withinInterval && eventCountExceeded) { - escalate.set(true); - return null; - } - - // Reset the info if we are outside the refresh interval - if (!withinInterval) { - return new EventInfo(now, now, 1); - } - - // Otherwise update event info - return new EventInfo(eventInfo.firstSeenUnixTime, now, eventCount); - }); - - return escalate.get(); - } - - /** - * Converts the logging level and objects provided to the logger to a unique key that - * identifies the type of event - * - * @param level the logging level - * @param eventArgs the arguments sent to the logging event - * @return the unique key for the event - */ - protected String createEventKey(LoggingLevel level, Object[] eventArgs) { - return String.format("%s::%s", level, - Arrays.stream(eventArgs).filter(keyFilter).map(Object::toString) - .collect(Collectors.joining("_"))); - } - - /** - * Event information for the time based event cache - * - * @author eddspencer - */ - private static class EventInfo { - private final long firstSeenUnixTime; - private final long lastSeenUnixTime; - private final long eventCount; - - private EventInfo(long firstSeenUnixTime, long lastSeenUnixTime, long eventCount) { - this.firstSeenUnixTime = firstSeenUnixTime; - this.lastSeenUnixTime = lastSeenUnixTime; - this.eventCount = eventCount; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - EventInfo eventInfo = (EventInfo) obj; - return firstSeenUnixTime == eventInfo.firstSeenUnixTime - && lastSeenUnixTime == eventInfo.lastSeenUnixTime; - } - - @Override - public int hashCode() { - return Objects.hash(firstSeenUnixTime, lastSeenUnixTime); - } - } -} diff --git a/src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java b/src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java deleted file mode 100644 index 40f6d0e..0000000 --- a/src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -package com.echobox.logging.escalator; - -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.slf4j.Logger; - -class EscalationLoggerTest { - - private EscalationTrigger trigger; - private EscalationAction action; - private EscalationLogger escalationLogger; - - @BeforeEach - public void setup() { - trigger = Mockito.mock(EscalationTrigger.class); - action = Mockito.mock(EscalationAction.class); - - final Logger logger = Mockito.mock(Logger.class); - escalationLogger = new EscalationLogger(logger, trigger, action); - } - - @Test - public void notEscalateButTriggered() { - escalationLogger.debug("This is a test"); - - verify(action, times(0)).escalate("This is a test"); - } - - @Test - public void escalateTRACE() { - when(trigger.markAndTrigger(LoggingLevel.TRACE, "This is a {}", "test")).thenReturn(true); - - escalationLogger.trace("This is a {}", "test"); - - verify(action).escalate("This is a {}", "test"); - } - - @Test - public void escalateDEBUG() { - when(trigger.markAndTrigger(LoggingLevel.DEBUG, "This is a test")).thenReturn(true); - - escalationLogger.debug("This is a test"); - - verify(action).escalate("This is a test"); - } - - @Test - public void escalateINFO() { - when(trigger.markAndTrigger(LoggingLevel.INFO, "This is a test")).thenReturn(true); - - escalationLogger.info("This is a test"); - - verify(action).escalate("This is a test"); - } - - @Test - public void escalateWARN() { - when(trigger.markAndTrigger(LoggingLevel.WARN, "This is a test")).thenReturn(true); - - escalationLogger.warn("This is a test"); - - verify(action).escalate("This is a test"); - } - - @Test - public void escalateERROR() { - Exception error = new Exception("Error"); - when(trigger.markAndTrigger(LoggingLevel.ERROR, "This is a test", error)).thenReturn(true); - - escalationLogger.error("This is a test", error); - - verify(action).escalate("This is a test", error); - } - -} \ No newline at end of file diff --git a/src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java b/src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java deleted file mode 100644 index fd166eb..0000000 --- a/src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.echobox.logging.escalator; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class TimeBasedEscalationTriggerTest { - - private TimeBasedEscalationTrigger trigger; - private long now; - - @BeforeEach - public void setup() { - trigger = new TimeBasedEscalationTrigger(() -> now, 3, 30, 60); - } - - @Test - public void doesNotEscalateOnFirstEvent() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void doesNotEscalateIfNotEnoughTimePassed() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void doesEscalateIfEnoughTimePassed() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void doesNotEscalateIfEnoughTimePassedButFailsMinInterval() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 40; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void doesNotEscalateIfNotEnoughEventsHaveHappened() { - trigger = new TimeBasedEscalationTrigger(() -> now, 4, 30, 60); - - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void allowsEventKeyToBeOverwritten() { - trigger = new TimeBasedEscalationTrigger(() -> now, 2, 30, 60) { - @Override - protected String createEventKey(LoggingLevel level, Object[] eventArgs) { - return "same-key"; - } - }; - - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "other")); - } - - @Test - public void allowsFilteringOfEventArguments() { - trigger = new TimeBasedEscalationTrigger(() -> now, 2, 30, 60) - .withEventKeyFilter(arg -> arg instanceof Exception); - - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1", new Exception("error"))); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event2", new Exception("error"))); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event3", new Exception("error"))); - } - - @Test - public void resetOnEventEscalation() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void resetWhenEventIsMissed() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 40; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void canKeepTrackOfMultipleEventsByLevel() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - assertFalse(trigger.markAndTrigger(LoggingLevel.ERROR, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.ERROR, "event")); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.ERROR, "event")); - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void canKeepTrackOfMultipleEventsByKey() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1")); - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event2")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1")); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1")); - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event2")); - } -} \ No newline at end of file From 53caa5532996eab5c963cd380db884815ab14acc Mon Sep 17 00:00:00 2001 From: Edd Spencer Date: Thu, 29 Jun 2023 09:02:51 +0100 Subject: [PATCH 10/23] Revert "SL-6587 - Remove Escalation classes. Now part of ebx-escalationlogging-sdk. (#11)" This reverts commit 0a64658b --- README.md | 2 +- pom.xml | 16 +- .../logging/escalator/EscalationAction.java | 33 ++ .../logging/escalator/EscalationLogger.java | 455 ++++++++++++++++++ .../logging/escalator/EscalationTrigger.java | 34 ++ .../logging/escalator/LoggingLevel.java | 46 ++ .../escalator/TimeBasedEscalationTrigger.java | 159 ++++++ .../escalator/EscalationLoggerTest.java | 97 ++++ .../TimeBasedEscalationTriggerTest.java | 135 ++++++ 9 files changed, 975 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/echobox/logging/escalator/EscalationAction.java create mode 100644 src/main/java/com/echobox/logging/escalator/EscalationLogger.java create mode 100644 src/main/java/com/echobox/logging/escalator/EscalationTrigger.java create mode 100644 src/main/java/com/echobox/logging/escalator/LoggingLevel.java create mode 100644 src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java create mode 100644 src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java create mode 100644 src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java diff --git a/README.md b/README.md index 54f0937..e05415d 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ structured arguments to be included in `ch.qos.logback.classic.net.SyslogAppende com.echobox ebx-structuredlogging-sdk - 2.0.0 + 1.1.0 ``` diff --git a/pom.xml b/pom.xml index f435a9e..ed1d8a9 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ com.echobox ebx-structuredlogging-sdk - 2.0.0 + 1.1.0 jar @@ -72,6 +72,20 @@ logstash-logback-encoder 6.4 + + + + org.junit.jupiter + junit-jupiter + 5.9.3 + test + + + org.mockito + mockito-core + 5.2.0 + test + diff --git a/src/main/java/com/echobox/logging/escalator/EscalationAction.java b/src/main/java/com/echobox/logging/escalator/EscalationAction.java new file mode 100644 index 0000000..233fe17 --- /dev/null +++ b/src/main/java/com/echobox/logging/escalator/EscalationAction.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging.escalator; + +/** + * Interface to do an escalation action once the desired trigger threshold has been met + * + * @author eddspencer + */ +public interface EscalationAction { + + /** + * An escalation has been triggered with the given keys + * + * @param keys the keys + */ + void escalate(Object... keys); +} diff --git a/src/main/java/com/echobox/logging/escalator/EscalationLogger.java b/src/main/java/com/echobox/logging/escalator/EscalationLogger.java new file mode 100644 index 0000000..8c286f3 --- /dev/null +++ b/src/main/java/com/echobox/logging/escalator/EscalationLogger.java @@ -0,0 +1,455 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging.escalator; + +import org.slf4j.Logger; +import org.slf4j.Marker; + +/** + * Logger wrapper that will escalate to another action if a certain trigger function passes on a + * logger. For example, if 10 debug messages of the same text are made within 10min an + * escalation could be made. + * + * N.B. the original message is still logged even when an escalation is made. + * + * @author eddspencer + */ +public class EscalationLogger implements Logger { + + private final Logger logger; + private final EscalationTrigger trigger; + private final EscalationAction action; + + public EscalationLogger(Logger logger, EscalationTrigger trigger, EscalationAction action) { + this.logger = logger; + this.trigger = trigger; + this.action = action; + } + + private void checkForEscalation(LoggingLevel level, Object... keys) { + if (trigger.markAndTrigger(level, keys)) { + action.escalate(keys); + } + } + + @Override + public String getName() { + return logger.getName(); + } + + @Override + public boolean isTraceEnabled() { + return logger.isTraceEnabled(); + } + + @Override + public boolean isTraceEnabled(Marker marker) { + return logger.isTraceEnabled(marker); + } + + @Override + public void trace(String msg) { + checkForEscalation(LoggingLevel.TRACE, msg); + + logger.trace(msg); + } + + @Override + public void trace(String format, Object arg) { + checkForEscalation(LoggingLevel.TRACE, format, arg); + + logger.trace(format, arg); + } + + @Override + public void trace(String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.TRACE, format, arg1, arg2); + + logger.trace(format, arg1, arg2); + } + + @Override + public void trace(String format, Object... arguments) { + checkForEscalation(LoggingLevel.TRACE, format, arguments); + + logger.trace(format, arguments); + } + + @Override + public void trace(String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.TRACE, msg, throwable); + + logger.trace(msg, throwable); + } + + @Override + public void trace(Marker marker, String msg) { + checkForEscalation(LoggingLevel.TRACE, marker, msg); + + logger.trace(marker, msg); + } + + @Override + public void trace(Marker marker, String format, Object arg) { + checkForEscalation(LoggingLevel.TRACE, marker, format, arg); + + logger.trace(marker, format, arg); + } + + @Override + public void trace(Marker marker, String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.TRACE, marker, format, arg1, arg2); + + logger.trace(marker, format, arg1, arg2); + } + + @Override + public void trace(Marker marker, String format, Object... argArray) { + checkForEscalation(LoggingLevel.TRACE, marker, format, argArray); + + logger.trace(marker, format, argArray); + } + + @Override + public void trace(Marker marker, String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.TRACE, marker, msg, throwable); + + logger.trace(marker, msg, throwable); + } + + @Override + public boolean isDebugEnabled() { + return logger.isDebugEnabled(); + } + + @Override + public boolean isDebugEnabled(Marker marker) { + return logger.isDebugEnabled(marker); + } + + @Override + public void debug(String msg) { + checkForEscalation(LoggingLevel.DEBUG, msg); + + logger.debug(msg); + } + + @Override + public void debug(String format, Object arg) { + checkForEscalation(LoggingLevel.DEBUG, format, arg); + + logger.debug(format, arg); + } + + @Override + public void debug(String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.DEBUG, format, arg1, arg2); + + logger.debug(format, arg1, arg2); + } + + @Override + public void debug(String format, Object... arguments) { + checkForEscalation(LoggingLevel.DEBUG, format, arguments); + + logger.debug(format, arguments); + } + + @Override + public void debug(String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.DEBUG, msg, throwable); + + logger.debug(msg, throwable); + } + + @Override + public void debug(Marker marker, String msg) { + checkForEscalation(LoggingLevel.DEBUG, marker, msg); + + logger.debug(marker, msg); + } + + @Override + public void debug(Marker marker, String format, Object arg) { + checkForEscalation(LoggingLevel.DEBUG, marker, format, arg); + + logger.debug(marker, format, arg); + } + + @Override + public void debug(Marker marker, String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.DEBUG, marker, arg1, arg2); + + logger.debug(marker, format, arg1, arg2); + } + + @Override + public void debug(Marker marker, String format, Object... arguments) { + checkForEscalation(LoggingLevel.DEBUG, marker, format, arguments); + + logger.debug(marker, format, arguments); + } + + @Override + public void debug(Marker marker, String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.DEBUG, marker, msg, throwable); + + logger.debug(marker, msg, throwable); + } + + @Override + public boolean isInfoEnabled() { + return logger.isInfoEnabled(); + } + + @Override + public boolean isInfoEnabled(Marker marker) { + return logger.isInfoEnabled(marker); + } + + @Override + public void info(String msg) { + checkForEscalation(LoggingLevel.INFO, msg); + + logger.info(msg); + } + + @Override + public void info(String format, Object arg) { + checkForEscalation(LoggingLevel.INFO, format, arg); + + logger.info(format, arg); + } + + @Override + public void info(String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.INFO, arg1, arg2); + + logger.info(format, arg1, arg2); + } + + @Override + public void info(String format, Object... arguments) { + checkForEscalation(LoggingLevel.INFO, format, arguments); + + logger.info(format, arguments); + } + + @Override + public void info(String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.INFO, msg, throwable); + + logger.info(msg, throwable); + } + + @Override + public void info(Marker marker, String msg) { + checkForEscalation(LoggingLevel.INFO, marker, msg); + + logger.info(marker, msg); + } + + @Override + public void info(Marker marker, String format, Object arg) { + checkForEscalation(LoggingLevel.INFO, marker, arg); + + logger.info(marker, format, arg); + } + + @Override + public void info(Marker marker, String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.INFO, marker, arg1, arg2); + + logger.info(marker, format, arg1, arg2); + } + + @Override + public void info(Marker marker, String format, Object... arguments) { + checkForEscalation(LoggingLevel.INFO, marker, format, arguments); + + logger.info(marker, format, arguments); + } + + @Override + public void info(Marker marker, String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.INFO, marker, msg, throwable); + + logger.info(marker, msg, throwable); + } + + @Override + public boolean isWarnEnabled() { + return logger.isWarnEnabled(); + } + + @Override + public boolean isWarnEnabled(Marker marker) { + return logger.isWarnEnabled(marker); + } + + @Override + public void warn(String msg) { + checkForEscalation(LoggingLevel.WARN, msg); + + logger.warn(msg); + } + + @Override + public void warn(String format, Object arg) { + checkForEscalation(LoggingLevel.WARN, format, arg); + + logger.warn(format, arg); + } + + @Override + public void warn(String format, Object... arguments) { + checkForEscalation(LoggingLevel.WARN, format, arguments); + + logger.warn(format, arguments); + } + + @Override + public void warn(String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.WARN, format, arg1, arg2); + + logger.warn(format, arg1, arg2); + } + + @Override + public void warn(String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.WARN, msg, throwable); + + logger.warn(msg, throwable); + } + + @Override + public void warn(Marker marker, String msg) { + checkForEscalation(LoggingLevel.WARN, marker, msg); + + logger.warn(marker, msg); + } + + @Override + public void warn(Marker marker, String format, Object arg) { + checkForEscalation(LoggingLevel.WARN, marker, format, arg); + + logger.warn(marker, format, arg); + } + + @Override + public void warn(Marker marker, String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.WARN, marker, format, arg1, arg2); + + logger.warn(marker, format, arg1, arg2); + } + + @Override + public void warn(Marker marker, String format, Object... arguments) { + checkForEscalation(LoggingLevel.WARN, marker, format, arguments); + + logger.warn(marker, format, arguments); + } + + @Override + public void warn(Marker marker, String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.WARN, marker, msg, throwable); + + logger.warn(marker, msg, throwable); + } + + @Override + public boolean isErrorEnabled() { + return logger.isErrorEnabled(); + } + + @Override + public boolean isErrorEnabled(Marker marker) { + return logger.isErrorEnabled(marker); + } + + @Override + public void error(String msg) { + checkForEscalation(LoggingLevel.ERROR, msg); + + logger.error(msg); + } + + @Override + public void error(String format, Object arg) { + checkForEscalation(LoggingLevel.ERROR, format, arg); + + logger.error(format, arg); + } + + @Override + public void error(String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.ERROR, format, arg1, arg2); + + logger.error(format, arg1, arg2); + } + + @Override + public void error(String format, Object... arguments) { + checkForEscalation(LoggingLevel.ERROR, format, arguments); + + logger.error(format, arguments); + } + + @Override + public void error(String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.ERROR, msg, throwable); + + logger.error(msg, throwable); + } + + @Override + public void error(Marker marker, String msg) { + checkForEscalation(LoggingLevel.ERROR, marker, msg); + + logger.error(marker, msg); + } + + @Override + public void error(Marker marker, String format, Object arg) { + checkForEscalation(LoggingLevel.ERROR, marker, format, arg); + + logger.error(marker, format, arg); + } + + @Override + public void error(Marker marker, String format, Object arg1, Object arg2) { + checkForEscalation(LoggingLevel.ERROR, marker, format, arg1, arg2); + + logger.error(marker, format, arg1, arg2); + } + + @Override + public void error(Marker marker, String format, Object... arguments) { + checkForEscalation(LoggingLevel.ERROR, marker, format, arguments); + + logger.error(marker, format, arguments); + } + + @Override + public void error(Marker marker, String msg, Throwable throwable) { + checkForEscalation(LoggingLevel.ERROR, marker, msg, throwable); + + logger.error(marker, msg, throwable); + } + +} diff --git a/src/main/java/com/echobox/logging/escalator/EscalationTrigger.java b/src/main/java/com/echobox/logging/escalator/EscalationTrigger.java new file mode 100644 index 0000000..b98620d --- /dev/null +++ b/src/main/java/com/echobox/logging/escalator/EscalationTrigger.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging.escalator; + +/** + * Interface to mark an event and return if this should result in an escalation + * + * @author eddspencer + */ +public interface EscalationTrigger { + /** + * Mark the logging event for the given keys and check if escalation is triggered + * + * @param level the level + * @param keys the keys + * @return whether to trigger and escalation + */ + boolean markAndTrigger(LoggingLevel level, Object... keys); +} diff --git a/src/main/java/com/echobox/logging/escalator/LoggingLevel.java b/src/main/java/com/echobox/logging/escalator/LoggingLevel.java new file mode 100644 index 0000000..3ef9d34 --- /dev/null +++ b/src/main/java/com/echobox/logging/escalator/LoggingLevel.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging.escalator; + +/** + * Logging levels to use in tracking events + * + * @author eddspencer + */ +enum LoggingLevel { + /** + * TRACE logging level + */ + TRACE, + /** + * DEBUG logging level + */ + DEBUG, + /** + * INFO logging level + */ + INFO, + /** + * WARN logging level + */ + WARN, + /** + * ERROR logging level + */ + ERROR; +} diff --git a/src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java b/src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java new file mode 100644 index 0000000..398f9b7 --- /dev/null +++ b/src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging.escalator; + +import java.util.Arrays; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +/** + * Implementation of the escalation trigger that triggers and escalation when a particular event + * has been happening at least a minimum amount of times at a given interval for a given period. i + * .e. has been happening consistently for a period of time and over X events in that period. + * + * Uses a {@link ConcurrentHashMap} to store these times in memory. + * + * @author eddspencer + */ +public class TimeBasedEscalationTrigger implements EscalationTrigger { + + private final Supplier unixTimeNow; + private final long minEventCount; + private final int refreshIntervalSecs; + private final int escalationPeriodSecs; + + private final Map cache = new ConcurrentHashMap<>(); + private Predicate keyFilter = key -> true; + + public TimeBasedEscalationTrigger(Supplier unixTimeNow, long minEventCount, + int rereshIntervalSecs, int escalationPeriodSecs) { + this.unixTimeNow = unixTimeNow; + this.minEventCount = minEventCount; + this.refreshIntervalSecs = rereshIntervalSecs; + this.escalationPeriodSecs = escalationPeriodSecs; + } + + public TimeBasedEscalationTrigger(long minEventCount, int refreshIntervalSecs, + int escalationPeriodSecs) { + this.unixTimeNow = () -> System.currentTimeMillis() / 1000; + this.minEventCount = minEventCount; + this.refreshIntervalSecs = refreshIntervalSecs; + this.escalationPeriodSecs = escalationPeriodSecs; + } + + /** + * Sets a filter to only match specific object arguments when generating the even key + * + * @param keyFilter the predicate to use to filter arguments for use in event key + * @return this + */ + public TimeBasedEscalationTrigger withEventKeyFilter(Predicate keyFilter) { + this.keyFilter = keyFilter; + return this; + } + + @Override + public boolean markAndTrigger(LoggingLevel level, Object... keys) { + final String key = createEventKey(level, keys); + final long now = unixTimeNow.get(); + + final AtomicBoolean escalate = new AtomicBoolean(false); + cache.compute(key, (k, eventInfo) -> { + // If we have no other events just cache this one + if (eventInfo == null) { + return new EventInfo(now, now, 1); + } + + final long eventCount = eventInfo.eventCount + 1; + final boolean escalationPeriodPassed = + now - eventInfo.firstSeenUnixTime >= escalationPeriodSecs; + final boolean withinInterval = now - eventInfo.lastSeenUnixTime <= refreshIntervalSecs; + final boolean eventCountExceeded = eventCount >= minEventCount; + + // Trigger escalation and reset event if enough time has passed and event count hit + if (escalationPeriodPassed && withinInterval && eventCountExceeded) { + escalate.set(true); + return null; + } + + // Reset the info if we are outside the refresh interval + if (!withinInterval) { + return new EventInfo(now, now, 1); + } + + // Otherwise update event info + return new EventInfo(eventInfo.firstSeenUnixTime, now, eventCount); + }); + + return escalate.get(); + } + + /** + * Converts the logging level and objects provided to the logger to a unique key that + * identifies the type of event + * + * @param level the logging level + * @param eventArgs the arguments sent to the logging event + * @return the unique key for the event + */ + protected String createEventKey(LoggingLevel level, Object[] eventArgs) { + return String.format("%s::%s", level, + Arrays.stream(eventArgs).filter(keyFilter).map(Object::toString) + .collect(Collectors.joining("_"))); + } + + /** + * Event information for the time based event cache + * + * @author eddspencer + */ + private static class EventInfo { + private final long firstSeenUnixTime; + private final long lastSeenUnixTime; + private final long eventCount; + + private EventInfo(long firstSeenUnixTime, long lastSeenUnixTime, long eventCount) { + this.firstSeenUnixTime = firstSeenUnixTime; + this.lastSeenUnixTime = lastSeenUnixTime; + this.eventCount = eventCount; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + EventInfo eventInfo = (EventInfo) obj; + return firstSeenUnixTime == eventInfo.firstSeenUnixTime + && lastSeenUnixTime == eventInfo.lastSeenUnixTime; + } + + @Override + public int hashCode() { + return Objects.hash(firstSeenUnixTime, lastSeenUnixTime); + } + } +} diff --git a/src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java b/src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java new file mode 100644 index 0000000..40f6d0e --- /dev/null +++ b/src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package com.echobox.logging.escalator; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.slf4j.Logger; + +class EscalationLoggerTest { + + private EscalationTrigger trigger; + private EscalationAction action; + private EscalationLogger escalationLogger; + + @BeforeEach + public void setup() { + trigger = Mockito.mock(EscalationTrigger.class); + action = Mockito.mock(EscalationAction.class); + + final Logger logger = Mockito.mock(Logger.class); + escalationLogger = new EscalationLogger(logger, trigger, action); + } + + @Test + public void notEscalateButTriggered() { + escalationLogger.debug("This is a test"); + + verify(action, times(0)).escalate("This is a test"); + } + + @Test + public void escalateTRACE() { + when(trigger.markAndTrigger(LoggingLevel.TRACE, "This is a {}", "test")).thenReturn(true); + + escalationLogger.trace("This is a {}", "test"); + + verify(action).escalate("This is a {}", "test"); + } + + @Test + public void escalateDEBUG() { + when(trigger.markAndTrigger(LoggingLevel.DEBUG, "This is a test")).thenReturn(true); + + escalationLogger.debug("This is a test"); + + verify(action).escalate("This is a test"); + } + + @Test + public void escalateINFO() { + when(trigger.markAndTrigger(LoggingLevel.INFO, "This is a test")).thenReturn(true); + + escalationLogger.info("This is a test"); + + verify(action).escalate("This is a test"); + } + + @Test + public void escalateWARN() { + when(trigger.markAndTrigger(LoggingLevel.WARN, "This is a test")).thenReturn(true); + + escalationLogger.warn("This is a test"); + + verify(action).escalate("This is a test"); + } + + @Test + public void escalateERROR() { + Exception error = new Exception("Error"); + when(trigger.markAndTrigger(LoggingLevel.ERROR, "This is a test", error)).thenReturn(true); + + escalationLogger.error("This is a test", error); + + verify(action).escalate("This is a test", error); + } + +} \ No newline at end of file diff --git a/src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java b/src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java new file mode 100644 index 0000000..fd166eb --- /dev/null +++ b/src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java @@ -0,0 +1,135 @@ +package com.echobox.logging.escalator; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class TimeBasedEscalationTriggerTest { + + private TimeBasedEscalationTrigger trigger; + private long now; + + @BeforeEach + public void setup() { + trigger = new TimeBasedEscalationTrigger(() -> now, 3, 30, 60); + } + + @Test + public void doesNotEscalateOnFirstEvent() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void doesNotEscalateIfNotEnoughTimePassed() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void doesEscalateIfEnoughTimePassed() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void doesNotEscalateIfEnoughTimePassedButFailsMinInterval() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 40; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void doesNotEscalateIfNotEnoughEventsHaveHappened() { + trigger = new TimeBasedEscalationTrigger(() -> now, 4, 30, 60); + + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void allowsEventKeyToBeOverwritten() { + trigger = new TimeBasedEscalationTrigger(() -> now, 2, 30, 60) { + @Override + protected String createEventKey(LoggingLevel level, Object[] eventArgs) { + return "same-key"; + } + }; + + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "other")); + } + + @Test + public void allowsFilteringOfEventArguments() { + trigger = new TimeBasedEscalationTrigger(() -> now, 2, 30, 60) + .withEventKeyFilter(arg -> arg instanceof Exception); + + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1", new Exception("error"))); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event2", new Exception("error"))); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event3", new Exception("error"))); + } + + @Test + public void resetOnEventEscalation() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void resetWhenEventIsMissed() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + now += 40; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void canKeepTrackOfMultipleEventsByLevel() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + assertFalse(trigger.markAndTrigger(LoggingLevel.ERROR, "event")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.ERROR, "event")); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.ERROR, "event")); + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); + } + + @Test + public void canKeepTrackOfMultipleEventsByKey() { + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1")); + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event2")); + now += 30; + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1")); + now += 30; + assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1")); + assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event2")); + } +} \ No newline at end of file From c90fdebc12f3a52632b3d85377e74c0fa9e8b6e1 Mon Sep 17 00:00:00 2001 From: Edd Spencer Date: Thu, 29 Jun 2023 09:03:02 +0100 Subject: [PATCH 11/23] Revert "SL-5978 Create TimeBasedEscalationTrigger to use with EscalationLogger. (#7)" This reverts commit 6e9eb5e4 --- CHANGELOG.md | 3 +- .../escalator/TimeBasedEscalationTrigger.java | 159 ------------------ .../TimeBasedEscalationTriggerTest.java | 135 --------------- 3 files changed, 1 insertion(+), 296 deletions(-) delete mode 100644 src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java delete mode 100644 src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index a355e60..3f1c6f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,9 @@ * Initial release -## 1.1.0 (May 4, 2023) +## 1.1.0 (May 2, 2023) * Create EscalationLogger class to all for automatic escalation based off of log messages. -* Create TimeBasedEscalationTrigger to use with EscalationLogger. ## 2.0.0 (June 21, 2023) diff --git a/src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java b/src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java deleted file mode 100644 index 398f9b7..0000000 --- a/src/main/java/com/echobox/logging/escalator/TimeBasedEscalationTrigger.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -package com.echobox.logging.escalator; - -import java.util.Arrays; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -/** - * Implementation of the escalation trigger that triggers and escalation when a particular event - * has been happening at least a minimum amount of times at a given interval for a given period. i - * .e. has been happening consistently for a period of time and over X events in that period. - * - * Uses a {@link ConcurrentHashMap} to store these times in memory. - * - * @author eddspencer - */ -public class TimeBasedEscalationTrigger implements EscalationTrigger { - - private final Supplier unixTimeNow; - private final long minEventCount; - private final int refreshIntervalSecs; - private final int escalationPeriodSecs; - - private final Map cache = new ConcurrentHashMap<>(); - private Predicate keyFilter = key -> true; - - public TimeBasedEscalationTrigger(Supplier unixTimeNow, long minEventCount, - int rereshIntervalSecs, int escalationPeriodSecs) { - this.unixTimeNow = unixTimeNow; - this.minEventCount = minEventCount; - this.refreshIntervalSecs = rereshIntervalSecs; - this.escalationPeriodSecs = escalationPeriodSecs; - } - - public TimeBasedEscalationTrigger(long minEventCount, int refreshIntervalSecs, - int escalationPeriodSecs) { - this.unixTimeNow = () -> System.currentTimeMillis() / 1000; - this.minEventCount = minEventCount; - this.refreshIntervalSecs = refreshIntervalSecs; - this.escalationPeriodSecs = escalationPeriodSecs; - } - - /** - * Sets a filter to only match specific object arguments when generating the even key - * - * @param keyFilter the predicate to use to filter arguments for use in event key - * @return this - */ - public TimeBasedEscalationTrigger withEventKeyFilter(Predicate keyFilter) { - this.keyFilter = keyFilter; - return this; - } - - @Override - public boolean markAndTrigger(LoggingLevel level, Object... keys) { - final String key = createEventKey(level, keys); - final long now = unixTimeNow.get(); - - final AtomicBoolean escalate = new AtomicBoolean(false); - cache.compute(key, (k, eventInfo) -> { - // If we have no other events just cache this one - if (eventInfo == null) { - return new EventInfo(now, now, 1); - } - - final long eventCount = eventInfo.eventCount + 1; - final boolean escalationPeriodPassed = - now - eventInfo.firstSeenUnixTime >= escalationPeriodSecs; - final boolean withinInterval = now - eventInfo.lastSeenUnixTime <= refreshIntervalSecs; - final boolean eventCountExceeded = eventCount >= minEventCount; - - // Trigger escalation and reset event if enough time has passed and event count hit - if (escalationPeriodPassed && withinInterval && eventCountExceeded) { - escalate.set(true); - return null; - } - - // Reset the info if we are outside the refresh interval - if (!withinInterval) { - return new EventInfo(now, now, 1); - } - - // Otherwise update event info - return new EventInfo(eventInfo.firstSeenUnixTime, now, eventCount); - }); - - return escalate.get(); - } - - /** - * Converts the logging level and objects provided to the logger to a unique key that - * identifies the type of event - * - * @param level the logging level - * @param eventArgs the arguments sent to the logging event - * @return the unique key for the event - */ - protected String createEventKey(LoggingLevel level, Object[] eventArgs) { - return String.format("%s::%s", level, - Arrays.stream(eventArgs).filter(keyFilter).map(Object::toString) - .collect(Collectors.joining("_"))); - } - - /** - * Event information for the time based event cache - * - * @author eddspencer - */ - private static class EventInfo { - private final long firstSeenUnixTime; - private final long lastSeenUnixTime; - private final long eventCount; - - private EventInfo(long firstSeenUnixTime, long lastSeenUnixTime, long eventCount) { - this.firstSeenUnixTime = firstSeenUnixTime; - this.lastSeenUnixTime = lastSeenUnixTime; - this.eventCount = eventCount; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - EventInfo eventInfo = (EventInfo) obj; - return firstSeenUnixTime == eventInfo.firstSeenUnixTime - && lastSeenUnixTime == eventInfo.lastSeenUnixTime; - } - - @Override - public int hashCode() { - return Objects.hash(firstSeenUnixTime, lastSeenUnixTime); - } - } -} diff --git a/src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java b/src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java deleted file mode 100644 index fd166eb..0000000 --- a/src/main/test/com/echobox/logging/escalator/TimeBasedEscalationTriggerTest.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.echobox.logging.escalator; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -class TimeBasedEscalationTriggerTest { - - private TimeBasedEscalationTrigger trigger; - private long now; - - @BeforeEach - public void setup() { - trigger = new TimeBasedEscalationTrigger(() -> now, 3, 30, 60); - } - - @Test - public void doesNotEscalateOnFirstEvent() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void doesNotEscalateIfNotEnoughTimePassed() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void doesEscalateIfEnoughTimePassed() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void doesNotEscalateIfEnoughTimePassedButFailsMinInterval() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 40; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void doesNotEscalateIfNotEnoughEventsHaveHappened() { - trigger = new TimeBasedEscalationTrigger(() -> now, 4, 30, 60); - - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void allowsEventKeyToBeOverwritten() { - trigger = new TimeBasedEscalationTrigger(() -> now, 2, 30, 60) { - @Override - protected String createEventKey(LoggingLevel level, Object[] eventArgs) { - return "same-key"; - } - }; - - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "other")); - } - - @Test - public void allowsFilteringOfEventArguments() { - trigger = new TimeBasedEscalationTrigger(() -> now, 2, 30, 60) - .withEventKeyFilter(arg -> arg instanceof Exception); - - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1", new Exception("error"))); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event2", new Exception("error"))); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event3", new Exception("error"))); - } - - @Test - public void resetOnEventEscalation() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void resetWhenEventIsMissed() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - now += 40; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void canKeepTrackOfMultipleEventsByLevel() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - assertFalse(trigger.markAndTrigger(LoggingLevel.ERROR, "event")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.ERROR, "event")); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.ERROR, "event")); - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event")); - } - - @Test - public void canKeepTrackOfMultipleEventsByKey() { - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1")); - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event2")); - now += 30; - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1")); - now += 30; - assertTrue(trigger.markAndTrigger(LoggingLevel.DEBUG, "event1")); - assertFalse(trigger.markAndTrigger(LoggingLevel.DEBUG, "event2")); - } -} \ No newline at end of file From 30c031e705330b5a27bca0fa51362a4d241a3d14 Mon Sep 17 00:00:00 2001 From: Edd Spencer Date: Thu, 29 Jun 2023 09:04:05 +0100 Subject: [PATCH 12/23] Revert "SL-5978 Create escalation logger class (#5)" This reverts commit 60b83ef8 --- CHANGELOG.md | 9 - README.md | 2 +- pom.xml | 16 +- .../logging/escalator/EscalationAction.java | 33 -- .../logging/escalator/EscalationLogger.java | 455 ------------------ .../logging/escalator/EscalationTrigger.java | 34 -- .../logging/escalator/LoggingLevel.java | 46 -- .../escalator/EscalationLoggerTest.java | 97 ---- 8 files changed, 2 insertions(+), 690 deletions(-) delete mode 100644 src/main/java/com/echobox/logging/escalator/EscalationAction.java delete mode 100644 src/main/java/com/echobox/logging/escalator/EscalationLogger.java delete mode 100644 src/main/java/com/echobox/logging/escalator/EscalationTrigger.java delete mode 100644 src/main/java/com/echobox/logging/escalator/LoggingLevel.java delete mode 100644 src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f1c6f4..63094f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,3 @@ ## 1.0.0 (Jan 1, 2014) * Initial release - -## 1.1.0 (May 2, 2023) - -* Create EscalationLogger class to all for automatic escalation based off of log messages. - -## 2.0.0 (June 21, 2023) - -* Remove EscalationLogger and TimeBasedEscalationTrigger classes. These are now part of - ebx-escalatedlogging-sdk. diff --git a/README.md b/README.md index e05415d..28b4549 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ structured arguments to be included in `ch.qos.logback.classic.net.SyslogAppende com.echobox ebx-structuredlogging-sdk - 1.1.0 + 1.0.0 ``` diff --git a/pom.xml b/pom.xml index ed1d8a9..4b898e5 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ com.echobox ebx-structuredlogging-sdk - 1.1.0 + 1.0.0 jar @@ -72,20 +72,6 @@ logstash-logback-encoder 6.4 - - - - org.junit.jupiter - junit-jupiter - 5.9.3 - test - - - org.mockito - mockito-core - 5.2.0 - test - diff --git a/src/main/java/com/echobox/logging/escalator/EscalationAction.java b/src/main/java/com/echobox/logging/escalator/EscalationAction.java deleted file mode 100644 index 233fe17..0000000 --- a/src/main/java/com/echobox/logging/escalator/EscalationAction.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -package com.echobox.logging.escalator; - -/** - * Interface to do an escalation action once the desired trigger threshold has been met - * - * @author eddspencer - */ -public interface EscalationAction { - - /** - * An escalation has been triggered with the given keys - * - * @param keys the keys - */ - void escalate(Object... keys); -} diff --git a/src/main/java/com/echobox/logging/escalator/EscalationLogger.java b/src/main/java/com/echobox/logging/escalator/EscalationLogger.java deleted file mode 100644 index 8c286f3..0000000 --- a/src/main/java/com/echobox/logging/escalator/EscalationLogger.java +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -package com.echobox.logging.escalator; - -import org.slf4j.Logger; -import org.slf4j.Marker; - -/** - * Logger wrapper that will escalate to another action if a certain trigger function passes on a - * logger. For example, if 10 debug messages of the same text are made within 10min an - * escalation could be made. - * - * N.B. the original message is still logged even when an escalation is made. - * - * @author eddspencer - */ -public class EscalationLogger implements Logger { - - private final Logger logger; - private final EscalationTrigger trigger; - private final EscalationAction action; - - public EscalationLogger(Logger logger, EscalationTrigger trigger, EscalationAction action) { - this.logger = logger; - this.trigger = trigger; - this.action = action; - } - - private void checkForEscalation(LoggingLevel level, Object... keys) { - if (trigger.markAndTrigger(level, keys)) { - action.escalate(keys); - } - } - - @Override - public String getName() { - return logger.getName(); - } - - @Override - public boolean isTraceEnabled() { - return logger.isTraceEnabled(); - } - - @Override - public boolean isTraceEnabled(Marker marker) { - return logger.isTraceEnabled(marker); - } - - @Override - public void trace(String msg) { - checkForEscalation(LoggingLevel.TRACE, msg); - - logger.trace(msg); - } - - @Override - public void trace(String format, Object arg) { - checkForEscalation(LoggingLevel.TRACE, format, arg); - - logger.trace(format, arg); - } - - @Override - public void trace(String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.TRACE, format, arg1, arg2); - - logger.trace(format, arg1, arg2); - } - - @Override - public void trace(String format, Object... arguments) { - checkForEscalation(LoggingLevel.TRACE, format, arguments); - - logger.trace(format, arguments); - } - - @Override - public void trace(String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.TRACE, msg, throwable); - - logger.trace(msg, throwable); - } - - @Override - public void trace(Marker marker, String msg) { - checkForEscalation(LoggingLevel.TRACE, marker, msg); - - logger.trace(marker, msg); - } - - @Override - public void trace(Marker marker, String format, Object arg) { - checkForEscalation(LoggingLevel.TRACE, marker, format, arg); - - logger.trace(marker, format, arg); - } - - @Override - public void trace(Marker marker, String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.TRACE, marker, format, arg1, arg2); - - logger.trace(marker, format, arg1, arg2); - } - - @Override - public void trace(Marker marker, String format, Object... argArray) { - checkForEscalation(LoggingLevel.TRACE, marker, format, argArray); - - logger.trace(marker, format, argArray); - } - - @Override - public void trace(Marker marker, String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.TRACE, marker, msg, throwable); - - logger.trace(marker, msg, throwable); - } - - @Override - public boolean isDebugEnabled() { - return logger.isDebugEnabled(); - } - - @Override - public boolean isDebugEnabled(Marker marker) { - return logger.isDebugEnabled(marker); - } - - @Override - public void debug(String msg) { - checkForEscalation(LoggingLevel.DEBUG, msg); - - logger.debug(msg); - } - - @Override - public void debug(String format, Object arg) { - checkForEscalation(LoggingLevel.DEBUG, format, arg); - - logger.debug(format, arg); - } - - @Override - public void debug(String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.DEBUG, format, arg1, arg2); - - logger.debug(format, arg1, arg2); - } - - @Override - public void debug(String format, Object... arguments) { - checkForEscalation(LoggingLevel.DEBUG, format, arguments); - - logger.debug(format, arguments); - } - - @Override - public void debug(String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.DEBUG, msg, throwable); - - logger.debug(msg, throwable); - } - - @Override - public void debug(Marker marker, String msg) { - checkForEscalation(LoggingLevel.DEBUG, marker, msg); - - logger.debug(marker, msg); - } - - @Override - public void debug(Marker marker, String format, Object arg) { - checkForEscalation(LoggingLevel.DEBUG, marker, format, arg); - - logger.debug(marker, format, arg); - } - - @Override - public void debug(Marker marker, String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.DEBUG, marker, arg1, arg2); - - logger.debug(marker, format, arg1, arg2); - } - - @Override - public void debug(Marker marker, String format, Object... arguments) { - checkForEscalation(LoggingLevel.DEBUG, marker, format, arguments); - - logger.debug(marker, format, arguments); - } - - @Override - public void debug(Marker marker, String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.DEBUG, marker, msg, throwable); - - logger.debug(marker, msg, throwable); - } - - @Override - public boolean isInfoEnabled() { - return logger.isInfoEnabled(); - } - - @Override - public boolean isInfoEnabled(Marker marker) { - return logger.isInfoEnabled(marker); - } - - @Override - public void info(String msg) { - checkForEscalation(LoggingLevel.INFO, msg); - - logger.info(msg); - } - - @Override - public void info(String format, Object arg) { - checkForEscalation(LoggingLevel.INFO, format, arg); - - logger.info(format, arg); - } - - @Override - public void info(String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.INFO, arg1, arg2); - - logger.info(format, arg1, arg2); - } - - @Override - public void info(String format, Object... arguments) { - checkForEscalation(LoggingLevel.INFO, format, arguments); - - logger.info(format, arguments); - } - - @Override - public void info(String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.INFO, msg, throwable); - - logger.info(msg, throwable); - } - - @Override - public void info(Marker marker, String msg) { - checkForEscalation(LoggingLevel.INFO, marker, msg); - - logger.info(marker, msg); - } - - @Override - public void info(Marker marker, String format, Object arg) { - checkForEscalation(LoggingLevel.INFO, marker, arg); - - logger.info(marker, format, arg); - } - - @Override - public void info(Marker marker, String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.INFO, marker, arg1, arg2); - - logger.info(marker, format, arg1, arg2); - } - - @Override - public void info(Marker marker, String format, Object... arguments) { - checkForEscalation(LoggingLevel.INFO, marker, format, arguments); - - logger.info(marker, format, arguments); - } - - @Override - public void info(Marker marker, String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.INFO, marker, msg, throwable); - - logger.info(marker, msg, throwable); - } - - @Override - public boolean isWarnEnabled() { - return logger.isWarnEnabled(); - } - - @Override - public boolean isWarnEnabled(Marker marker) { - return logger.isWarnEnabled(marker); - } - - @Override - public void warn(String msg) { - checkForEscalation(LoggingLevel.WARN, msg); - - logger.warn(msg); - } - - @Override - public void warn(String format, Object arg) { - checkForEscalation(LoggingLevel.WARN, format, arg); - - logger.warn(format, arg); - } - - @Override - public void warn(String format, Object... arguments) { - checkForEscalation(LoggingLevel.WARN, format, arguments); - - logger.warn(format, arguments); - } - - @Override - public void warn(String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.WARN, format, arg1, arg2); - - logger.warn(format, arg1, arg2); - } - - @Override - public void warn(String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.WARN, msg, throwable); - - logger.warn(msg, throwable); - } - - @Override - public void warn(Marker marker, String msg) { - checkForEscalation(LoggingLevel.WARN, marker, msg); - - logger.warn(marker, msg); - } - - @Override - public void warn(Marker marker, String format, Object arg) { - checkForEscalation(LoggingLevel.WARN, marker, format, arg); - - logger.warn(marker, format, arg); - } - - @Override - public void warn(Marker marker, String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.WARN, marker, format, arg1, arg2); - - logger.warn(marker, format, arg1, arg2); - } - - @Override - public void warn(Marker marker, String format, Object... arguments) { - checkForEscalation(LoggingLevel.WARN, marker, format, arguments); - - logger.warn(marker, format, arguments); - } - - @Override - public void warn(Marker marker, String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.WARN, marker, msg, throwable); - - logger.warn(marker, msg, throwable); - } - - @Override - public boolean isErrorEnabled() { - return logger.isErrorEnabled(); - } - - @Override - public boolean isErrorEnabled(Marker marker) { - return logger.isErrorEnabled(marker); - } - - @Override - public void error(String msg) { - checkForEscalation(LoggingLevel.ERROR, msg); - - logger.error(msg); - } - - @Override - public void error(String format, Object arg) { - checkForEscalation(LoggingLevel.ERROR, format, arg); - - logger.error(format, arg); - } - - @Override - public void error(String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.ERROR, format, arg1, arg2); - - logger.error(format, arg1, arg2); - } - - @Override - public void error(String format, Object... arguments) { - checkForEscalation(LoggingLevel.ERROR, format, arguments); - - logger.error(format, arguments); - } - - @Override - public void error(String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.ERROR, msg, throwable); - - logger.error(msg, throwable); - } - - @Override - public void error(Marker marker, String msg) { - checkForEscalation(LoggingLevel.ERROR, marker, msg); - - logger.error(marker, msg); - } - - @Override - public void error(Marker marker, String format, Object arg) { - checkForEscalation(LoggingLevel.ERROR, marker, format, arg); - - logger.error(marker, format, arg); - } - - @Override - public void error(Marker marker, String format, Object arg1, Object arg2) { - checkForEscalation(LoggingLevel.ERROR, marker, format, arg1, arg2); - - logger.error(marker, format, arg1, arg2); - } - - @Override - public void error(Marker marker, String format, Object... arguments) { - checkForEscalation(LoggingLevel.ERROR, marker, format, arguments); - - logger.error(marker, format, arguments); - } - - @Override - public void error(Marker marker, String msg, Throwable throwable) { - checkForEscalation(LoggingLevel.ERROR, marker, msg, throwable); - - logger.error(marker, msg, throwable); - } - -} diff --git a/src/main/java/com/echobox/logging/escalator/EscalationTrigger.java b/src/main/java/com/echobox/logging/escalator/EscalationTrigger.java deleted file mode 100644 index b98620d..0000000 --- a/src/main/java/com/echobox/logging/escalator/EscalationTrigger.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -package com.echobox.logging.escalator; - -/** - * Interface to mark an event and return if this should result in an escalation - * - * @author eddspencer - */ -public interface EscalationTrigger { - /** - * Mark the logging event for the given keys and check if escalation is triggered - * - * @param level the level - * @param keys the keys - * @return whether to trigger and escalation - */ - boolean markAndTrigger(LoggingLevel level, Object... keys); -} diff --git a/src/main/java/com/echobox/logging/escalator/LoggingLevel.java b/src/main/java/com/echobox/logging/escalator/LoggingLevel.java deleted file mode 100644 index 3ef9d34..0000000 --- a/src/main/java/com/echobox/logging/escalator/LoggingLevel.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -package com.echobox.logging.escalator; - -/** - * Logging levels to use in tracking events - * - * @author eddspencer - */ -enum LoggingLevel { - /** - * TRACE logging level - */ - TRACE, - /** - * DEBUG logging level - */ - DEBUG, - /** - * INFO logging level - */ - INFO, - /** - * WARN logging level - */ - WARN, - /** - * ERROR logging level - */ - ERROR; -} diff --git a/src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java b/src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java deleted file mode 100644 index 40f6d0e..0000000 --- a/src/main/test/com/echobox/logging/escalator/EscalationLoggerTest.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - -package com.echobox.logging.escalator; - -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; -import org.slf4j.Logger; - -class EscalationLoggerTest { - - private EscalationTrigger trigger; - private EscalationAction action; - private EscalationLogger escalationLogger; - - @BeforeEach - public void setup() { - trigger = Mockito.mock(EscalationTrigger.class); - action = Mockito.mock(EscalationAction.class); - - final Logger logger = Mockito.mock(Logger.class); - escalationLogger = new EscalationLogger(logger, trigger, action); - } - - @Test - public void notEscalateButTriggered() { - escalationLogger.debug("This is a test"); - - verify(action, times(0)).escalate("This is a test"); - } - - @Test - public void escalateTRACE() { - when(trigger.markAndTrigger(LoggingLevel.TRACE, "This is a {}", "test")).thenReturn(true); - - escalationLogger.trace("This is a {}", "test"); - - verify(action).escalate("This is a {}", "test"); - } - - @Test - public void escalateDEBUG() { - when(trigger.markAndTrigger(LoggingLevel.DEBUG, "This is a test")).thenReturn(true); - - escalationLogger.debug("This is a test"); - - verify(action).escalate("This is a test"); - } - - @Test - public void escalateINFO() { - when(trigger.markAndTrigger(LoggingLevel.INFO, "This is a test")).thenReturn(true); - - escalationLogger.info("This is a test"); - - verify(action).escalate("This is a test"); - } - - @Test - public void escalateWARN() { - when(trigger.markAndTrigger(LoggingLevel.WARN, "This is a test")).thenReturn(true); - - escalationLogger.warn("This is a test"); - - verify(action).escalate("This is a test"); - } - - @Test - public void escalateERROR() { - Exception error = new Exception("Error"); - when(trigger.markAndTrigger(LoggingLevel.ERROR, "This is a test", error)).thenReturn(true); - - escalationLogger.error("This is a test", error); - - verify(action).escalate("This is a test", error); - } - -} \ No newline at end of file From 7481e06dc40eb0e26df2619d7164a49e3216ca57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 May 2024 11:52:16 +0100 Subject: [PATCH 13/23] Bump ch.qos.logback:logback-classic from 1.2.3 to 1.2.13 (#13) Bumps [ch.qos.logback:logback-classic](https://github.com/qos-ch/logback) from 1.2.3 to 1.2.13. - [Commits](https://github.com/qos-ch/logback/compare/v_1.2.3...v_1.2.13) --- updated-dependencies: - dependency-name: ch.qos.logback:logback-classic dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4b898e5..db18d79 100644 --- a/pom.xml +++ b/pom.xml @@ -64,7 +64,7 @@ ch.qos.logback logback-classic - 1.2.3 + 1.2.13 From 76787a2bc9d60a68971fb2d633df2ca83a845dda Mon Sep 17 00:00:00 2001 From: David Ashton Date: Fri, 17 May 2024 16:26:13 +0100 Subject: [PATCH 14/23] SL-10078 Add dependabot config (#14) * SL-10078 Add dependabot config * SL-10078 Version update and changelog addition --- .github/dependabot.yml | 8 ++++++++ CHANGELOG.md | 4 ++++ pom.xml | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..d2b20ab --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + - package-ecosystem: maven + directory: "/" + schedule: + interval: "weekly" + day: "sunday" + time: "17:00" diff --git a/CHANGELOG.md b/CHANGELOG.md index 63094f9..026a4d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,3 +3,7 @@ ## 1.0.0 (Jan 1, 2014) * Initial release + +## 1.0.1 (May 16, 2024) + +* Update dependencies and add dependabot configuration. diff --git a/pom.xml b/pom.xml index db18d79..978f93c 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ com.echobox ebx-structuredlogging-sdk - 1.0.0 + 1.0.1 jar From ff90d58d545cdcab4ec1786f77c4507c1882043e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 16:28:08 +0100 Subject: [PATCH 15/23] Bump org.apache.maven.plugins:maven-gpg-plugin from 3.0.1 to 3.2.4 (#15) Bumps [org.apache.maven.plugins:maven-gpg-plugin](https://github.com/apache/maven-gpg-plugin) from 3.0.1 to 3.2.4. - [Release notes](https://github.com/apache/maven-gpg-plugin/releases) - [Commits](https://github.com/apache/maven-gpg-plugin/compare/maven-gpg-plugin-3.0.1...maven-gpg-plugin-3.2.4) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-gpg-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 978f93c..df6cff0 100644 --- a/pom.xml +++ b/pom.xml @@ -229,7 +229,7 @@ org.apache.maven.plugins maven-gpg-plugin - 3.0.1 + 3.2.4 sign-artifacts From aba44a0c8827f2bafa30a3d9e2e701054d880c5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 16:28:36 +0100 Subject: [PATCH 16/23] Bump org.apache.maven.surefire:surefire-junit47 from 3.0.0-M5 to 3.2.5 (#16) Bumps org.apache.maven.surefire:surefire-junit47 from 3.0.0-M5 to 3.2.5. --- updated-dependencies: - dependency-name: org.apache.maven.surefire:surefire-junit47 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index df6cff0..054b507 100644 --- a/pom.xml +++ b/pom.xml @@ -92,7 +92,7 @@ org.apache.maven.surefire surefire-junit47 - 3.0.0-M5 + 3.2.5 From dbbc12a3db30a84fb479ded52a90a3708abcc50b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 16:28:58 +0100 Subject: [PATCH 17/23] Bump org.apache.maven.plugins:maven-source-plugin from 3.2.1 to 3.3.1 (#17) Bumps [org.apache.maven.plugins:maven-source-plugin](https://github.com/apache/maven-source-plugin) from 3.2.1 to 3.3.1. - [Commits](https://github.com/apache/maven-source-plugin/compare/maven-source-plugin-3.2.1...maven-source-plugin-3.3.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-source-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 054b507..208170d 100644 --- a/pom.xml +++ b/pom.xml @@ -201,7 +201,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.1 attach-sources From fe0ea35772e24e1e2b43a89ca0a0129165f20b71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 16:30:38 +0100 Subject: [PATCH 18/23] Bump org.apache.maven.plugins:maven-surefire-plugin (#18) Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.0.0-M5 to 3.2.5. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.0.0-M5...surefire-3.2.5) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 208170d..e3d7325 100644 --- a/pom.xml +++ b/pom.xml @@ -87,7 +87,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M5 + 3.2.5 org.apache.maven.surefire From cc13963bf18f6a3295b729b39e8cec11e4994c32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 16:31:15 +0100 Subject: [PATCH 19/23] Bump org.apache.maven.plugins:maven-checkstyle-plugin (#19) Bumps [org.apache.maven.plugins:maven-checkstyle-plugin](https://github.com/apache/maven-checkstyle-plugin) from 3.1.1 to 3.3.1. - [Commits](https://github.com/apache/maven-checkstyle-plugin/compare/maven-checkstyle-plugin-3.1.1...maven-checkstyle-plugin-3.3.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-checkstyle-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e3d7325..1bbf28c 100644 --- a/pom.xml +++ b/pom.xml @@ -113,7 +113,7 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.1.1 + 3.3.1 validate From 36bb17d343e72f62aebccb2c2723de2e9f886531 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 16:35:38 +0100 Subject: [PATCH 20/23] Bump org.apache.maven.plugins:maven-pmd-plugin from 3.13.0 to 3.22.0 (#20) Bumps [org.apache.maven.plugins:maven-pmd-plugin](https://github.com/apache/maven-pmd-plugin) from 3.13.0 to 3.22.0. - [Release notes](https://github.com/apache/maven-pmd-plugin/releases) - [Commits](https://github.com/apache/maven-pmd-plugin/compare/maven-pmd-plugin-3.13.0...maven-pmd-plugin-3.22.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-pmd-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1bbf28c..02f3a44 100644 --- a/pom.xml +++ b/pom.xml @@ -146,7 +146,7 @@ org.apache.maven.plugins maven-pmd-plugin - 3.13.0 + 3.22.0 cpd From 094d74a8631c9194251dd5c335de75f6a90af99a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 16:36:05 +0100 Subject: [PATCH 21/23] Bump com.github.sevntu-checkstyle:sevntu-checks from 1.35.0 to 1.44.1 (#22) Bumps com.github.sevntu-checkstyle:sevntu-checks from 1.35.0 to 1.44.1. --- updated-dependencies: - dependency-name: com.github.sevntu-checkstyle:sevntu-checks dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 02f3a44..6596aa2 100644 --- a/pom.xml +++ b/pom.xml @@ -139,7 +139,7 @@ com.github.sevntu-checkstyle sevntu-checks - 1.35.0 + 1.44.1 From 48f92e77247f8265d1d865ac240de09ff51f420b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 16:36:32 +0100 Subject: [PATCH 22/23] Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.2.0 to 3.6.3 (#23) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.2.0 to 3.6.3. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.2.0...maven-javadoc-plugin-3.6.3) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6596aa2..8ffe704 100644 --- a/pom.xml +++ b/pom.xml @@ -99,7 +99,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 + 3.6.3 attach-javadocs @@ -214,7 +214,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 + 3.6.3 attach-javadocs From ae51617c5e19ca4fb371ccea14d71b8219eafa24 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 16:38:24 +0100 Subject: [PATCH 23/23] Bump org.apache.maven.plugins:maven-compiler-plugin from 3.8.1 to 3.13.0 (#26) Bumps [org.apache.maven.plugins:maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.8.1 to 3.13.0. - [Release notes](https://github.com/apache/maven-compiler-plugin/releases) - [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.8.1...maven-compiler-plugin-3.13.0) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-compiler-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8ffe704..c2bf5d8 100644 --- a/pom.xml +++ b/pom.xml @@ -79,7 +79,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.13.0 true