Upgraded to jdk21, updated dependencies and added unit tests
Locusworks Team/app-logger/pipeline/head There was a failure building this commit
Locusworks Team/app-logger/pipeline/head There was a failure building this commit
This commit is contained in:
1 parent
94dcaf508d
commit
f49a8150d1
16 files changed
+789
-563
No files matched your search
Vendored
+91
-186
@@ -1,186 +1,91 @@
|
||||
#!groovy
|
||||
|
||||
// Required Jenkins plugins:
|
||||
// https://wiki.jenkins-ci.org/display/JENKINS/Timestamper
|
||||
// https://wiki.jenkins-ci.org/display/JENKINS/Static+Code+Analysis+Plug-ins
|
||||
// https://wiki.jenkins-ci.org/display/JENKINS/Checkstyle+Plugin ?
|
||||
// https://wiki.jenkins-ci.org/display/JENKINS/FindBugs+Plugin
|
||||
// https://wiki.jenkins-ci.org/display/JENKINS/PMD+Plugin ?
|
||||
// https://wiki.jenkins-ci.org/display/JENKINS/DRY+Plugin ?
|
||||
// https://wiki.jenkins-ci.org/display/JENKINS/Task+Scanner+Plugin
|
||||
// https://wiki.jenkins-ci.org/display/JENKINS/Javadoc+Plugin
|
||||
// https://wiki.jenkins-ci.org/display/JENKINS/JaCoCo+Plugin ?
|
||||
|
||||
|
||||
init()
|
||||
|
||||
def branch_name
|
||||
def branch_name_base
|
||||
def build_number
|
||||
def build_url
|
||||
def git_commit
|
||||
def job_name
|
||||
def tag
|
||||
def version
|
||||
def build_type
|
||||
def display_name
|
||||
|
||||
def init() {
|
||||
|
||||
// Keep the 5 most recent builds
|
||||
properties([[$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', numToKeepStr: '5']]])
|
||||
|
||||
build_number = env.BUILD_NUMBER
|
||||
build_url = env.BUILD_URL
|
||||
job_name = "${env.JOB_NAME}"
|
||||
branch_name = env.BRANCH_NAME
|
||||
branch_name_docker = branch_name.replaceAll(/\//,'.')
|
||||
persist = "/var/lib/jenkins/PERSIST/${branch_name_docker}"
|
||||
|
||||
// execute the branch type specific pipeline code
|
||||
try {
|
||||
|
||||
if (branch_name.indexOf('release/')==0) build_type='release'
|
||||
if (branch_name.indexOf('feature/')==0) build_type='feature'
|
||||
if (branch_name.indexOf('develop')==0) build_type='develop'
|
||||
if (branch_name.indexOf('hotfix')==0) build_type='hotfix'
|
||||
if (branch_name.indexOf('bugfix')==0) build_type='bugfix'
|
||||
if (branch_name.indexOf('master')==0) build_type='master'
|
||||
|
||||
// common pipeline elements
|
||||
node() {
|
||||
Initialize()
|
||||
SetVersion(build_type)
|
||||
print_vars() // after SetVersion - all variables now defined
|
||||
set_result('INPROGRESS')
|
||||
Build() // builds database via flyway migration
|
||||
}
|
||||
|
||||
if (branch_name.indexOf('develop')==0) {
|
||||
node() {
|
||||
Deploy();
|
||||
}
|
||||
} else if (branch_name.indexOf('release/')==0) {
|
||||
node() {
|
||||
Deploy();
|
||||
}
|
||||
}
|
||||
|
||||
node() {
|
||||
set_result('SUCCESS')
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
node() {
|
||||
set_result('FAILURE')
|
||||
}
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
def Build() {
|
||||
stage ('build') {
|
||||
mvn "install -DskipTests=true -Dbuild.revision=${git_commit}"
|
||||
step([$class: 'ArtifactArchiver', artifacts: '**/target/*.jar', fingerprint: true])
|
||||
}
|
||||
}
|
||||
|
||||
def Initialize() {
|
||||
stage ('initialize') {
|
||||
|
||||
// get new code
|
||||
checkout scm
|
||||
|
||||
git_commit = getSha1()
|
||||
}
|
||||
}
|
||||
|
||||
def Deploy() {
|
||||
stage ('deploy') {
|
||||
mvn "deploy -DskipTests=true -Dbuild.number=${build_number} -Dbuild.revision=${git_commit}"
|
||||
}
|
||||
}
|
||||
|
||||
def getSha1() {
|
||||
sha1 = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
|
||||
echo "sha1 is ${sha1}"
|
||||
return sha1
|
||||
}
|
||||
|
||||
def mvn(args) {
|
||||
withMaven(
|
||||
maven: 'maven-3.6.1',
|
||||
globalMavenSettingsConfig: 'locusworks-settings'
|
||||
) {
|
||||
|
||||
sh "mvn ${args}"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
def mvn_initial(args) {
|
||||
mvn(args)
|
||||
}
|
||||
|
||||
def set_result(status) {
|
||||
if ( status == 'SUCCESS' ) {
|
||||
currentBuild.result = status
|
||||
notify_bitbucket('SUCCESSFUL')
|
||||
} else if ( status == 'FAILURE' ) {
|
||||
currentBuild.result = status
|
||||
notify_bitbucket('FAILED')
|
||||
} else if ( status == 'INPROGRESS' ) {
|
||||
notify_bitbucket('INPROGRESS')
|
||||
} else {
|
||||
error ("unknown status")
|
||||
}
|
||||
|
||||
// save in persistence file for access the status page
|
||||
// make sure the directory exists first
|
||||
sh "mkdir -p $persist && echo $status > $persist/build.result"
|
||||
}
|
||||
|
||||
def notify_bitbucket(state) {
|
||||
}
|
||||
|
||||
def print_vars() {
|
||||
echo "build_number = ${build_number}"
|
||||
echo "build_url = ${build_url}"
|
||||
echo "job_name = ${job_name}"
|
||||
echo "branch_name = ${branch_name}"
|
||||
echo "branch_name_base = ${branch_name_base}"
|
||||
echo "build_type = ${build_type}"
|
||||
echo "display_name = ${currentBuild.displayName}"
|
||||
echo "version = ${version}"
|
||||
echo "git_commit = ${git_commit}"
|
||||
|
||||
}
|
||||
|
||||
def SetVersion( v ) {
|
||||
stage ('set version') {
|
||||
echo "set version ${v}"
|
||||
branch_name_base = (branch_name =~ /([^\/]+$)/)[0][0]
|
||||
if ( v == 'release' ) {
|
||||
// for release branches, where the branch is named "release/1.2.3",
|
||||
// derive the version and display name derive from the numeric suffix and append the build number
|
||||
// 3.2.1.100
|
||||
version = branch_name_base + "." + build_number + "-RELEASE";
|
||||
//version = branch_name.substring('release/'.length()) + "." + build_number
|
||||
currentBuild.displayName = version
|
||||
} else if (v == 'develop') {
|
||||
version = branch_name_base + "." + build_number + "-SNAPSHOT";
|
||||
currentBuild.displayName = version
|
||||
} else {
|
||||
// for all other branches the version number is 0 with an appended build number
|
||||
// and for the display name use the jenkins default #n and add the branch name
|
||||
// #101 - feature/user/foo
|
||||
//version = '0.' + build_number
|
||||
version = branch_name_base + "." + build_number
|
||||
currentBuild.displayName = "#" + build_number + " - " + branch_name_base
|
||||
}
|
||||
display_name = currentBuild.displayName
|
||||
mvn_initial "versions:set -DnewVersion=${version}"
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
options {
|
||||
buildDiscarder(logRotator(numToKeepStr: '5'))
|
||||
disableConcurrentBuilds()
|
||||
skipDefaultCheckout(true)
|
||||
timestamps()
|
||||
}
|
||||
|
||||
environment {
|
||||
BUILD_VERSION = ''
|
||||
DEPLOY_BUILD = 'false'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
checkout scm
|
||||
}
|
||||
}
|
||||
|
||||
stage('Set version') {
|
||||
steps {
|
||||
script {
|
||||
String branch = env.BRANCH_NAME
|
||||
if (!branch) {
|
||||
error('BRANCH_NAME is unavailable; this pipeline must run as a multibranch job')
|
||||
}
|
||||
|
||||
def releaseMatch = branch =~ /^release\/(\d+\.\d+\.\d+)$/
|
||||
if (releaseMatch.matches()) {
|
||||
env.BUILD_VERSION = "${releaseMatch[0][1]}.${env.BUILD_NUMBER}-RELEASE"
|
||||
env.DEPLOY_BUILD = 'true'
|
||||
} else if (branch == 'develop') {
|
||||
env.BUILD_VERSION = "develop.${env.BUILD_NUMBER}-SNAPSHOT"
|
||||
env.DEPLOY_BUILD = 'true'
|
||||
} else {
|
||||
String safeBranch = branch.replaceAll(/[^A-Za-z0-9._-]/, '-')
|
||||
env.BUILD_VERSION = "0.0.${env.BUILD_NUMBER}-${safeBranch}-SNAPSHOT"
|
||||
}
|
||||
currentBuild.displayName = env.BUILD_VERSION
|
||||
}
|
||||
|
||||
withMaven(maven: 'maven-3.9.16', globalMavenSettingsConfig: 'locusworks-settings') {
|
||||
sh 'mvn -B versions:set -DgenerateBackupPoms=false -DnewVersion="$BUILD_VERSION"'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build and test') {
|
||||
steps {
|
||||
withMaven(maven: 'maven-3.9.16', globalMavenSettingsConfig: 'locusworks-settings') {
|
||||
sh 'mvn -B clean verify -Dbuild.revision="$GIT_COMMIT"'
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
junit allowEmptyResults: true, testResults: '**/target/surefire-reports/*.xml'
|
||||
}
|
||||
success {
|
||||
archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true
|
||||
archiveArtifacts artifacts: '**/target/site/jacoco/**', fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Deploy') {
|
||||
when {
|
||||
expression { env.DEPLOY_BUILD == 'true' }
|
||||
}
|
||||
steps {
|
||||
withMaven(maven: 'maven-3.9.16', globalMavenSettingsConfig: 'locusworks-settings') {
|
||||
sh 'mvn -B deploy -DskipTests -Ddependency-check.skip=true -Dbuild.number="$BUILD_NUMBER" -Dbuild.revision="$GIT_COMMIT"'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
success {
|
||||
echo "Published build ${env.BUILD_VERSION} successfully"
|
||||
}
|
||||
failure {
|
||||
echo "Build ${env.BUILD_VERSION ?: env.BUILD_NUMBER} failed"
|
||||
}
|
||||
cleanup {
|
||||
deleteDir()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
# This is a sample build configuration for Java (Maven).
|
||||
# Check our guides at https://confluence.atlassian.com/x/zd-5Mw for more examples.
|
||||
# Only use spaces to indent your .yml configuration.
|
||||
# -----
|
||||
# You can specify a custom docker image from Docker Hub as your build environment.
|
||||
image: maven:3.3.9
|
||||
|
||||
pipelines:
|
||||
default:
|
||||
- step:
|
||||
caches:
|
||||
- maven
|
||||
script: # Modify the commands below to build your repository.
|
||||
- mvn -B verify # -B batch mode makes Maven less verbose
|
||||
@@ -1,156 +1,197 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>net.locusworks</groupId>
|
||||
<artifactId>applogger</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>Application Logger</name>
|
||||
<description>Logger library for applications</description>
|
||||
|
||||
<scm>
|
||||
<url>ssh://gitea@gitea.locusworks.net:7999/locusworks/app-logger.git</url>
|
||||
</scm>
|
||||
<organization>
|
||||
<name>locusworks</name>
|
||||
<url>www.locusworks.net</url>
|
||||
</organization>
|
||||
|
||||
<properties>
|
||||
<main.basedir>${project.basedir}</main.basedir>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<log4j.version>2.19.0</log4j.version>
|
||||
<slf4j.version>2.0.1</slf4j.version>
|
||||
<nexus.repo>https://nexus.locusworks.net</nexus.repo>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M7</version>
|
||||
<configuration>
|
||||
<forkMode>always</forkMode>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.10.1</version>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
<failOnError>true</failOnError>
|
||||
<compilerArgs>
|
||||
<arg>-Xlint:all</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>7.2.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>enforce</id>
|
||||
<configuration>
|
||||
<rules>
|
||||
<DependencyConvergence />
|
||||
</rules>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>enforce</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-slf4j-impl</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>nexus-snapshot</id>
|
||||
<url>${nexus.repo}/repository/locusworks-snapshot/</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>nexus-release</id>
|
||||
<url>${nexus.repo}/repository/locusworks-release/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>locusworks-public</id>
|
||||
<name>locusworks-public</name>
|
||||
<url>${nexus.repo}/repository/locusworks-public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>locusworks-public</id>
|
||||
<url>${nexus.repo}/repository/locusworks-public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>net.locusworks</groupId>
|
||||
<artifactId>applogger</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>Application Logger</name>
|
||||
<description>Logger library for applications</description>
|
||||
|
||||
<scm>
|
||||
<url>ssh://gitea@gitea.locusworks.net:7999/locusworks/app-logger.git</url>
|
||||
</scm>
|
||||
<organization>
|
||||
<name>locusworks</name>
|
||||
<url>www.locusworks.net</url>
|
||||
</organization>
|
||||
|
||||
<properties>
|
||||
<slf4j.version>2.0.18</slf4j.version>
|
||||
<junit.version>5.14.4</junit.version>
|
||||
<mockito.version>5.23.0</mockito.version>
|
||||
<jacoco.version>0.8.15</jacoco.version>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<nexus.repo>https://nexus.locusworks.net</nexus.repo>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
<version>${jacoco.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>prepare-agent</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>report</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>report</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>coverage-check</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<rules>
|
||||
<rule>
|
||||
<element>BUNDLE</element>
|
||||
<limits>
|
||||
<limit>
|
||||
<counter>LINE</counter>
|
||||
<value>COVEREDRATIO</value>
|
||||
<minimum>0.75</minimum>
|
||||
</limit>
|
||||
</limits>
|
||||
</rule>
|
||||
</rules>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.5.6</version>
|
||||
<configuration>
|
||||
<argLine>@{argLine} -javaagent:${settings.localRepository}/org/mockito/mockito-core/${mockito.version}/mockito-core-${mockito.version}.jar</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.15.0</version>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
<failOnError>true</failOnError>
|
||||
<compilerArgs>
|
||||
<arg>-Xlint:all</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>13.0.0</version>
|
||||
<configuration>
|
||||
<skipProvidedScope>true</skipProvidedScope>
|
||||
<skipTestScope>true</skipTestScope>
|
||||
<failOnError>true</failOnError>
|
||||
<versionCheckEnabled>true</versionCheckEnabled>
|
||||
<nvdApiKey>e2eb1036-9b5b-4df9-95e7-0888be947011</nvdApiKey>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>3.6.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>enforce</id>
|
||||
<configuration>
|
||||
<rules>
|
||||
<DependencyConvergence />
|
||||
</rules>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>enforce</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>nexus-snapshot</id>
|
||||
<url>${nexus.repo}/repository/locusworks-snapshot/</url>
|
||||
</snapshotRepository>
|
||||
<repository>
|
||||
<id>nexus-release</id>
|
||||
<url>${nexus.repo}/repository/locusworks-release/</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>locusworks-public</id>
|
||||
<name>locusworks-public</name>
|
||||
<url>${nexus.repo}/repository/locusworks-public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>locusworks-public</id>
|
||||
<url>${nexus.repo}/repository/locusworks-public/</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
||||
@@ -4,7 +4,9 @@ import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.helpers.FormattingTuple;
|
||||
import org.slf4j.helpers.MessageFormatter;
|
||||
|
||||
/**
|
||||
* Logger implementation to use across applications. Extends slf4j logger to work with other logging applications
|
||||
@@ -13,9 +15,9 @@ import org.slf4j.Marker;
|
||||
*/
|
||||
public class ApplicationLogger implements org.slf4j.Logger {
|
||||
|
||||
protected static final String DEFAULT_FORMAT = "%s";
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ApplicationLogger.class);
|
||||
protected static final String DEFAULT_FORMAT = "{}";
|
||||
|
||||
private final Logger logger;
|
||||
|
||||
private final String name;
|
||||
|
||||
@@ -41,10 +43,15 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
* @param name name of the logger
|
||||
* @param level level of logging to set the logger to
|
||||
*/
|
||||
protected ApplicationLogger(String name, LogLevel level) {
|
||||
this.name = name;
|
||||
this.level = level;
|
||||
}
|
||||
protected ApplicationLogger(String name, LogLevel level) {
|
||||
this(name, level, LoggerFactory.getLogger(name));
|
||||
}
|
||||
|
||||
ApplicationLogger(String name, LogLevel level, Logger logger) {
|
||||
this.name = name;
|
||||
this.level = level;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -104,8 +111,8 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTraceEnabled() {
|
||||
return this.level.log(LogLevel.TRACE);
|
||||
public boolean isTraceEnabled() {
|
||||
return enabled(LogLevel.TRACE) && logger.isTraceEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -129,43 +136,43 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(String msg, Throwable t) {
|
||||
trace("%s%n%s", msg, getStackTrace(t.getStackTrace()));
|
||||
public void trace(String msg, Throwable t) {
|
||||
log(LogLevel.TRACE, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTraceEnabled(Marker marker) {
|
||||
return isTraceEnabled();
|
||||
public boolean isTraceEnabled(Marker marker) {
|
||||
return enabled(LogLevel.TRACE) && logger.isTraceEnabled(marker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Marker marker, String msg) {
|
||||
trace(msg);
|
||||
public void trace(Marker marker, String msg) {
|
||||
markerLog(LogLevel.TRACE, marker, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Marker marker, String format, Object arg) {
|
||||
trace(format, arg);
|
||||
markerLog(LogLevel.TRACE, marker, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Marker marker, String format, Object arg1, Object arg2) {
|
||||
trace(format, arg1, arg2);
|
||||
markerLog(LogLevel.TRACE, marker, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Marker marker, String format, Object... argArray) {
|
||||
trace(format, argArray);
|
||||
markerLog(LogLevel.TRACE, marker, format, argArray);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Marker marker, String msg, Throwable t) {
|
||||
trace(msg, t);
|
||||
markerLog(LogLevel.TRACE, marker, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugEnabled() {
|
||||
return this.level.log(LogLevel.DEBUG);
|
||||
public boolean isDebugEnabled() {
|
||||
return enabled(LogLevel.DEBUG) && logger.isDebugEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -189,43 +196,43 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(String msg, Throwable t) {
|
||||
debug("%s%n%s", msg, getStackTrace(t.getStackTrace()));
|
||||
public void debug(String msg, Throwable t) {
|
||||
log(LogLevel.DEBUG, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugEnabled(Marker marker) {
|
||||
return isDebugEnabled();
|
||||
public boolean isDebugEnabled(Marker marker) {
|
||||
return enabled(LogLevel.DEBUG) && logger.isDebugEnabled(marker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Marker marker, String msg) {
|
||||
debug(msg);
|
||||
public void debug(Marker marker, String msg) {
|
||||
markerLog(LogLevel.DEBUG, marker, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Marker marker, String format, Object arg) {
|
||||
debug(format, arg);
|
||||
markerLog(LogLevel.DEBUG, marker, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Marker marker, String format, Object arg1, Object arg2) {
|
||||
debug(format, arg1, arg2);
|
||||
markerLog(LogLevel.DEBUG, marker, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Marker marker, String format, Object... arguments) {
|
||||
debug(format, arguments);
|
||||
markerLog(LogLevel.DEBUG, marker, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Marker marker, String msg, Throwable t) {
|
||||
debug(msg, t);
|
||||
markerLog(LogLevel.DEBUG, marker, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInfoEnabled() {
|
||||
return this.level.log(LogLevel.INFO);
|
||||
public boolean isInfoEnabled() {
|
||||
return enabled(LogLevel.INFO) && logger.isInfoEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -249,8 +256,8 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(String msg, Throwable t) {
|
||||
info("%s%n%s", msg, getStackTrace(t.getStackTrace()));
|
||||
public void info(String msg, Throwable t) {
|
||||
log(LogLevel.INFO, msg, t);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -282,38 +289,38 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInfoEnabled(Marker marker) {
|
||||
return isInfoEnabled();
|
||||
public boolean isInfoEnabled(Marker marker) {
|
||||
return enabled(LogLevel.INFO) && logger.isInfoEnabled(marker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Marker marker, String msg) {
|
||||
info(msg);
|
||||
public void info(Marker marker, String msg) {
|
||||
markerLog(LogLevel.INFO, marker, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Marker marker, String format, Object arg) {
|
||||
info(format, arg);
|
||||
markerLog(LogLevel.INFO, marker, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Marker marker, String format, Object arg1, Object arg2) {
|
||||
info(format, arg1, arg2);
|
||||
markerLog(LogLevel.INFO, marker, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Marker marker, String format, Object... arguments) {
|
||||
info(format, arguments);
|
||||
markerLog(LogLevel.INFO, marker, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Marker marker, String msg, Throwable t) {
|
||||
info(msg, t);
|
||||
markerLog(LogLevel.INFO, marker, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWarnEnabled() {
|
||||
return this.level.log(LogLevel.WARN);
|
||||
public boolean isWarnEnabled() {
|
||||
return enabled(LogLevel.WARN) && logger.isWarnEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -337,38 +344,38 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(String msg, Throwable t) {
|
||||
warn("%s%n%s", msg, getStackTrace(t.getStackTrace()));
|
||||
public void warn(String msg, Throwable t) {
|
||||
log(LogLevel.WARN, msg, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWarnEnabled(Marker marker) {
|
||||
return isWarnEnabled();
|
||||
public boolean isWarnEnabled(Marker marker) {
|
||||
return enabled(LogLevel.WARN) && logger.isWarnEnabled(marker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Marker marker, String msg) {
|
||||
warn(msg);
|
||||
public void warn(Marker marker, String msg) {
|
||||
markerLog(LogLevel.WARN, marker, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Marker marker, String format, Object arg) {
|
||||
warn(format, arg);
|
||||
markerLog(LogLevel.WARN, marker, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Marker marker, String format, Object arg1, Object arg2) {
|
||||
warn(format, arg1, arg2);
|
||||
markerLog(LogLevel.WARN, marker, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Marker marker, String format, Object... arguments) {
|
||||
warn(format, arguments);
|
||||
markerLog(LogLevel.WARN, marker, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Marker marker, String msg, Throwable t) {
|
||||
warn(msg, t);
|
||||
markerLog(LogLevel.WARN, marker, msg, t);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -399,8 +406,8 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorEnabled() {
|
||||
return this.level.log(LogLevel.ERROR);
|
||||
public boolean isErrorEnabled() {
|
||||
return enabled(LogLevel.ERROR) && logger.isErrorEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -428,8 +435,8 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(String msg, Throwable t) {
|
||||
error("%s%n%s", msg, getStackTrace(t.getStackTrace()));
|
||||
public void error(String msg, Throwable t) {
|
||||
log(LogLevel.ERROR, msg, t);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -447,8 +454,8 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
* @param sb String builder to append message to
|
||||
* @param e throwable error to log
|
||||
*/
|
||||
public void error(Map<String, String> values, StringBuilder sb, Throwable e) {
|
||||
error(values, null, sb);
|
||||
public void error(Map<String, String> values, StringBuilder sb, Throwable e) {
|
||||
error(values, null, sb, e);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -468,41 +475,38 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
* @param sb string builder to append messages to
|
||||
* @param e Throwable error to log
|
||||
*/
|
||||
public void error(Map<String, String> values, String valueFormat, StringBuilder sb, Throwable e) {
|
||||
msgHelper(LogLevel.ERROR, values, valueFormat, sb);
|
||||
if (e != null) {
|
||||
msgHelper(LogLevel.ERROR,"", e);
|
||||
}
|
||||
public void error(Map<String, String> values, String valueFormat, StringBuilder sb, Throwable e) {
|
||||
log(LogLevel.ERROR, formatValues(values, valueFormat, sb), e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorEnabled(Marker marker) {
|
||||
return isErrorEnabled();
|
||||
public boolean isErrorEnabled(Marker marker) {
|
||||
return enabled(LogLevel.ERROR) && logger.isErrorEnabled(marker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Marker marker, String msg) {
|
||||
error(msg);
|
||||
public void error(Marker marker, String msg) {
|
||||
markerLog(LogLevel.ERROR, marker, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Marker marker, String format, Object arg) {
|
||||
error(format, arg);
|
||||
markerLog(LogLevel.ERROR, marker, format, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Marker marker, String format, Object arg1, Object arg2) {
|
||||
error(format, arg1, arg2);
|
||||
markerLog(LogLevel.ERROR, marker, format, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Marker marker, String format, Object... arguments) {
|
||||
error(format, arguments);
|
||||
markerLog(LogLevel.ERROR, marker, format, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Marker marker, String msg, Throwable t) {
|
||||
error(msg, t);
|
||||
markerLog(LogLevel.ERROR, marker, msg, t);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -510,7 +514,7 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
* @param level log level to use
|
||||
* @param message message to log
|
||||
*/
|
||||
protected void log(LogLevel level, String message) {
|
||||
protected void log(LogLevel level, String message) {
|
||||
if (level == null ||this.level == null || level.toInt() < this.level.toInt()) return;
|
||||
|
||||
switch (level) {
|
||||
@@ -535,7 +539,43 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean enabled(LogLevel messageLevel) {
|
||||
LogLevel current = this.level;
|
||||
return current != null && current != LogLevel.OFF && messageLevel.toInt() >= current.toInt();
|
||||
}
|
||||
|
||||
protected void log(LogLevel level, String message, Throwable throwable) {
|
||||
if (level == null || this.level == null || level.toInt() < this.level.toInt()) return;
|
||||
switch (level) {
|
||||
case ALL:
|
||||
case TRACE: logger.trace(message, throwable); break;
|
||||
case DEBUG: logger.debug(message, throwable); break;
|
||||
case INFO: logger.info(message, throwable); break;
|
||||
case WARN: logger.warn(message, throwable); break;
|
||||
case ERROR:
|
||||
case FATAL: logger.error(message, throwable); break;
|
||||
case OFF:
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
private void markerLog(LogLevel level, Marker marker, String message, Object... arguments) {
|
||||
if (level == null || this.level == null || level.toInt() < this.level.toInt()) return;
|
||||
FormattingTuple tuple = MessageFormatter.arrayFormat(message, arguments);
|
||||
switch (level) {
|
||||
case ALL:
|
||||
case TRACE: logger.trace(marker, tuple.getMessage(), tuple.getThrowable()); break;
|
||||
case DEBUG: logger.debug(marker, tuple.getMessage(), tuple.getThrowable()); break;
|
||||
case INFO: logger.info(marker, tuple.getMessage(), tuple.getThrowable()); break;
|
||||
case WARN: logger.warn(marker, tuple.getMessage(), tuple.getThrowable()); break;
|
||||
case ERROR:
|
||||
case FATAL: logger.error(marker, tuple.getMessage(), tuple.getThrowable()); break;
|
||||
case OFF:
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the exception stack trace to a string
|
||||
@@ -566,11 +606,13 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
* @param valueFormat value format to map values as
|
||||
* @param sb String builder to append messages to
|
||||
*/
|
||||
private void msgHelper(LogLevel level, Map<String, String> values, String valueFormat, StringBuilder sb) {
|
||||
|
||||
if (sb == null) {
|
||||
sb = new StringBuilder();
|
||||
}
|
||||
private void msgHelper(LogLevel level, Map<String, String> values, String valueFormat, StringBuilder sb) {
|
||||
log(level, formatValues(values, valueFormat, sb));
|
||||
}
|
||||
|
||||
private String formatValues(Map<String, String> values, String valueFormat, StringBuilder sb) {
|
||||
if (values == null) throw new IllegalArgumentException("values must not be null");
|
||||
if (sb == null) sb = new StringBuilder();
|
||||
|
||||
if (valueFormat == null || valueFormat.trim().isEmpty()) {
|
||||
int longest = 0;
|
||||
@@ -590,8 +632,8 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
.map(entry -> String.format(format, entry.getKey(), entry.getValue()))
|
||||
.forEach(builder::append);
|
||||
|
||||
log(level, builder.toString());
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Help format a message for logging
|
||||
@@ -599,8 +641,9 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
* @param format The string format to use
|
||||
* @param args Arguments to use in the string format
|
||||
*/
|
||||
private void msgHelper(LogLevel level, String format, Object...args) {
|
||||
log(level, String.format(format, args));
|
||||
private void msgHelper(LogLevel level, String format, Object...args) {
|
||||
FormattingTuple tuple = MessageFormatter.arrayFormat(format, args);
|
||||
log(level, tuple.getMessage(), tuple.getThrowable());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -619,7 +662,7 @@ public class ApplicationLogger implements org.slf4j.Logger {
|
||||
* @param message the message to log
|
||||
* @return the formatted string
|
||||
*/
|
||||
private String format(String message, LogLevel level) {
|
||||
return String.format("th%06d [%-5s] [%s] %s", Thread.currentThread().getId(), level, this.name, message);
|
||||
}
|
||||
private String format(String message, LogLevel level) {
|
||||
return String.format("th%06d [%-5s] [%s] %s", Thread.currentThread().threadId(), level, this.name, message);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package net.locusworks.logger;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/***
|
||||
@@ -12,9 +12,9 @@ import java.util.stream.Collectors;
|
||||
* @date 02/15/2018
|
||||
*/
|
||||
public class ApplicationLoggerFactory {
|
||||
private static Map<String, ApplicationLogger> loggers = new TreeMap<>();
|
||||
private static LogLevel DEFAULT_LEVEL = LogLevel.ALL;
|
||||
private static ApplicationLoggerInitializer initializer;
|
||||
private static final Map<String, ApplicationLogger> loggers = new ConcurrentHashMap<>();
|
||||
private static volatile LogLevel defaultLevel = LogLevel.ALL;
|
||||
private static volatile ApplicationLoggerInitializer initializer;
|
||||
|
||||
/**
|
||||
* Need to get the log level from the properties file.
|
||||
@@ -24,7 +24,8 @@ public class ApplicationLoggerFactory {
|
||||
*/
|
||||
public static void init(ApplicationLoggerInitializer init) {
|
||||
initializer = init;
|
||||
DEFAULT_LEVEL = initializer == null ? LogLevel.INFO : initializer.initialize();
|
||||
LogLevel initializedLevel = initializer == null ? LogLevel.INFO : initializer.initialize();
|
||||
defaultLevel = initializedLevel == null ? LogLevel.INFO : initializedLevel;
|
||||
loadLoggers();
|
||||
}
|
||||
|
||||
@@ -60,7 +61,7 @@ public class ApplicationLoggerFactory {
|
||||
* @return
|
||||
*/
|
||||
private static LogLevel getDefaultLevel() {
|
||||
return DEFAULT_LEVEL;
|
||||
return defaultLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,10 +71,8 @@ public class ApplicationLoggerFactory {
|
||||
* @return the logger represented by the given name
|
||||
*/
|
||||
public static ApplicationLogger getLogger(String name, LogLevel level) {
|
||||
if (!loggers.containsKey(name)) {
|
||||
loggers.put(name, new ApplicationLogger(name, level));
|
||||
}
|
||||
ApplicationLogger logger = loggers.get(name);
|
||||
ApplicationLogger logger = loggers.computeIfAbsent(name,
|
||||
loggerName -> new ApplicationLogger(loggerName, level == null ? getDefaultLevel() : level));
|
||||
if (initializer != null) {
|
||||
initializer.postGetLogger(logger.getName(), logger.getLogLevel().toName());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package net.locusworks.logger;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/** Buffers redirected output so each complete UTF-8 line becomes one log event. */
|
||||
final class LineLoggingOutputStream extends OutputStream {
|
||||
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
private final Consumer<String> sink;
|
||||
|
||||
LineLoggingOutputStream(Consumer<String> sink) {
|
||||
this.sink = sink;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(int value) {
|
||||
if (value == '\n') {
|
||||
emit();
|
||||
} else {
|
||||
buffer.write(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void write(byte[] bytes, int offset, int length) {
|
||||
int end = offset + length;
|
||||
int start = offset;
|
||||
for (int index = offset; index < end; index++) {
|
||||
if (bytes[index] == '\n') {
|
||||
buffer.write(bytes, start, index - start);
|
||||
emit();
|
||||
start = index + 1;
|
||||
}
|
||||
}
|
||||
buffer.write(bytes, start, end - start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void flush() {
|
||||
if (buffer.size() > 0) emit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
flush();
|
||||
super.close();
|
||||
}
|
||||
|
||||
private void emit() {
|
||||
byte[] bytes = buffer.toByteArray();
|
||||
buffer.reset();
|
||||
int length = bytes.length;
|
||||
if (length > 0 && bytes[length - 1] == '\r') length--;
|
||||
sink.accept(new String(bytes, 0, length, UTF_8));
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,10 @@ public enum LogLevel {
|
||||
TRACE(1, "TRACE"),
|
||||
ALL(0, "ALL");
|
||||
|
||||
private Integer intLevel;
|
||||
private String levelName;
|
||||
private final int intLevel;
|
||||
private final String levelName;
|
||||
|
||||
private LogLevel(Integer intLevel, String levelName) {
|
||||
LogLevel(int intLevel, String levelName) {
|
||||
this.intLevel = intLevel;
|
||||
this.levelName = levelName;
|
||||
}
|
||||
@@ -41,7 +41,7 @@ public enum LogLevel {
|
||||
* Get the integer representation of the log level
|
||||
* @return intLevel
|
||||
*/
|
||||
public Integer toInt() {
|
||||
public int toInt() {
|
||||
return this.intLevel;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public enum LogLevel {
|
||||
*/
|
||||
public static LogLevel getEnum(Integer level) {
|
||||
for (LogLevel l : values()) {
|
||||
if (l.toInt().equals(level)) {
|
||||
if (level != null && l.toInt() == level) {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
@@ -77,6 +77,7 @@ public enum LogLevel {
|
||||
* @return the log level for the name or null if it cant be found
|
||||
*/
|
||||
public static LogLevel getEnum(String levelName) {
|
||||
if (levelName == null) return null;
|
||||
for (LogLevel l : values()) {
|
||||
if (l.toName().equalsIgnoreCase(levelName)) {
|
||||
return l;
|
||||
@@ -84,4 +85,4 @@ public enum LogLevel {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,15 @@
|
||||
package net.locusworks.logger;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
@ApplicationLoggerInfo(name="System.Debug", defaultLevel=LogLevel.DEBUG)
|
||||
public class SystemDebugLogger extends PrintStream {
|
||||
|
||||
private ApplicationLogger logger;
|
||||
|
||||
public SystemDebugLogger() {
|
||||
this(ApplicationLoggerFactory.getLogger(SystemDebugLogger.class));
|
||||
}
|
||||
|
||||
public SystemDebugLogger(ApplicationLogger logger) {
|
||||
super(new ByteArrayOutputStream());
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) {
|
||||
logger.debug(new String(b, UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) {
|
||||
logger.debug(new String(b, off, len, UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) {
|
||||
write(new byte[] { (byte)b });
|
||||
}
|
||||
}
|
||||
public SystemDebugLogger(ApplicationLogger logger) {
|
||||
super(new LineLoggingOutputStream(logger::debug), true);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,15 @@
|
||||
package net.locusworks.logger;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
@ApplicationLoggerInfo(name="System.Err", defaultLevel=LogLevel.ERROR)
|
||||
public class SystemErrLogger extends PrintStream {
|
||||
|
||||
private ApplicationLogger logger;
|
||||
|
||||
public SystemErrLogger() {
|
||||
this(ApplicationLoggerFactory.getLogger(SystemErrLogger.class));
|
||||
}
|
||||
|
||||
public SystemErrLogger(ApplicationLogger logger) {
|
||||
super(new ByteArrayOutputStream());
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) {
|
||||
logger.error(new String(b, UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) {
|
||||
logger.error(new String(b, off, len, UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) {
|
||||
write(new byte[] { (byte)b });
|
||||
}
|
||||
}
|
||||
public SystemErrLogger(ApplicationLogger logger) {
|
||||
super(new LineLoggingOutputStream(logger::error), true);
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,15 @@
|
||||
package net.locusworks.logger;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintStream;
|
||||
|
||||
@ApplicationLoggerInfo(name="System.Out", defaultLevel=LogLevel.OFF)
|
||||
public class SystemOutLogger extends PrintStream {
|
||||
|
||||
private ApplicationLogger logger;
|
||||
|
||||
public SystemOutLogger() {
|
||||
this(ApplicationLoggerFactory.getLogger(SystemOutLogger.class));
|
||||
}
|
||||
|
||||
public SystemOutLogger(ApplicationLogger logger) {
|
||||
super(new ByteArrayOutputStream());
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) {
|
||||
logger.info(new String(b, UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) {
|
||||
logger.info(new String(b, off, len, UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) {
|
||||
write(new byte[] { (byte)b });
|
||||
}
|
||||
}
|
||||
public SystemOutLogger(ApplicationLogger logger) {
|
||||
super(new LineLoggingOutputStream(logger::info), true);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Configuration status="WARN">
|
||||
<Appenders>
|
||||
<Console name="ConsoleAppender" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%d{dd-MMM-yyyy HH:mm:ss.SSS} %m%n" />
|
||||
</Console>
|
||||
<RollingFile name="application" fileName="application.log"
|
||||
filePattern="$${date:yyyy-MM}/${name}-%d{yyyy-MM-dd}-%i.log.gz">
|
||||
<PatternLayout>
|
||||
<pattern>%d{dd-MMM-yyyy HH:mm:ss.SSS} %m%n</pattern>
|
||||
</PatternLayout>
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy />
|
||||
<SizeBasedTriggeringPolicy size="10 MB" />
|
||||
</Policies>
|
||||
</RollingFile>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Root level="INFO">
|
||||
<AppenderRef ref="ConsoleAppender" />
|
||||
<AppenderRef ref="application" />
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
@@ -0,0 +1,101 @@
|
||||
package net.locusworks.logger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.contains;
|
||||
import static org.mockito.ArgumentMatchers.same;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.Marker;
|
||||
|
||||
class ApplicationLoggerDelegationTest {
|
||||
@Test
|
||||
void delegatesFormattingMarkersAndThrowablesAtEveryLevel() {
|
||||
Logger delegate = mock(Logger.class);
|
||||
Marker marker = mock(Marker.class);
|
||||
RuntimeException failure = new RuntimeException("boom");
|
||||
when(delegate.getName()).thenReturn("test");
|
||||
when(delegate.isTraceEnabled()).thenReturn(true);
|
||||
when(delegate.isDebugEnabled()).thenReturn(true);
|
||||
when(delegate.isInfoEnabled()).thenReturn(true);
|
||||
when(delegate.isWarnEnabled()).thenReturn(true);
|
||||
when(delegate.isErrorEnabled()).thenReturn(true);
|
||||
when(delegate.isTraceEnabled(marker)).thenReturn(true);
|
||||
when(delegate.isDebugEnabled(marker)).thenReturn(true);
|
||||
when(delegate.isInfoEnabled(marker)).thenReturn(true);
|
||||
when(delegate.isWarnEnabled(marker)).thenReturn(true);
|
||||
when(delegate.isErrorEnabled(marker)).thenReturn(true);
|
||||
|
||||
ApplicationLogger logger = new ApplicationLogger("test", LogLevel.ALL, delegate);
|
||||
assertEquals("test", logger.getName());
|
||||
assertTrue(logger.isTraceEnabled());
|
||||
assertTrue(logger.isDebugEnabled(marker));
|
||||
assertTrue(logger.isInfoEnabled());
|
||||
assertTrue(logger.isWarnEnabled(marker));
|
||||
assertTrue(logger.isErrorEnabled());
|
||||
|
||||
logger.trace("trace {}", 1);
|
||||
logger.trace("trace {} {}", 1, 2);
|
||||
logger.trace("trace {}", new Object[] {1});
|
||||
logger.trace("trace failure", failure);
|
||||
logger.debug("debug {}", 1);
|
||||
logger.debug("debug {} {}", 1, 2);
|
||||
logger.debug("debug {}", new Object[] {1});
|
||||
logger.debug("debug failure", failure);
|
||||
logger.info("info {}", 1);
|
||||
logger.info("info {} {}", 1, 2);
|
||||
logger.info("info {}", new Object[] {1});
|
||||
logger.info("info failure", failure);
|
||||
logger.warn("warn {}", 1);
|
||||
logger.warn("warn {} {}", 1, 2);
|
||||
logger.warn("warn {}", new Object[] {1});
|
||||
logger.warn("warn failure", failure);
|
||||
logger.error("error {}", 1);
|
||||
logger.error("error {} {}", 1, 2);
|
||||
logger.error("error {}", new Object[] {1});
|
||||
logger.error("error failure", failure);
|
||||
logger.error(failure);
|
||||
|
||||
logger.trace(marker, "trace {}", 1);
|
||||
logger.trace(marker, "trace {} {}", 1, 2);
|
||||
logger.trace(marker, "trace", new Object[0]);
|
||||
logger.trace(marker, "trace failure", failure);
|
||||
logger.debug(marker, "debug {}", 1);
|
||||
logger.debug(marker, "debug {} {}", 1, 2);
|
||||
logger.debug(marker, "debug", new Object[0]);
|
||||
logger.debug(marker, "debug failure", failure);
|
||||
logger.info(marker, "info {}", 1);
|
||||
logger.info(marker, "info {} {}", 1, 2);
|
||||
logger.info(marker, "info", new Object[0]);
|
||||
logger.info(marker, "info failure", failure);
|
||||
logger.warn(marker, "warn {}", 1);
|
||||
logger.warn(marker, "warn {} {}", 1, 2);
|
||||
logger.warn(marker, "warn", new Object[0]);
|
||||
logger.warn(marker, "warn failure", failure);
|
||||
logger.error(marker, "error {}", 1);
|
||||
logger.error(marker, "error {} {}", 1, 2);
|
||||
logger.error(marker, "error", new Object[0]);
|
||||
logger.error(marker, "error failure", failure);
|
||||
|
||||
Map<String, String> values = new LinkedHashMap<>();
|
||||
values.put("a", "one");
|
||||
values.put("long", "two");
|
||||
logger.info(values);
|
||||
logger.warn(values, new StringBuilder("prefix"));
|
||||
logger.error(values, "%s=%s", new StringBuilder(), failure);
|
||||
|
||||
verify(delegate, atLeastOnce()).info(contains("info 1"), org.mockito.ArgumentMatchers.isNull(Throwable.class));
|
||||
verify(delegate).error("error failure", failure);
|
||||
verify(delegate).error(marker, "error failure", failure);
|
||||
verify(delegate).error(contains("a=one"), same(failure));
|
||||
|
||||
logger.setLogLevel(LogLevel.OFF);
|
||||
assertEquals(LogLevel.OFF, logger.getLogLevel());
|
||||
assertFalse(logger.isErrorEnabled());
|
||||
logger.error("not logged");
|
||||
verify(delegate, never()).error(contains("not logged"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package net.locusworks.logger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.mockito.ArgumentMatchers.anyMap;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ApplicationLoggerFactoryTest {
|
||||
@ApplicationLoggerInfo(name = "annotated-name", defaultLevel = LogLevel.WARN)
|
||||
private static final class AnnotatedType { }
|
||||
|
||||
@Test
|
||||
void initializesLoadsConfiguresAndSavesLoggers() {
|
||||
ApplicationLoggerInitializer initializer = mock(ApplicationLoggerInitializer.class);
|
||||
when(initializer.initialize()).thenReturn(LogLevel.DEBUG);
|
||||
ApplicationLoggerFactory.init(initializer);
|
||||
verify(initializer).loadLoggers();
|
||||
|
||||
ApplicationLogger annotated = ApplicationLoggerFactory.getLogger(AnnotatedType.class);
|
||||
assertEquals("annotated-name", annotated.getName());
|
||||
assertEquals(LogLevel.WARN, annotated.getLogLevel());
|
||||
verify(initializer).postGetLogger("annotated-name", "WARN");
|
||||
|
||||
ApplicationLoggerFactory.setLogLevels(List.of(new ApplicationLoggerFactory.LoggerInfo("annotated-name", "ERROR")));
|
||||
assertEquals(LogLevel.ERROR, annotated.getLogLevel());
|
||||
ApplicationLogger added = new ApplicationLogger("added-test", LogLevel.INFO);
|
||||
ApplicationLoggerFactory.addLogger(added);
|
||||
assertSame(added, ApplicationLoggerFactory.getLogger("added-test"));
|
||||
ApplicationLoggerFactory.addLoggers(List.of(new ApplicationLoggerFactory.LoggerInfo("list-test", "TRACE")));
|
||||
assertEquals(LogLevel.TRACE, ApplicationLoggerFactory.getLogger("list-test").getLogLevel());
|
||||
|
||||
ApplicationLoggerFactory.saveLogLevels();
|
||||
verify(initializer).saveLogLevels(anyMap());
|
||||
ApplicationLoggerFactory.loadLoggers(null);
|
||||
ApplicationLoggerFactory.saveLogLevels(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
void loggerInfoSupportsBeanAccess() {
|
||||
ApplicationLoggerFactory.LoggerInfo info = new ApplicationLoggerFactory.LoggerInfo();
|
||||
info.setLogger("logger");
|
||||
info.setLevel("INFO");
|
||||
assertEquals("logger", info.getLogger());
|
||||
assertEquals("INFO", info.getLevel());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package net.locusworks.logger;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ApplicationLoggerTest {
|
||||
@Test
|
||||
void filtersMessagesBelowConfiguredLevel() {
|
||||
ApplicationLogger logger = new ApplicationLogger("level-test", LogLevel.INFO);
|
||||
assertTrue(logger.isInfoEnabled());
|
||||
assertFalse(logger.isDebugEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void factoryReturnsOneInstanceUnderConcurrency() {
|
||||
List<ApplicationLogger> results = IntStream.range(0, 100).parallel()
|
||||
.mapToObj(i -> ApplicationLoggerFactory.getLogger("concurrent-test"))
|
||||
.toList();
|
||||
results.forEach(logger -> assertSame(results.get(0), logger));
|
||||
}
|
||||
|
||||
@Test
|
||||
void supportsSlf4jFormattingAndPreservesThrowable() throws Exception {
|
||||
PrintStream original = System.err;
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
try (PrintStream capture = new PrintStream(output, true, UTF_8)) {
|
||||
System.setErr(capture);
|
||||
ApplicationLogger logger = new ApplicationLogger("format-test", LogLevel.INFO);
|
||||
IllegalStateException failure = new IllegalStateException("failure-detail");
|
||||
logger.info("Hello {}", "world");
|
||||
logger.error("Operation failed", failure);
|
||||
} finally {
|
||||
System.setErr(original);
|
||||
}
|
||||
String logged = output.toString(UTF_8);
|
||||
assertTrue(logged.contains("Hello world"));
|
||||
assertTrue(logged.contains("IllegalStateException: failure-detail"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void systemStreamBuffersUtf8ByLine() {
|
||||
CapturingLogger logger = new CapturingLogger();
|
||||
try (PrintStream stream = new SystemOutLogger(logger)) {
|
||||
byte[] text = "héllo\nsecond\n".getBytes(UTF_8);
|
||||
for (byte value : text) stream.write(value);
|
||||
}
|
||||
assertEquals(List.of("héllo", "second"), logger.messages);
|
||||
}
|
||||
|
||||
private static final class CapturingLogger extends ApplicationLogger {
|
||||
private final List<String> messages = new ArrayList<>();
|
||||
private CapturingLogger() { super("capture", LogLevel.ALL); }
|
||||
@Override public void info(String message) { messages.add(message); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package net.locusworks.logger;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class LogLevelTest {
|
||||
@Test
|
||||
void convertsNamesAndNumbers() {
|
||||
for (LogLevel level : LogLevel.values()) {
|
||||
assertEquals(level, LogLevel.getEnum(level.toInt()));
|
||||
assertEquals(level, LogLevel.getEnum(level.toName().toLowerCase()));
|
||||
assertEquals(level.toName(), level.toString());
|
||||
}
|
||||
assertNull(LogLevel.getEnum(99));
|
||||
assertNull(LogLevel.getEnum((Integer) null));
|
||||
assertNull(LogLevel.getEnum("unknown"));
|
||||
assertNull(LogLevel.getEnum((String) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void comparesSeverityAndHandlesNull() {
|
||||
assertTrue(LogLevel.INFO.log(LogLevel.DEBUG));
|
||||
assertFalse(LogLevel.DEBUG.log(LogLevel.INFO));
|
||||
assertFalse(LogLevel.INFO.log(null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package net.locusworks.logger;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class SystemLoggerTest {
|
||||
@Test
|
||||
void routesCompleteLinesToTheirConfiguredLevels() {
|
||||
ApplicationLogger logger = mock(ApplicationLogger.class);
|
||||
try (PrintStream out = new SystemOutLogger(logger);
|
||||
PrintStream err = new SystemErrLogger(logger);
|
||||
PrintStream debug = new SystemDebugLogger(logger)) {
|
||||
out.print("out\r\n");
|
||||
err.print("err\n");
|
||||
debug.print("debug");
|
||||
debug.flush();
|
||||
}
|
||||
verify(logger).info("out");
|
||||
verify(logger).error("err");
|
||||
verify(logger).debug("debug");
|
||||
}
|
||||
|
||||
@Test
|
||||
void preservesUtf8SplitAcrossIndividualWrites() {
|
||||
ApplicationLogger logger = mock(ApplicationLogger.class);
|
||||
try (PrintStream out = new SystemOutLogger(logger)) {
|
||||
for (byte value : "h\u00e9llo\n".getBytes(UTF_8)) out.write(value);
|
||||
}
|
||||
verify(logger).info("h\u00e9llo");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user