diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 04bca272..00000000 --- a/.travis.yml +++ /dev/null @@ -1,40 +0,0 @@ -sudo: required -language: java -jdk: - - openjdk8 -before_cache: -- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock -- rm -fr $HOME/.gradle/caches/*/plugin-resolution/ -cache: - directories: - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ -script: -- ./gradlew build -after_success: -- ./gradlew codeCoverageReport -- bash <(curl -s https://codecov.io/bash) -deploy: -- provider: script - script: ./gradlew bintrayUpload - skip_cleanup: true - on: - repo: hmcts/java-logging - tags: true -- provider: releases - api_key: - secure: v1gAVCFHdpRMYEyD2R4zOqxNAkd+TL+RFndzlTw0kUtQT+SbTNfLhnxiMwHfFeIn3ivqQ1MLt8zXo5zDtFHHRGp6QX/kA9I0mIj74rf/sj0z0ElXCDtiB41NVcq9++X1OmvP4qniWxcvi03e4TMg0HIiLGzD41437NVN1So/PUYFVxgvyeENL6JUIe7d2y48ZP2YvWh1tvwj5Z3p/bEd2Kp7H0aTP58l1kSkSHoSonNHpB/yjT9qN6VSWTyMl8GxeRPX4FSYEGBpDy7+8wxVO/MVOMwu0X2T6vgYlmkXj4U7bmXf0kMkvbeBQC/yZEH8D2y1W3piERw0b17kc9t7tigULBXIEhUNUgKFVEdTDSAEJASpytlxKfsaNVjsUx9n9kWhSUqtFgIz9msS4iJpImkSLTr20BivJ829zNfcG1wbHyIqlV5MQKTAqCwU6RWvRrT0OwhCT38R0lzmyDKEUbRbz+kGW4Vqo5BaPRMrxZZFRMtSHDuh8HCp2LzefUcfUX7LCvSd4z0MFK0o1WEn1lEuB1haViF2JWiov973JFqH7FjJe0iF172GOaMMFRR6ck8g8omfGO+ufZtxPeW5Zw47IridV9HaOhN/K8wkT7xVgdKy+qZmRdzdEHOo2hT2n9mbagIFmqc4yKN91elhAc/vzieE1WNx0n8+Aj9joyY= - file_glob: true - file: - - build/libs/java-logging-*.jar - - java-logging-appinsights/build/libs/logging-appinsights-*.jar - - java-logging-httpcomponents/build/libs/logging-httpcomponents-*.jar - - java-logging-spring/build/libs/logging-spring-*.jar - skip_cleanup: true - on: - repo: hmcts/java-logging - tags: true -env: - global: - - secure: idyabL0MgrmQw8ZdwgRYe8/ewYrdYlNAaYUZbhTzLnnIkXAnPXhFxPB+k2mDaMf0ww26VpBl4O6aYv5bHrCI+1/oziByTSz6Qny9j3F2h/gnSwyXZUe427BCjTR9Wz1+TvASGansO+igj0FxENGikqKDd0V5Qe8lr4Lm01+xXLoAXfvyqqiAqjsRHvl1vG+9F+G80hzmMBSBm7AkN//uYJRFCJV07yp6J0ALd6Z81cChNJgvS7oG9iXimFltiCwf8KNcotkm/mbGHULyj6YVfnFePSoIuI94QBi2myqxDRQ56bv7wtipsF0zaOn+Zc5hPr6QGPMXNWeD3kp/ZmEYWsg5VFQEdcpnKhyv7zcmKZDaYQgIkdjZTZ1rDBj04ubBJs96dEex2CamascLTuq5XuVs3O8MG4GrcKPDqTbDNDnSVDtyRUakhWwnFn424shotCyXl+k06THlFVQq229eBRKCQDdGWtV2B4Z55AxQdIHqaDLppYJs1wCC7350/gY0pXgm4928UpVxx3Bk/Gu1HT8gIWOiEYigqqPOgFlfrdGMiPyRM0WHImZ9Ru8d/RvMnGYndwlY10q3i2lM+CdwthaPp1f9jZDZw2uqqmiUlOuH+oVG4l61h+gznlH277KXcjTPbLjwczo5nZ0L4H/TBGTVrhTOVUQEsBu/zYrAZo8= - - secure: lMbaGTv2PCsjiwGpDMsTKShmtC6Fj6bp++2Re2H2+lgRAmepnr9h8+5ckHyaGYH6HuxSBYN9Q01F1t6lwn1tZQYhJ6EJYK8Kb1KHWnXME3K6VnM/C+6Yr7TkZr0+1SaDE7CIAjCzgF3v5MsWlBUDLhJYViwNuZaJ+Ej73RJkIi0qEu2Dk0PYx6JMK/jwnCojCOYoWjm7d23Tyu5ACo+onZF1WCfVVrI7Gq8kEN4OhClozVvF5IFqfeGEJCWzMsNCxJDE9ptFJcDmp5he41l1GrXNgD9rCxWay03l96Z2+OcqeXV9prIZ36h1mnWy3pd+Xnpxi0LqE09nBFnnGMCwbeer16hG09zsxav6Qk68AUt+smHEcxzFJC9Q6otW+6ud8gxk4kxPkyYo0+adQj5yuudVNS8R7sH8hsTKdD6K0Hv5I3Yob2eSw+1aaE1iz8vplbMCdwOVuZH9uwpgWrivi4HZO9VKgkZ83nr7guJpES7i+YhmiokpN8eUZFrUKCW0ScUJGit8JBjOeaSZod6prd/X7roI4u79eeYG0l76PcN/vPgfUN4cQEOOwg97XLpAvYySghC5ppRUnczDs/iEV5sqWS2QnF20JY+2CDEJkrfC/JlpR2TETrVzeBfzs/VKm811vAoRXscaGWGCfg2FdAWHvpquQ8EViqKnzH/9V5M= diff --git a/README.md b/README.md index 49a4b17b..2afabadb 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,14 @@ -[![Build Status](https://travis-ci.org/hmcts/java-logging.svg?branch=master)](https://travis-ci.org/hmcts/java-logging) [![GitHub version](https://badge.fury.io/gh/hmcts%2Fjava-logging.svg)](https://badge.fury.io/gh/hmcts%2Fjava-logging) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/ebac86c131154ef2b59ab302d1d75fd9)](https://www.codacy.com/app/HMCTS/java-logging) -[![codecov](https://codecov.io/gh/hmcts/java-logging/branch/master/graph/badge.svg)](https://codecov.io/gh/hmcts/java-logging) [![Known Vulnerabilities](https://snyk.io/test/github/hmcts/java-logging/badge.svg)](https://snyk.io/test/github/hmcts/java-logging) -[ ![Download](https://api.bintray.com/packages/hmcts/hmcts-maven/logging/images/download.svg) ](https://bintray.com/hmcts/hmcts-maven/logging/_latestVersion) -# Reform Java logging module +# Java logging A Java module which standardises the logging for the reform projects. ## Prerequisites -- [Java 8](https://www.oracle.com/java) +- [Java 11](https://adoptium.net/) ## User guide @@ -25,46 +22,13 @@ Simply add base component as your project's dependency and then one or more of t Base component dependency, gradle: ```groovy -compile group: 'uk.gov.hmcts.reform', name: 'logging', version: '5.1.1' +implementation group: 'com.github.hmcts.java-logging', name: 'logging', version: '5.1.9' ``` #### java-logging-insights Use for automatic configuration of Azure Application Insights for a Spring Boot project. [Read more](java-logging-appinsights/README.md) -#### java-logging-spring - -Use for formatting log output in Spring Boot applications. - - -Gradle: -```groovy -compile group: 'uk.gov.hmcts.reform', name: 'logging-spring', version: '5.1.1' -``` - -#### java-logging-httpcomponents - -Use for adding request IDs to external HTTP / HTTPS requests. - -Gradle: -```groovy -compile group: 'uk.gov.hmcts.reform', name: 'logging-httpcomponents', version: '5.1.1' -``` - -**Please note:** You will also need to implement a class that configures an HTTP client with interceptors for outbound HTTP requests and responses. See https://github.com/hmcts/cmc-claim-store/blob/master/src/main/java/uk/gov/hmcts/cmc/claimstore/clients/RestClient.java#L98 for an example. - -After that you can log like you would do with any [SLF4J](https://www.slf4j.org/) logger. Define it as a class field: - -```java -private static final Logger log = LoggerFactory.getLogger(SomeResource.class); -``` - -And do the actual logging, e.g.: - -```java -log.info("An important business process has finished"); -``` - ### Configuration defaults By default the module will use a simple, human-friendly logging format which can be used out-of-the-box for development: @@ -143,19 +107,6 @@ To install the artifact to a local Maven repository: ./gradlew install ``` -### Exception logging - -Since [v1.5.0](https://github.com/hmcts/java-logging/releases/tag/1.5.0) Alert level and error code are required fields for any exception to be logged. -In order to correctly stream log events for all exceptions one must be extended with `AbstractLoggingException`. -Error code is introduced as legacy error group not minding the fact exceptions themselves represent relevant error group. -There is a helper `UnknownErrorCodeException` class which populates the field with `UNKNOWN` as error code. - -Alert level is still required. - ### Releasing -Run the script `./prepare-for-release.sh` select an appropriate version and follow the instructions the script provides - -## Future development considerations - -- [MDC](https://logback.qos.ch/manual/mdc.html) for capturing and logging request identifiers. +Create a release via the GitHub UI, the tag selected will be used as the version number diff --git a/build.gradle b/build.gradle index dca56176..09f586ba 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,5 @@ -buildscript { - dependencies { - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5' - } -} - plugins { - id 'org.owasp.dependencycheck' version '6.3.2' + id 'org.owasp.dependencycheck' version '6.5.2.1' id 'com.github.ben-manes.versions' version '0.39.0' } @@ -19,19 +13,18 @@ allprojects { apply plugin: 'java-library' apply plugin: 'maven-publish' apply plugin: 'checkstyle' - apply plugin: 'com.jfrog.bintray' apply plugin: 'jacoco' apply plugin: 'com.github.ben-manes.versions' apply plugin: 'pmd' checkstyle { - toolVersion = '8.24' + toolVersion = '9.2.1' maxWarnings = 0 getConfigDirectory().set(new File(rootDir, "config/checkstyle")) } pmd { - toolVersion = "6.25.0" + toolVersion = "6.41.0" ignoreFailures = true incrementalAnalysis = true sourceSets = [sourceSets.main, sourceSets.test] @@ -43,36 +36,18 @@ allprojects { toolVersion = "0.8.4" } - sourceCompatibility = 1.8 + java { + toolchain { + languageVersion = JavaLanguageVersion.of(11) + } + } repositories { mavenLocal() mavenCentral() - jcenter() - } - - configurations.all { - resolutionStrategy { - eachDependency { DependencyResolveDetails details -> - if (details.requested.group in ['com.fasterxml.jackson.core', 'com.fasterxml.jackson.module', 'com.fasterxml.jackson.datatype']) { - details.useVersion '2.9.9' - } - if (details.requested.name == 'jackson-databind') { - details.useVersion '2.9.10' - } - if (details.requested.name == 'guava') { - details.useVersion '28.0-jre' - } - } - } } dependencies { - implementation group: 'net.logstash.logback', name: 'logstash-logback-encoder', version: '6.6' - implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.30' - implementation group: 'org.slf4j', name: 'jul-to-slf4j', version: '1.7.32' - implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.6' - api group: 'javax.servlet', name: 'javax.servlet-api', version: '4.0.1' testImplementation group: 'junit', name: 'junit', version: '4.13.2' } @@ -112,10 +87,10 @@ task codeCoverageReport(type: JacocoReport, dependsOn: allprojects*.test) { } reports { - csv.enabled = false - html.enabled = true + csv.required = false + html.required = true html.destination = file("${buildDir}/reports/jacoco/html") - xml.enabled = true + xml.required = true xml.destination = file("${buildDir}/reports/jacoco/jacocoTestReport.xml") } } @@ -136,23 +111,6 @@ publishing { } } -bintray { - user = System.getenv('BINTRAY_USER') - key = System.getenv('BINTRAY_KEY') - publications = ['Main'] - publish = true - pkg { - repo = 'hmcts-maven' - name = 'logging' - userOrg = 'hmcts' - licenses = ['MIT'] - vcsUrl = 'https://github.com/hmcts/java-logging' - version { - name = project.version - } - } -} - dependencies { testImplementation group: 'org.mockito', name: 'mockito-core', version: '4.0.0' testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.21.0' diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 12fbb2d7..1dae5739 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -237,13 +237,9 @@ value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/> - - - - diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ac33e994..669386b8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/java-logging-appinsights/README.md b/java-logging-appinsights/README.md index c6316cb1..2bcc7d26 100644 --- a/java-logging-appinsights/README.md +++ b/java-logging-appinsights/README.md @@ -1,6 +1,8 @@ # Azure Application Insights -Logging module to auto configure necessary components for Azure Application Insights app. It uses [azure-application-insights-spring-boot-starter](https://github.com/Microsoft/ApplicationInsights-Java/tree/v2.3.1/azure-application-insights-spring-boot-starter) and adds some specific initializers as Spring beans. Module also tracks logback INFO events for `uk.gov.hmcts` loggers +Logging module to auto configure necessary components for Azure Application Insights app. +It uses [azure-application-insights-spring-boot-starter](https://github.com/Microsoft/ApplicationInsights-Java/tree/v2.3.1/azure-application-insights-spring-boot-starter) and adds some specific initializers as Spring beans. +Module also tracks logback INFO events for `uk.gov.hmcts` loggers ## User guide @@ -8,43 +10,21 @@ The module provides all Telemetry modules and initializers available from web ar ### Basic usage -For now you need to add the HMCTS maven repository: - -Maven: - -```xml - - - hmcts-maven - HMCTS Maven - https://dl.bintray.com/hmcts/hmcts-maven - - - - - uk.gov.hmcts.reform - java-logging-appinsights - 5.1.1 - -``` - Gradle: ```groovy repositories { - maven { - url "https://dl.bintray.com/hmcts/hmcts-maven" - } + maven { url 'https://jitpack.io' } } dependencies { - compile group: 'uk.gov.hmcts.reform', name: 'logging-appinsights', version: '5.1.1' + implementation group: 'com.github.hmcts.java-logging', name: 'logging-appinsights', version: '5.1.9' } ``` It will automatically include Request Name interceptor and Request Tracking Filter configurations into spring boot web application. -Request Tracking Filter needs agent to be configured. By default agent uses built in configuration but you can provide your own. +Request Tracking Filter needs agent to be configured. By default agent uses built in configuration but you can provide your own. Sample of `AI-Agent.xml`: @@ -69,7 +49,7 @@ Retrieve the jar from github, i.e. https://github.com/Microsoft/ApplicationInsig TelemetryClient can be `autowired` to implement custom telemetry metrics. #### Provide Instrumentation Key - + Set the environment variable: AZURE_APPLICATIONINSIGHTS_INSTRUMENTATIONKEY. If you are deploying using the CNP pipeline this will be automatically added for you. You can also set it using a spring property (useful for tests): @@ -132,7 +112,7 @@ Along with custom Source name there are more optional headers to be applied at w [SyntheticHeaders](java-logging-appinsights/src/main/java/uk/gov/hmcts/reform/logging/appinsights/SyntheticHeaders) might be deprecated in future based on Microsoft making the constants public. -#### To disable Application insights completely +#### To disable Application insights completely Refer [Spring Starter disabling App Insights](https://github.com/Microsoft/ApplicationInsights-Java/tree/v2.3.1/azure-application-insights-spring-boot-starter#completely-disable-application-insights-using-applicationproperties) @@ -174,7 +154,7 @@ This configuration entry is also used by [`SpringBootTelemetryInitializer`](http For Spring starter configurations , Refer [configure-more-parameters-using-applicationproperties](https://github.com/Microsoft/ApplicationInsights-Java/tree/v2.3.1/azure-application-insights-spring-boot-starter#configure-more-parameters-using-applicationproperties) -Additional properties : +Additional properties : ```properties application-insights.custom.modules.ContextInitializer.enabled=true application-insights.default.modules.TimestampPropertyInitializer.enabled=true diff --git a/java-logging-appinsights/build.gradle b/java-logging-appinsights/build.gradle index 602a4a3b..866aedaa 100644 --- a/java-logging-appinsights/build.gradle +++ b/java-logging-appinsights/build.gradle @@ -23,23 +23,6 @@ publishing { } } -bintray { - user = System.getenv('BINTRAY_USER') - key = System.getenv('BINTRAY_KEY') - publications = ['Insights'] - publish = true - pkg { - repo = 'hmcts-maven' - name = 'logging-appinsights' - userOrg = 'hmcts' - licenses = ['MIT'] - vcsUrl = 'https://github.com/hmcts/java-logging' - version { - name = project.version - } - } -} - repositories { flatDir { dirs "$projectDir/lib" diff --git a/java-logging-appinsights/src/main/java/uk/gov/hmcts/reform/logging/appinsights/AbstractAppInsights.java b/java-logging-appinsights/src/main/java/uk/gov/hmcts/reform/logging/appinsights/AbstractAppInsights.java deleted file mode 100644 index 59ff781d..00000000 --- a/java-logging-appinsights/src/main/java/uk/gov/hmcts/reform/logging/appinsights/AbstractAppInsights.java +++ /dev/null @@ -1,28 +0,0 @@ -package uk.gov.hmcts.reform.logging.appinsights; - -import com.microsoft.applicationinsights.TelemetryClient; - -import static java.util.Objects.requireNonNull; - -/** - *

@deprecated TelemetryClient can be directly used for any custom implementation.

- * Application Insights class to send custom telemetry to AppInsights. - * - * // NO PMD is for pmd rule to skip the check of any abstract methods being present in abstract class. - * - */ -@Deprecated -public abstract class AbstractAppInsights { // NOPMD - - protected final TelemetryClient telemetry; - - protected AbstractAppInsights(TelemetryClient telemetry) { - requireNonNull( - telemetry.getContext().getInstrumentationKey(), - "Missing APPINSIGHTS_INSTRUMENTATIONKEY environment variable" - ); - telemetry.getContext().getComponent().setVersion(getClass().getPackage().getImplementationVersion()); - - this.telemetry = telemetry; - } -} diff --git a/java-logging-appinsights/src/main/java/uk/gov/hmcts/reform/logging/appinsights/telemetry/initializers/ContextVersionInitializer.java b/java-logging-appinsights/src/main/java/uk/gov/hmcts/reform/logging/appinsights/telemetry/initializers/ContextVersionInitializer.java index e0f4871c..f15c4d8d 100644 --- a/java-logging-appinsights/src/main/java/uk/gov/hmcts/reform/logging/appinsights/telemetry/initializers/ContextVersionInitializer.java +++ b/java-logging-appinsights/src/main/java/uk/gov/hmcts/reform/logging/appinsights/telemetry/initializers/ContextVersionInitializer.java @@ -8,7 +8,6 @@ * *

This Telemetry Initializer is used to auto-configure version field as current spring boot starter for * app insights is not setting this. - * This is to deprecate {@link uk.gov.hmcts.reform.logging.appinsights.AbstractAppInsights}

*/ public class ContextVersionInitializer implements ContextInitializer { @Override diff --git a/java-logging-appinsights/src/test/java/uk/gov/hmcts/reform/logging/appinsights/AppInsightsAllComponentsTest.java b/java-logging-appinsights/src/test/java/uk/gov/hmcts/reform/logging/appinsights/AppInsightsAllComponentsTest.java deleted file mode 100644 index 8b01b0e6..00000000 --- a/java-logging-appinsights/src/test/java/uk/gov/hmcts/reform/logging/appinsights/AppInsightsAllComponentsTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package uk.gov.hmcts.reform.logging.appinsights; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.ApplicationContext; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT, properties = { - "azure.applicationinsights.instrumentationkey=some-key" -}) -public class AppInsightsAllComponentsTest { - - @Autowired - private AbstractAppInsights insights; - - @Autowired - private ApplicationContext context; - - @Test - public void contextLoads() { - assertThat(insights).isInstanceOf(SpringBootTestApplication.AppInsightsImp.class); - assertThat(context.containsBean("contextVersionInitializer")).isTrue(); - assertThat(context.containsBean("sequencePropertyInitializer")).isTrue(); - assertThat(context.containsBean("timestampPropertyInitializer")).isTrue(); - assertThat(context.containsBean("webSyntheticRequestTelemetryInitializer")).isTrue(); - - } -} diff --git a/java-logging-appinsights/src/test/java/uk/gov/hmcts/reform/logging/appinsights/SpringBootTestApplication.java b/java-logging-appinsights/src/test/java/uk/gov/hmcts/reform/logging/appinsights/SpringBootTestApplication.java deleted file mode 100644 index 2e66339c..00000000 --- a/java-logging-appinsights/src/test/java/uk/gov/hmcts/reform/logging/appinsights/SpringBootTestApplication.java +++ /dev/null @@ -1,24 +0,0 @@ -package uk.gov.hmcts.reform.logging.appinsights; - -import com.microsoft.applicationinsights.TelemetryClient; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; - -@SpringBootApplication -@SuppressWarnings("HideUtilityClassConstructor") -public class SpringBootTestApplication { - - public static void main(String[] args) { - SpringApplication.run(SpringBootTestApplication.class, args); - } - - @Component - @ConditionalOnProperty(name = "app-insights.telemetry-component", havingValue = "true", matchIfMissing = true) - public static class AppInsightsImp extends AbstractAppInsights { - public AppInsightsImp(TelemetryClient telemetry) { - super(telemetry); - } - } -} diff --git a/java-logging-httpcomponents/build.gradle b/java-logging-httpcomponents/build.gradle deleted file mode 100644 index 10258d3f..00000000 --- a/java-logging-httpcomponents/build.gradle +++ /dev/null @@ -1,42 +0,0 @@ -java { - withJavadocJar() - withSourcesJar() -} - -publishing { - publications { - HttpComponents(MavenPublication) { - from components.java - groupId project.group - artifactId 'logging-httpcomponents' - version project.version - } - } -} - -bintray { - user = System.getenv('BINTRAY_USER') - key = System.getenv('BINTRAY_KEY') - publications = ['HttpComponents'] - publish = true - pkg { - repo = 'hmcts-maven' - name = 'logging-httpcomponents' - userOrg = 'hmcts' - licenses = ['MIT'] - vcsUrl = 'https://github.com/hmcts/java-logging' - version { - name = project.version - } - } -} - -dependencies { - implementation project(':') - implementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.13' - - testImplementation project(':').sourceSets.test.output - testImplementation group: 'org.mockito', name: 'mockito-core', version: '4.0.0' - testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.21.0' - testImplementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.6' -} diff --git a/java-logging-httpcomponents/src/main/java/uk/gov/hmcts/reform/logging/httpcomponents/OutboundRequestIdSettingInterceptor.java b/java-logging-httpcomponents/src/main/java/uk/gov/hmcts/reform/logging/httpcomponents/OutboundRequestIdSettingInterceptor.java deleted file mode 100644 index 8e17a610..00000000 --- a/java-logging-httpcomponents/src/main/java/uk/gov/hmcts/reform/logging/httpcomponents/OutboundRequestIdSettingInterceptor.java +++ /dev/null @@ -1,31 +0,0 @@ -package uk.gov.hmcts.reform.logging.httpcomponents; - -import org.apache.http.HttpRequest; -import org.apache.http.HttpRequestInterceptor; -import org.apache.http.protocol.HttpContext; -import uk.gov.hmcts.reform.logging.HttpHeaders; -import uk.gov.hmcts.reform.logging.MdcFields; -import uk.gov.hmcts.reform.logging.tracing.RequestIdGenerator; - -import java.util.function.Supplier; - -public class OutboundRequestIdSettingInterceptor implements HttpRequestInterceptor { - - private Supplier nextRequestId; - - public OutboundRequestIdSettingInterceptor() { - this(RequestIdGenerator::next); - } - - public OutboundRequestIdSettingInterceptor(Supplier nextRequestId) { - this.nextRequestId = nextRequestId; - } - - @Override - public void process(HttpRequest request, HttpContext context) { - request.setHeader(HttpHeaders.REQUEST_ID, nextRequestId.get()); - request.setHeader(HttpHeaders.ROOT_REQUEST_ID, MdcFields.getRootRequestId()); - request.setHeader(HttpHeaders.ORIGIN_REQUEST_ID, MdcFields.getRequestId()); - } - -} diff --git a/java-logging-httpcomponents/src/main/java/uk/gov/hmcts/reform/logging/httpcomponents/OutboundRequestLoggingInterceptor.java b/java-logging-httpcomponents/src/main/java/uk/gov/hmcts/reform/logging/httpcomponents/OutboundRequestLoggingInterceptor.java deleted file mode 100644 index 18b8e8eb..00000000 --- a/java-logging-httpcomponents/src/main/java/uk/gov/hmcts/reform/logging/httpcomponents/OutboundRequestLoggingInterceptor.java +++ /dev/null @@ -1,63 +0,0 @@ -package uk.gov.hmcts.reform.logging.httpcomponents; - -import org.apache.http.HttpRequest; -import org.apache.http.HttpRequestInterceptor; -import org.apache.http.HttpResponse; -import org.apache.http.HttpResponseInterceptor; -import org.apache.http.RequestLine; -import org.apache.http.protocol.HttpContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.time.Clock; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import static java.time.Clock.systemUTC; - -import static net.logstash.logback.marker.Markers.appendEntries; -import static org.apache.http.protocol.HttpCoreContext.HTTP_TARGET_HOST; - -public class OutboundRequestLoggingInterceptor implements HttpRequestInterceptor, HttpResponseInterceptor { - private static final Logger LOG = LoggerFactory.getLogger(OutboundRequestLoggingInterceptor.class); - private final Clock clock; - - public OutboundRequestLoggingInterceptor() { - this(systemUTC()); - } - - /* default */ OutboundRequestLoggingInterceptor(Clock clock) { - this.clock = clock; - } - - @Override - public void process(HttpRequest request, HttpContext context) { - RequestLine requestLine = request.getRequestLine(); - - context.setAttribute("startedOn", clock.millis()); - context.setAttribute("method", requestLine.getMethod()); - context.setAttribute("url", context.getAttribute(HTTP_TARGET_HOST) + requestLine.getUri()); - - LOG.info(appendEntries(requestMarkers(context)), "Outbound request start"); - } - - @Override - public void process(HttpResponse response, HttpContext context) { - LOG.info(appendEntries(responseMarkers(context, response)), "Outbound request finish"); - } - - private Map responseMarkers(HttpContext context, HttpResponse response) { - Map markers = requestMarkers(context); - markers.put("responseTime", clock.millis() - (long) context.getAttribute("startedOn")); - markers.put("responseCode", response.getStatusLine().getStatusCode()); - return markers; - } - - private Map requestMarkers(HttpContext context) { - Map markers = new ConcurrentHashMap<>(); - markers.put("requestMethod", context.getAttribute("method")); - markers.put("requestURI", context.getAttribute("url")); - return markers; - } - -} diff --git a/java-logging-httpcomponents/src/test/java/uk/gov/hmcts/reform/logging/httpcomponents/FakeClock.java b/java-logging-httpcomponents/src/test/java/uk/gov/hmcts/reform/logging/httpcomponents/FakeClock.java deleted file mode 100644 index 6556ddaa..00000000 --- a/java-logging-httpcomponents/src/test/java/uk/gov/hmcts/reform/logging/httpcomponents/FakeClock.java +++ /dev/null @@ -1,31 +0,0 @@ -package uk.gov.hmcts.reform.logging.httpcomponents; - -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneId; - -class FakeClock extends Clock { - private long elapsed; - private final long increment; - - /* default */ FakeClock(int increment) { - super(); - this.increment = increment; - } - - @Override - public ZoneId getZone() { - return null; - } - - @Override - public Clock withZone(ZoneId zone) { - return null; - } - - @Override - public Instant instant() { - elapsed += increment; - return Instant.ofEpochMilli(elapsed); - } -} diff --git a/java-logging-httpcomponents/src/test/java/uk/gov/hmcts/reform/logging/httpcomponents/OutboundRequestIdSettingInterceptorTest.java b/java-logging-httpcomponents/src/test/java/uk/gov/hmcts/reform/logging/httpcomponents/OutboundRequestIdSettingInterceptorTest.java deleted file mode 100644 index 83dc7104..00000000 --- a/java-logging-httpcomponents/src/test/java/uk/gov/hmcts/reform/logging/httpcomponents/OutboundRequestIdSettingInterceptorTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package uk.gov.hmcts.reform.logging.httpcomponents; - -import org.apache.http.message.BasicHttpRequest; -import org.apache.http.protocol.HttpContext; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; -import uk.gov.hmcts.reform.logging.HttpHeaders; -import uk.gov.hmcts.reform.logging.MdcFields; - -import static org.assertj.core.api.Assertions.assertThat; - -@RunWith(MockitoJUnitRunner.class) -public class OutboundRequestIdSettingInterceptorTest { - - private static final String ANY = "any"; - - private OutboundRequestIdSettingInterceptor interceptor; - - @Mock - private HttpContext context; - - private BasicHttpRequest request; - - @Before - public void beforeEachTest() { - interceptor = new OutboundRequestIdSettingInterceptor(); - request = new BasicHttpRequest(ANY, ANY); - } - - @Test - public void requestIdShouldBeGenerated() { - interceptor = new OutboundRequestIdSettingInterceptor(() -> "test-id"); - interceptor.process(request, context); - assertThat(request.getFirstHeader(HttpHeaders.REQUEST_ID).getValue()).isEqualTo("test-id"); - } - - @Test - public void rootRequestIdShouldBeSetFromRootRequest() { - MdcFields.setRootRequestId("ROOT_REQUEST_ID"); - - interceptor.process(request, context); - - assertThat(request.getHeaders(HttpHeaders.ROOT_REQUEST_ID)).hasSize(1); - assertThat(request.getFirstHeader(HttpHeaders.ROOT_REQUEST_ID).getValue()).isEqualTo("ROOT_REQUEST_ID"); - } - - @Test - public void originRequestIdShouldBeSetFromCurrentRequest() { - MdcFields.setRequestId("CURRENT_REQUEST_ID"); - - interceptor.process(request, context); - - assertThat(request.getHeaders(HttpHeaders.ORIGIN_REQUEST_ID)).hasSize(1); - assertThat(request.getFirstHeader(HttpHeaders.ORIGIN_REQUEST_ID).getValue()).isEqualTo("CURRENT_REQUEST_ID"); - } - -} diff --git a/java-logging-httpcomponents/src/test/java/uk/gov/hmcts/reform/logging/httpcomponents/OutboundRequestLoggingInterceptorTest.java b/java-logging-httpcomponents/src/test/java/uk/gov/hmcts/reform/logging/httpcomponents/OutboundRequestLoggingInterceptorTest.java deleted file mode 100644 index 921a3ef3..00000000 --- a/java-logging-httpcomponents/src/test/java/uk/gov/hmcts/reform/logging/httpcomponents/OutboundRequestLoggingInterceptorTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package uk.gov.hmcts.reform.logging.httpcomponents; - -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.spi.ILoggingEvent; -import org.apache.http.ProtocolVersion; -import org.apache.http.message.BasicHttpRequest; -import org.apache.http.message.BasicHttpResponse; -import org.apache.http.message.BasicStatusLine; -import org.apache.http.protocol.BasicHttpContext; -import org.apache.http.protocol.HttpContext; -import org.assertj.core.data.Index; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.slf4j.LoggerFactory; -import uk.gov.hmcts.reform.logging.TestAppender; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import static ch.qos.logback.classic.Level.INFO; -import static net.logstash.logback.marker.Markers.appendEntries; -import static org.apache.http.protocol.HttpCoreContext.HTTP_TARGET_HOST; -import static org.assertj.core.api.Assertions.assertThat; -import static org.slf4j.Logger.ROOT_LOGGER_NAME; - -public class OutboundRequestLoggingInterceptorTest { - - private static final ProtocolVersion ANY_PROTOCOL = new ProtocolVersion("any", 0, 0); - - private final TestAppender testAppender = new TestAppender(); - - @Before - public void addAppender() { - ((Logger) LoggerFactory.getLogger(ROOT_LOGGER_NAME)).addAppender(testAppender); - } - - @After - public void removeAppender() { - ((Logger) LoggerFactory.getLogger(ROOT_LOGGER_NAME)).detachAppender(testAppender); - } - - @Test - public void logsRequestAndResponseFields() { - HttpContext context = new BasicHttpContext(); - context.setAttribute(HTTP_TARGET_HOST, "http://www.google.com"); - - OutboundRequestLoggingInterceptor interceptor = new OutboundRequestLoggingInterceptor(new FakeClock(20)); - - interceptor.process(new BasicHttpRequest("GET", "/something"), context); - interceptor.process(new BasicHttpResponse(new BasicStatusLine(ANY_PROTOCOL, 200, "any")), context); - - Map fields = new ConcurrentHashMap<>(); - fields.put("requestMethod", "GET"); - fields.put("requestURI", "http://www.google.com/something"); - testAppender.assertEvent(0, INFO, "Outbound request start", appendEntries(fields)); - - fields.put("responseTime", 20L); - fields.put("responseCode", 200); - testAppender.assertEvent(1, INFO, "Outbound request finish", appendEntries(fields)); - } - - @Test - public void allowEmptyConstructorToBuildDefaultClock() { - testAppender.clearEvents(); - - HttpContext context = new BasicHttpContext(); - context.setAttribute(HTTP_TARGET_HOST, "http://www.google.com"); - - OutboundRequestLoggingInterceptor interceptor = new OutboundRequestLoggingInterceptor(); - - interceptor.process(new BasicHttpRequest("GET", "/something"), context); - interceptor.process(new BasicHttpResponse(new BasicStatusLine(ANY_PROTOCOL, 200, "any")), context); - - assertThat(testAppender.getEvents()) - .extracting(ILoggingEvent::getMessage) - .contains("Outbound request start", Index.atIndex(0)) - .contains("Outbound request finish", Index.atIndex(1)); - } -} diff --git a/java-logging-spring/build.gradle b/java-logging-spring/build.gradle deleted file mode 100644 index cf87edd1..00000000 --- a/java-logging-spring/build.gradle +++ /dev/null @@ -1,60 +0,0 @@ -plugins { - id 'io.spring.dependency-management' version '1.0.11.RELEASE' -} - -java { - withJavadocJar() - withSourcesJar() -} - -publishing { - publications { - Spring(MavenPublication) { - from components.java - groupId project.group - artifactId 'logging-spring' - version project.version - } - } -} - -bintray { - user = System.getenv('BINTRAY_USER') - key = System.getenv('BINTRAY_KEY') - publications = ['Spring'] - publish = true - pkg { - repo = 'hmcts-maven' - name = 'logging-spring' - userOrg = 'hmcts' - licenses = ['MIT'] - vcsUrl = 'https://github.com/hmcts/java-logging' - version { - name = project.version - } - } -} - -def versions = [ - springBoot: '2.5.3' -] - -dependencyManagement { - imports { - mavenBom "org.springframework.boot:spring-boot-dependencies:${versions.springBoot}" - } -} - -dependencies { - implementation project(':') - api group: 'org.springframework.boot', name: 'spring-boot-autoconfigure' - - testImplementation project(':').sourceSets.test.output - testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-web' - testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-security' - testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test' - - testImplementation group: 'org.springframework.security', name: 'spring-security-test' - - testImplementation group: 'com.google.code.tempus-fugit', name: 'tempus-fugit', version: '1.1' -} diff --git a/java-logging-spring/src/main/java/uk/gov/hmcts/reform/logging/spring/RequestLoggingAutoConfiguration.java b/java-logging-spring/src/main/java/uk/gov/hmcts/reform/logging/spring/RequestLoggingAutoConfiguration.java deleted file mode 100644 index d151283b..00000000 --- a/java-logging-spring/src/main/java/uk/gov/hmcts/reform/logging/spring/RequestLoggingAutoConfiguration.java +++ /dev/null @@ -1,34 +0,0 @@ -package uk.gov.hmcts.reform.logging.spring; - -import org.springframework.boot.autoconfigure.AutoConfigureAfter; -import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; -import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import uk.gov.hmcts.reform.logging.filters.RequestIdsSettingFilter; -import uk.gov.hmcts.reform.logging.filters.RequestStatusLoggingFilter; - -import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE; - -@Configuration -@ConditionalOnWebApplication -@AutoConfigureAfter(WebMvcAutoConfiguration.class) -public class RequestLoggingAutoConfiguration { - - @Bean - public FilterRegistrationBean requestIdLoggingFilter() { - FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); - filterRegistrationBean.setFilter(new RequestIdsSettingFilter()); - filterRegistrationBean.setOrder(HIGHEST_PRECEDENCE); - return filterRegistrationBean; - } - - @Bean - public FilterRegistrationBean requestStatusLoggingFilter() { - FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); - filterRegistrationBean.setFilter(new RequestStatusLoggingFilter()); - filterRegistrationBean.setOrder(HIGHEST_PRECEDENCE + 1); - return filterRegistrationBean; - } -} diff --git a/java-logging-spring/src/main/resources/META-INF/spring.factories b/java-logging-spring/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 27ee7f9c..00000000 --- a/java-logging-spring/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=uk.gov.hmcts.reform.logging.spring.RequestLoggingAutoConfiguration diff --git a/java-logging-spring/src/test/java/uk/gov/hmcts/reform/logging/spring/RequestLoggingComponentTest.java b/java-logging-spring/src/test/java/uk/gov/hmcts/reform/logging/spring/RequestLoggingComponentTest.java deleted file mode 100644 index 906c3764..00000000 --- a/java-logging-spring/src/test/java/uk/gov/hmcts/reform/logging/spring/RequestLoggingComponentTest.java +++ /dev/null @@ -1,128 +0,0 @@ -package uk.gov.hmcts.reform.logging.spring; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.Logger; -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.joran.spi.JoranException; -import com.google.code.tempusfugit.temporal.Condition; -import com.google.code.tempusfugit.temporal.Duration; -import com.google.code.tempusfugit.temporal.Timeout; -import com.google.code.tempusfugit.temporal.WaitFor; -import org.assertj.core.groups.Tuple; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.util.ResourceUtils; -import uk.gov.hmcts.reform.logging.TestAppender; - -import java.io.IOException; -import java.io.InputStream; -import java.util.List; -import java.util.concurrent.TimeoutException; -import java.util.stream.Collectors; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.slf4j.Logger.ROOT_LOGGER_NAME; -import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = RANDOM_PORT, properties = "logging.config=src/test/resources/logback-test-sender.xml") -public class RequestLoggingComponentTest { - - @Autowired - private TestRestTemplate restTemplate; - - @Autowired - private List filters; - - @Before - public void listenForEvents() throws JoranException, IOException { - LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); - loggerContext.reset(); - JoranConfigurator configurator = new JoranConfigurator(); - - try (InputStream configStream = ResourceUtils.getURL("classpath:logback-test-receiver.xml").openStream()) { - configurator.setContext(loggerContext); - configurator.doConfigure(configStream); - } - } - - private Condition eventCondition(String message) { - return () -> loggedEvents().stream().filter( - event -> event.getFormattedMessage().startsWith(message) - ).collect(Collectors.toList()).size() == 1; - } - - private void awaitForMessage(String message) throws TimeoutException, InterruptedException { - WaitFor.waitOrTimeout(eventCondition(message), Timeout.timeout(Duration.seconds(5))); - } - - @Test - public void requestProcessedMessageShouldBeLoggedForPublicResource() throws InterruptedException, TimeoutException { - ResponseEntity response = restTemplate.getForEntity("/public", String.class); - - assertThat(response.getBody()).isEqualTo("OK"); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - - awaitForMessage("Request GET /public processed"); - } - - @Test - public void requestProcessedMessageShouldBeLoggedForProtectedResource() - throws InterruptedException, TimeoutException { - - // making sure our Filters are placed outside SecurityFilterChain - // and get executed no matter request is allowed or not - ResponseEntity response = restTemplate.getForEntity("/protected", String.class); - - assertThat(response.getBody()).isNotEqualTo("OK"); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN); - - awaitForMessage("Request GET /protected processed"); - } - - @Test - public void requestFailedMessageShouldBeLoggedForFailingResource() throws InterruptedException, TimeoutException { - // making sure our Filters are not executed twice for failed requests - ResponseEntity response = restTemplate.getForEntity("/failing", String.class); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - - awaitForMessage("Request GET /failing failed"); - } - - @Test - public void requestNotFoundMessageShouldBeLoggedForDestroyingResource() - throws InterruptedException, TimeoutException { - - // would be better to close context but fails completing tests - filters.forEach(filter -> filter.getFilter().destroy()); - ResponseEntity response = restTemplate.getForEntity("/destroying", String.class); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - - List events = loggedEvents(); - - assertThat(events).extracting("level", "message") - .containsOnlyOnce(Tuple.tuple(Level.DEBUG, "Settings logging destroyed due to timeout or filter exit")) - .containsOnlyOnce(Tuple.tuple(Level.DEBUG, "Status logging destroyed due to timeout or filter exit")); - - awaitForMessage("Request GET /destroying processed"); - } - - private List loggedEvents() { - Logger rootLogger = (Logger) LoggerFactory.getLogger(ROOT_LOGGER_NAME); - TestAppender testAppender = (TestAppender) rootLogger.getAppender("TEST_APPENDER"); - return testAppender.getEvents(); - } -} diff --git a/java-logging-spring/src/test/java/uk/gov/hmcts/reform/logging/spring/SpringBootTestApplication.java b/java-logging-spring/src/test/java/uk/gov/hmcts/reform/logging/spring/SpringBootTestApplication.java deleted file mode 100644 index 3826eebf..00000000 --- a/java-logging-spring/src/test/java/uk/gov/hmcts/reform/logging/spring/SpringBootTestApplication.java +++ /dev/null @@ -1,58 +0,0 @@ -package uk.gov.hmcts.reform.logging.spring; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@SpringBootApplication -@SuppressWarnings("HideUtilityClassConstructor") -public class SpringBootTestApplication { - public static void main(String[] args) { - SpringApplication.run(SpringBootTestApplication.class, args); - } - - @RestController - public static class TestController { - - private class RequestMappingException extends RuntimeException { - public static final long serialVersionUID = 4328743; // copy from pmd docs :D - - /* default */ RequestMappingException(String message) { - super(message); - } - } - - @RequestMapping("/public") - public String publicEndpoint() { - return "OK"; - } - - @RequestMapping("/protected") - public String protectedEndpoint() { - return "OK"; - } - - @RequestMapping("/failing") - public String failingEndpoint() throws RequestMappingException { - throw new RequestMappingException("Failing endpoint"); - } - } - - @Configuration - @EnableWebSecurity - public class WebSecurityConfig extends WebSecurityConfigurerAdapter { - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .authorizeRequests() - .antMatchers("/public").permitAll() - .antMatchers("/failing").permitAll() - .antMatchers("/protected").authenticated(); - } - } -} diff --git a/java-logging-spring/src/test/resources/logback-test-receiver.xml b/java-logging-spring/src/test/resources/logback-test-receiver.xml deleted file mode 100644 index 71bcc7ce..00000000 --- a/java-logging-spring/src/test/resources/logback-test-receiver.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - ${SOCKET_APPENDER_PORT:-38249} - - diff --git a/java-logging-spring/src/test/resources/logback-test-sender.xml b/java-logging-spring/src/test/resources/logback-test-sender.xml deleted file mode 100644 index 9c123ac9..00000000 --- a/java-logging-spring/src/test/resources/logback-test-sender.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - localhost - ${SOCKET_APPENDER_PORT:-38249} - 10000 - false - - - - - - diff --git a/settings.gradle b/settings.gradle index 3ce68c08..83a3d54f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,3 @@ rootProject.name = 'java-logging' -include 'java-logging-httpcomponents' -include 'java-logging-spring' include 'java-logging-appinsights' diff --git a/src/main/java/uk/gov/hmcts/reform/logging/HttpHeaders.java b/src/main/java/uk/gov/hmcts/reform/logging/HttpHeaders.java deleted file mode 100644 index 2e83b6a0..00000000 --- a/src/main/java/uk/gov/hmcts/reform/logging/HttpHeaders.java +++ /dev/null @@ -1,11 +0,0 @@ -package uk.gov.hmcts.reform.logging; - -public final class HttpHeaders { - public static final String REQUEST_ID = "Request-Id"; - public static final String ROOT_REQUEST_ID = "Root-Request-Id"; - public static final String ORIGIN_REQUEST_ID = "Origin-Request-Id"; - - private HttpHeaders() { - // Constants class - } -} diff --git a/src/main/java/uk/gov/hmcts/reform/logging/MdcFields.java b/src/main/java/uk/gov/hmcts/reform/logging/MdcFields.java deleted file mode 100644 index a701e9ff..00000000 --- a/src/main/java/uk/gov/hmcts/reform/logging/MdcFields.java +++ /dev/null @@ -1,53 +0,0 @@ -package uk.gov.hmcts.reform.logging; - -import org.slf4j.MDC; - -public final class MdcFields { - - private static final String FIELD_SESSION_ID = "sessionId"; - private static final String FIELD_ROOT_REQUEST_ID = "rootRequestId"; - private static final String FIELD_ORIGIN_REQUEST_ID = "originRequestId"; - private static final String FIELD_REQUEST_ID = "requestId"; - - private MdcFields() { - } - - public static void setSessionId(String sessionId) { - MDC.put(FIELD_SESSION_ID, sessionId); - } - - public static String getSessionId() { - return MDC.get(FIELD_SESSION_ID); - } - - public static void setRootRequestId(String requestId) { - MDC.put(FIELD_ROOT_REQUEST_ID, requestId); - } - - public static String getRootRequestId() { - return MDC.get(FIELD_ROOT_REQUEST_ID); - } - - public static void setOriginRequestId(String requestId) { - MDC.put(FIELD_ORIGIN_REQUEST_ID, requestId); - } - - public static String getOriginRequestId() { - return MDC.get(FIELD_ORIGIN_REQUEST_ID); - } - - public static void setRequestId(String requestId) { - MDC.put(FIELD_REQUEST_ID, requestId); - } - - public static String getRequestId() { - return MDC.get(FIELD_REQUEST_ID); - } - - public static void removeAll() { - MDC.remove(FIELD_SESSION_ID); - MDC.remove(FIELD_ROOT_REQUEST_ID); - MDC.remove(FIELD_ORIGIN_REQUEST_ID); - MDC.remove(FIELD_REQUEST_ID); - } -} diff --git a/src/main/java/uk/gov/hmcts/reform/logging/filters/RequestIdsSettingFilter.java b/src/main/java/uk/gov/hmcts/reform/logging/filters/RequestIdsSettingFilter.java deleted file mode 100644 index f4990b01..00000000 --- a/src/main/java/uk/gov/hmcts/reform/logging/filters/RequestIdsSettingFilter.java +++ /dev/null @@ -1,88 +0,0 @@ -package uk.gov.hmcts.reform.logging.filters; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import uk.gov.hmcts.reform.logging.HttpHeaders; -import uk.gov.hmcts.reform.logging.MdcFields; -import uk.gov.hmcts.reform.logging.tracing.RequestIdGenerator; - -import java.io.IOException; -import java.util.function.Supplier; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -public class RequestIdsSettingFilter implements Filter { - - private static final Logger LOG = LoggerFactory.getLogger(RequestIdsSettingFilter.class); - - private final Supplier requestIdGenerator; - - public RequestIdsSettingFilter() { - this(RequestIdGenerator::next); - } - - public RequestIdsSettingFilter(Supplier requestIdGenerator) { - this.requestIdGenerator = requestIdGenerator; - } - - /** - * {@inheritDoc}. - */ - @Override - public void init(FilterConfig filterConfig) { - // Nothing to do - } - - /** - * {@inheritDoc}. - */ - @Override - public void doFilter( - ServletRequest request, - ServletResponse response, - FilterChain chain - ) throws IOException, ServletException { - try { - HttpServletRequest httpServletRequest = (HttpServletRequest) request; - MdcFields.setSessionId(getSessionId(httpServletRequest)); - setRequestTracingHeaders(httpServletRequest); - - chain.doFilter(request, response); - } finally { - MdcFields.removeAll(); - } - } - - private void setRequestTracingHeaders(HttpServletRequest httpServletRequest) { - String requestId = httpServletRequest.getHeader(HttpHeaders.REQUEST_ID); - if (isPresent(requestId)) { - MdcFields.setRequestId(requestId); - String rootRequestId = httpServletRequest.getHeader(HttpHeaders.ROOT_REQUEST_ID); - MdcFields.setRootRequestId(isPresent(rootRequestId) ? rootRequestId : requestId); - MdcFields.setOriginRequestId(httpServletRequest.getHeader(HttpHeaders.ORIGIN_REQUEST_ID)); - } else { - MdcFields.setRequestId(requestIdGenerator.get()); - MdcFields.setRootRequestId(MdcFields.getRequestId()); - } - } - - private String getSessionId(HttpServletRequest httpServletRequest) { - HttpSession session = httpServletRequest.getSession(false); - return session == null ? null : session.getId(); - } - - private boolean isPresent(String string) { - return string != null && !string.isEmpty(); - } - - @Override - public void destroy() { - LOG.debug("Settings logging destroyed due to timeout or filter exit"); - } -} diff --git a/src/main/java/uk/gov/hmcts/reform/logging/filters/RequestStatusLoggingFilter.java b/src/main/java/uk/gov/hmcts/reform/logging/filters/RequestStatusLoggingFilter.java deleted file mode 100644 index 348375ce..00000000 --- a/src/main/java/uk/gov/hmcts/reform/logging/filters/RequestStatusLoggingFilter.java +++ /dev/null @@ -1,106 +0,0 @@ -package uk.gov.hmcts.reform.logging.filters; - -import net.logstash.logback.marker.LogstashMarker; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.time.Clock; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import static net.logstash.logback.marker.Markers.appendEntries; - - -public class RequestStatusLoggingFilter implements Filter { - private static final Logger LOG = LoggerFactory.getLogger(RequestStatusLoggingFilter.class); - - private final Clock clock; - - public RequestStatusLoggingFilter() { - this(Clock.systemDefaultZone()); - } - - public RequestStatusLoggingFilter(Clock clock) { - this.clock = clock; - } - - /** - * {@inheritDoc}. - */ - @Override - public void init(FilterConfig filterConfig) { - } - - /** - * {@inheritDoc}. - */ - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - long startTime = clock.millis(); - - // we use Marker instead of StructuredArgument because we want all - // these fields to appear at the top level of the JSON - try { - chain.doFilter(request, response); - - logMessage(request, response, startTime, true, null); - } catch (Exception e) { - logMessage(request, null, startTime, false, e); - - throw e; - } - } - - private void logMessage(ServletRequest request, - ServletResponse response, - long startTime, - boolean isSuccess, - Throwable cause) { - HttpServletRequest httpServletRequest = (HttpServletRequest) request; - String requestMethod = httpServletRequest.getMethod(); - String requestUri = httpServletRequest.getRequestURI(); - long responseTime = clock.millis() - startTime; - - // collect markers - Map fields = new ConcurrentHashMap<>(); - - fields.put("requestMethod", requestMethod); - fields.put("requestUri", requestUri); - fields.put("responseTime", responseTime); - - if (response != null) { - fields.put("responseCode", ((HttpServletResponse) response).getStatus()); - } - - LogstashMarker marker = appendEntries(fields); - - // format the message - String status = isSuccess ? "processed" : "failed"; - String message = String.format("Request %s %s %s in %dms", requestMethod, requestUri, status, responseTime); - - // log the event - if (isSuccess) { - LOG.info(marker, message); - } else { - LOG.error(marker, message, cause); - } - } - - /** - * {@inheritDoc}. - */ - @Override - public void destroy() { - LOG.debug("Status logging destroyed due to timeout or filter exit"); - } -} diff --git a/src/main/java/uk/gov/hmcts/reform/logging/tracing/RequestIdGenerator.java b/src/main/java/uk/gov/hmcts/reform/logging/tracing/RequestIdGenerator.java deleted file mode 100644 index d2ed9b74..00000000 --- a/src/main/java/uk/gov/hmcts/reform/logging/tracing/RequestIdGenerator.java +++ /dev/null @@ -1,15 +0,0 @@ -package uk.gov.hmcts.reform.logging.tracing; - -import java.util.UUID; - -public final class RequestIdGenerator { - - public static String next() { - return UUID.randomUUID().toString(); - } - - private RequestIdGenerator() { - // Utility class - } - -} diff --git a/src/test/java/uk/gov/hmcts/reform/logging/TestAppender.java b/src/test/java/uk/gov/hmcts/reform/logging/TestAppender.java deleted file mode 100644 index 3d26d9e7..00000000 --- a/src/test/java/uk/gov/hmcts/reform/logging/TestAppender.java +++ /dev/null @@ -1,43 +0,0 @@ -package uk.gov.hmcts.reform.logging; - -import ch.qos.logback.classic.Level; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.AppenderBase; -import org.slf4j.Marker; - -import java.util.ArrayList; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -public class TestAppender extends AppenderBase { - private final List events = new ArrayList<>(); - - public TestAppender() { - super(); - start(); - } - - @Override - protected void append(ILoggingEvent eventObject) { - events.add(eventObject); - } - - public void assertEvent(int index, Level expectedLevel, String expectedMessage, Marker marker) { - assertThat(event(index).getLevel()).isEqualTo(expectedLevel); - assertThat(event(index).getFormattedMessage()).isEqualTo(expectedMessage); - assertThat(event(index).getMarker()).isEqualTo(marker); - } - - private ILoggingEvent event(int index) { - return events.get(index); - } - - public void clearEvents() { - events.clear(); - } - - public List getEvents() { - return events; - } -} diff --git a/src/test/java/uk/gov/hmcts/reform/logging/filters/RequestIdsSettingFilterTest.java b/src/test/java/uk/gov/hmcts/reform/logging/filters/RequestIdsSettingFilterTest.java deleted file mode 100644 index 1a100e5a..00000000 --- a/src/test/java/uk/gov/hmcts/reform/logging/filters/RequestIdsSettingFilterTest.java +++ /dev/null @@ -1,121 +0,0 @@ -package uk.gov.hmcts.reform.logging.filters; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; -import uk.gov.hmcts.reform.logging.HttpHeaders; -import uk.gov.hmcts.reform.logging.MdcFields; - -import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class RequestIdsSettingFilterTest { - - private static final String GENERATED_REQUEST_ID = "some-generated-request-id"; - - @Mock - private ServletResponse response; - - @Mock - private HttpServletRequest request; - @Mock - private HttpSession httpSession; - - private final RequestIdsSettingFilter filter = new RequestIdsSettingFilter(() -> GENERATED_REQUEST_ID); - - @Before - public void beforeEach() { - MdcFields.removeAll(); - } - - @Test - public void allRequestHeadersShouldBeReusedIfRequestIdHeaderIsProvided() throws IOException, ServletException { - HttpServletRequest request = requestWithHeaders("id", "originId", "rootId"); - filter.doFilter(request, response, (req, resp) -> { - assertThat(MdcFields.getRequestId()).isEqualTo("id"); - assertThat(MdcFields.getOriginRequestId()).isEqualTo("originId"); - assertThat(MdcFields.getRootRequestId()).isEqualTo("rootId"); - }); - } - - @Test - public void originIdShouldNotBeSetWhenItsBlankAndRequestIdIsPresent() throws IOException, ServletException { - HttpServletRequest request = requestWithHeaders("id", null, null); - filter.doFilter(request, response, (req, resp) -> { - assertThat(MdcFields.getRequestId()).isEqualTo("id"); - assertThat(MdcFields.getOriginRequestId()).isNullOrEmpty(); - }); - } - - @Test - public void rootIdShouldBeSetToRequestIdWhenItsBlankAndRequestIdIsPresent() throws IOException, ServletException { - HttpServletRequest request = requestWithHeaders("id", null, null); - filter.doFilter(request, response, (req, resp) -> { - assertThat(MdcFields.getRequestId()).isEqualTo("id"); - assertThat(MdcFields.getRootRequestId()).isEqualTo(MdcFields.getRequestId()); - }); - } - - @Test - public void requestAndRootRequestIdsShouldBeSetWhenRequestIdIsNull() throws IOException, ServletException { - HttpServletRequest request = requestWithHeaders(null, null, null); - filter.doFilter(request, response, (req, resp) -> { - assertThat(MdcFields.getRequestId()).isEqualTo(GENERATED_REQUEST_ID); - assertThat(MdcFields.getRootRequestId()).isEqualTo(MdcFields.getRequestId()); - assertThat(MdcFields.getOriginRequestId()).isNullOrEmpty(); - }); - } - - @Test - public void requestAndRootRequestIdsShouldBeSetWhenRequestIdIsBlank() throws IOException, ServletException { - HttpServletRequest request = requestWithHeaders("", null, null); - filter.doFilter(request, response, (req, resp) -> { - assertThat(MdcFields.getRequestId()).isEqualTo(GENERATED_REQUEST_ID); - assertThat(MdcFields.getRootRequestId()).isEqualTo(MdcFields.getRequestId()); - assertThat(MdcFields.getOriginRequestId()).isNullOrEmpty(); - }); - } - - @Test - public void sessionIdShouldBeLoggedIfTheSessionExists() throws IOException, ServletException { - HttpServletRequest request = requestWithSessionId("some-session-id"); - - filter.doFilter(request, response, (req, resp) -> { - assertThat(MdcFields.getSessionId()).isEqualTo("some-session-id"); - }); - - assertThat(MdcFields.getSessionId()).isNull(); - } - - @Test - public void sessionIdShouldNotBeLoggedIfSessionDoesNotExist() throws IOException, ServletException { - filter.doFilter(request, response, (req, resp) -> { - assertThat(MdcFields.getSessionId()).isNull(); - }); - - assertThat(MdcFields.getSessionId()).isNull(); - } - - private HttpServletRequest requestWithHeaders(String requestId, String originRequestId, String rootRequestId) { - when(request.getHeader(HttpHeaders.REQUEST_ID)).thenReturn(requestId); - when(request.getHeader(HttpHeaders.ORIGIN_REQUEST_ID)).thenReturn(originRequestId); - when(request.getHeader(HttpHeaders.ROOT_REQUEST_ID)).thenReturn(rootRequestId); - return request; - } - - private HttpServletRequest requestWithSessionId(String sessionId) { - when(httpSession.getId()).thenReturn(sessionId); - - when(request.getSession(false)).thenReturn(httpSession); - return request; - } -} diff --git a/src/test/java/uk/gov/hmcts/reform/logging/filters/RequestStatusLoggingFilterTest.java b/src/test/java/uk/gov/hmcts/reform/logging/filters/RequestStatusLoggingFilterTest.java deleted file mode 100644 index 66176d07..00000000 --- a/src/test/java/uk/gov/hmcts/reform/logging/filters/RequestStatusLoggingFilterTest.java +++ /dev/null @@ -1,109 +0,0 @@ -package uk.gov.hmcts.reform.logging.filters; - -import ch.qos.logback.classic.Logger; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.slf4j.LoggerFactory; -import uk.gov.hmcts.reform.logging.TestAppender; - -import java.io.IOException; -import java.time.Clock; -import java.time.Instant; -import java.time.ZoneId; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import static ch.qos.logback.classic.Level.ERROR; -import static ch.qos.logback.classic.Level.INFO; -import static net.logstash.logback.marker.Markers.appendEntries; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.slf4j.Logger.ROOT_LOGGER_NAME; - -public class RequestStatusLoggingFilterTest { - private static final Clock FROZEN_CLOCK = Clock.fixed(Instant.EPOCH, ZoneId.systemDefault()); - private static final String GET = "GET"; - private static final String SOME_PATH = "/some/path"; - - private final TestAppender testAppender = new TestAppender(); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Before - public void addAppender() { - ((Logger) LoggerFactory.getLogger(ROOT_LOGGER_NAME)).addAppender(testAppender); - } - - @After - public void removeAppender() { - ((Logger) LoggerFactory.getLogger(ROOT_LOGGER_NAME)).detachAppender(testAppender); - } - - @Test - public void logsSuccessfulRequest() throws IOException, ServletException { - new RequestStatusLoggingFilter(FROZEN_CLOCK).doFilter( - requestWithMethodAndUri(), - responseWithStatus(400), - mock(FilterChain.class) - ); - - Map fields = new ConcurrentHashMap<>(); - fields.put("requestMethod", GET); - fields.put("requestUri", SOME_PATH); - fields.put("responseTime", 0L); - fields.put("responseCode", 400); - - String message = "Request " + GET + " " + SOME_PATH + " processed in 0ms"; - - testAppender.assertEvent(0, INFO, message, appendEntries(fields)); - } - - @Test - public void logsFailedRequest() throws IOException, ServletException { - thrown.expect(RuntimeException.class); - - new RequestStatusLoggingFilter(FROZEN_CLOCK).doFilter( - requestWithMethodAndUri(), - responseWithStatus(-1), - failingFilterChain() - ); - - Map fields = new ConcurrentHashMap<>(); - fields.put("requestMethod", GET); - fields.put("requestUri", SOME_PATH); - fields.put("responseTime", 0L); - - String message = "Request " + GET + " " + SOME_PATH + " failed in 0ms"; - - testAppender.assertEvent(0, ERROR, message, appendEntries(fields)); - } - - private HttpServletRequest requestWithMethodAndUri() { - HttpServletRequest request = mock(HttpServletRequest.class); - when(request.getMethod()).thenReturn(GET); - when(request.getRequestURI()).thenReturn(SOME_PATH); - return request; - } - - private HttpServletResponse responseWithStatus(int statusCode) { - HttpServletResponse response = mock(HttpServletResponse.class); - when(response.getStatus()).thenReturn(statusCode); - return response; - } - - private FilterChain failingFilterChain() throws IOException, ServletException { - FilterChain chain = mock(FilterChain.class); - doThrow(new RuntimeException("something failed")).when(chain).doFilter(any(), any()); - return chain; - } -} diff --git a/src/test/java/uk/gov/hmcts/reform/logging/tracing/RequestIdGeneratorTest.java b/src/test/java/uk/gov/hmcts/reform/logging/tracing/RequestIdGeneratorTest.java deleted file mode 100644 index ecfbe025..00000000 --- a/src/test/java/uk/gov/hmcts/reform/logging/tracing/RequestIdGeneratorTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package uk.gov.hmcts.reform.logging.tracing; - -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class RequestIdGeneratorTest { - - @Test - @SuppressWarnings("checkstyle:AbbreviationAsWordInName") - public void nextIdShouldReturnUUIDString() { - String id = RequestIdGenerator.next(); - assertThat(id).matches("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"); - } - - @Test - public void shouldGenerateDifferentValuesOnEachCall() { - String first = RequestIdGenerator.next(); - String second = RequestIdGenerator.next(); - String third = RequestIdGenerator.next(); - - assertThat(first).isNotEqualTo(second); - assertThat(second).isNotEqualTo(third); - assertThat(third).isNotEqualTo(first); - } - -}