diff --git a/CHANGELOG.md b/CHANGELOG.md index 95a40de..42a0ab3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,4 +54,23 @@ * Refactored and simplified PatternResolver and Element code using java functions * Raised test coverage * Allow easy overwriting of existing patterns with custom elements -* Upgrade to latest versions \ No newline at end of file +* Upgrade to latest versions + +### 1.6.1 + +(2023-11-10) + +* Headers case insensitive +* Upgrade to latest versions + +### 1.7.0 + +(2024-01-13) + +* Native handling of values +* All Log Elements return now native objects if possible +* String based Appenders have to stringify themselves +* Appenders that understand native objects benefit from this change +* **BREAKING CHANGE**: `Appender.push` signature changed and simplified - only relevant if you have a custom Appender +* Upgrade to Vert.x 4.5.1 -> Ready for Virtual Threads +* Automatic injection of `timestamp` for `ElasticSearchAppender` - no need anymore to define it artifically in logPattern diff --git a/ES_README.md b/ES_README.md index ea77687..ccb2c17 100644 --- a/ES_README.md +++ b/ES_README.md @@ -8,13 +8,12 @@ As configuration is now done by plain JsonObject its very simple to use and inje ```yaml configurations: - identifier: accesslog-plain - logPattern: "%{msec}t %D cs-uri" + logPattern: "%D cs-uri" appenders: - - appenderClassName : com.mdac.vertx.web.accesslogger.appender.elasticsearch.impl.ElasticSearchAppender + - appenderClassName : com.romanpierson.vertx.web.accesslogger.appender.elasticsearch.impl.ElasticSearchAppender config: instanceIdentifier: accesslog fieldNames: - - timestamp - duration - uri ``` @@ -22,10 +21,15 @@ configurations: ## Conventions By default all log elements configured will be sent to the indexer to be interpreted as message to be indexed. However the timestamp is passed to the indexer as meta data as the indexer potentially requires that raw value eg to determinate the target index name. -By default you should put as first element plain timestamp %{msec} and the appender will remove that element from the message sent to the indexer. The instance identifier tells the indexer verticle to what ES instance the data should be indexed. All the detailed configuration of this is done directly on the indexer verticle itself (so the appender does not have to know about this). +## Timestamp + +The timestamp value is automatically added - there is no need to add this on the logPattern. + +The real fieldname used in the indexer for the ES timestamp field is configured in the indexer verticle itself. + ## Field Names Definition -As for each field to be indexed a specific name needs to be used this has to be explicitly set by configuration property `fieldNames`. Be aware that you need to put a name for all fields of your logpattern even for eg the timestamp one that is actually skipped at the end. The real fieldname used in the indexer for the ES timestamp field is configured in the indexer verticle itself. +As for each field to be indexed a specific name needs to be used this has to be explicitly set by configuration property `fieldNames`. Be aware that you need to put a name for all fields of your logpattern. diff --git a/LICENSE.txt b/LICENSE.txt index 8314556..bf99f76 100755 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -187,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2016-2023 Roman Pierson + Copyright 2016-2024 Roman Pierson Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index f1332f3..3b1ecbe 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Just add it as a dependency to your project (gradle example) ```xml dependencies { - compile 'com.romanpierson:vertx-web-accesslog:1.6.0' + compile 'com.romanpierson:vertx-web-accesslog:1.7.0' } ``` @@ -41,6 +41,7 @@ dependencies { Accesslog version | Vertx version ----|------ 5.0.0-SNAPSHOT | 5.0.0-SNAPSHOT > +1.7.0 | 4.5.1 > 1.6.0 | 4.3.0 > 1.5.0 | 4.2.0 > 1.4.0 | 4.0.0 - 4.1.x diff --git a/build.gradle b/build.gradle index 7d949e9..6d9027e 100755 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ plugins { id 'java' id 'maven-publish' id 'jacoco' - id "org.sonarqube" version "4.0.0.2929" + id "org.sonarqube" version "4.4.1.3373" } repositories { @@ -14,8 +14,8 @@ repositories { ext{ vertxVersion = '5.0.0-SNAPSHOT' - jupiterVersion = '5.10.0' - jupiterLauncherVersion = '1.10.0' + jupiterVersion = '5.10.1' + jupiterLauncherVersion = '1.10.1' slfApiVersion = '2.0.9' logbackVersion = '1.4.11' } @@ -42,8 +42,10 @@ test { finalizedBy jacocoTestReport } -sourceCompatibility='1.8' -targetCompatibility='1.8' +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} jar.archiveFileName = "vertx-web-accesslog-5.0.0-SNAPSHOT.jar" @@ -55,7 +57,7 @@ publishing { publications { mavenJava(MavenPublication) { - groupId 'com.mdac' + groupId 'com.romanpierson' artifactId 'vertx-web-accesslog' version '5.0.0-SNAPSHOT' @@ -82,6 +84,6 @@ jacocoTestReport { } wrapper() { - gradleVersion = '8.0.2' + gradleVersion = '8.5' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e1bef7e..a595206 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-8.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0..1b6c787 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/AccessLoggerConstants.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/AccessLoggerConstants.java index 2ee89a7..273244c 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/AccessLoggerConstants.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/AccessLoggerConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -34,6 +34,14 @@ private HandlerConfiguration() {} public static final String CONFIG_KEY_IS_AUTO_DEPLOY_PRODUCER_VERTICLE = "isAutoDeployProducerVerticle"; } + public static class InternalValues { + + private InternalValues() {} + + public static final String TIMESTAMP = "timestamp"; + + } + public static class Messages { private Messages() {} diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/AccessLoggerHandler.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/AccessLoggerHandler.java index 1b38529..e356399 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/AccessLoggerHandler.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/AccessLoggerHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/Appender.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/Appender.java index 7a44af0..5c47f94 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/Appender.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/Appender.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -12,7 +12,8 @@ */ package com.romanpierson.vertx.web.accesslogger.appender; -import io.vertx.core.json.JsonArray; +import java.util.List; +import java.util.Map; /** * @@ -25,13 +26,16 @@ public interface Appender { /** * - * Push the access events to the appender. + * Push the access element values to the appender. + * + * Those values can contain native data types and null values * * Its the appenders responsibility to implement local storage * - * @param accessEvent List of access events the appender should handle - those are no copies + * @param rawAccessElementValues List of access events the appender should handle - those are no copies + * @param internalValues A list of internal values that are sent independent from the configured access log elements */ - void push(JsonArray accessEvent); + void push(List rawAccessElementValues, Map internalValues); /** diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/console/impl/ConsoleAppender.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/console/impl/ConsoleAppender.java index abcd4a5..ce84658 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/console/impl/ConsoleAppender.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/console/impl/ConsoleAppender.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -12,12 +12,16 @@ */ package com.romanpierson.vertx.web.accesslogger.appender.console.impl; +import static com.romanpierson.vertx.web.accesslogger.util.FormatUtility.getStringifiedParameterValues; + +import java.util.List; +import java.util.Map; + import com.romanpierson.vertx.web.accesslogger.AccessLoggerConstants; import com.romanpierson.vertx.web.accesslogger.appender.Appender; import io.vertx.core.impl.logging.Logger; import io.vertx.core.impl.logging.LoggerFactory; -import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; /** @@ -46,28 +50,12 @@ public ConsoleAppender(final JsonObject config){ } @Override - public void push(JsonArray accessEvent) { + public void push(List rawAccessElementValues, Map internalValues) { - Object [] parameterValues = getParameterValues(accessEvent); - - final String formattedString = String.format(this.resolvedPattern, parameterValues); + final String formattedString = String.format(this.resolvedPattern, getStringifiedParameterValues(rawAccessElementValues)); System.out.println(formattedString); } - - private Object[] getParameterValues(final JsonArray values){ - - final String[] parameterValues = new String[values.size()]; - - int i = 0; - for (final Object xValue : values.getList()) { - parameterValues[i] = (String) xValue; - i++; - } - - return parameterValues; - - } } diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/elasticsearch/impl/ElasticSearchAppender.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/elasticsearch/impl/ElasticSearchAppender.java index 96793b2..f47285c 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/elasticsearch/impl/ElasticSearchAppender.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/elasticsearch/impl/ElasticSearchAppender.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -13,7 +13,10 @@ package com.romanpierson.vertx.web.accesslogger.appender.elasticsearch.impl; import java.util.Collection; +import java.util.List; +import java.util.Map; +import com.romanpierson.vertx.web.accesslogger.AccessLoggerConstants; import com.romanpierson.vertx.web.accesslogger.AccessLoggerConstants.ElasticSearchAppenderConfig; import com.romanpierson.vertx.web.accesslogger.AccessLoggerConstants.ElasticSearchAppenderConfig.Field; import com.romanpierson.vertx.web.accesslogger.appender.Appender; @@ -39,12 +42,10 @@ public class ElasticSearchAppender implements Appender { private final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); private static final String CONFIG_KEY_INSTANCE_IDENTIFER = "instanceIdentifier"; - private static final String CONFIG_KEY_TIMESTAMP_POSITION = "timestampPosition"; private static final String CONFIG_KEY_FIELD_NAMES = "fieldNames"; private final EventBus vertxEventBus; - private final int timestampPosition; private final String instanceIdentifier; private final Collection fieldNames; @@ -59,54 +60,55 @@ public ElasticSearchAppender(final JsonObject config){ this.vertxEventBus = Vertx.currentContext().owner().eventBus(); - this.timestampPosition = config.getInteger(CONFIG_KEY_TIMESTAMP_POSITION, 0); this.instanceIdentifier = config.getString(CONFIG_KEY_INSTANCE_IDENTIFER); this.fieldNames = config.getJsonArray(CONFIG_KEY_FIELD_NAMES).getList(); - logger.info("Created ElasticSearchAppender with " + CONFIG_KEY_INSTANCE_IDENTIFER + " [" + this.instanceIdentifier + "], " + CONFIG_KEY_TIMESTAMP_POSITION + " [" + this.timestampPosition + "], " + CONFIG_KEY_FIELD_NAMES + " " +this.fieldNames); + logger.info("Created ElasticSearchAppender with " + CONFIG_KEY_INSTANCE_IDENTIFER + " [" + this.instanceIdentifier + "], " + CONFIG_KEY_FIELD_NAMES + " " +this.fieldNames); } - private String[] getParameterValues(final JsonArray values){ + private Object[] getParameterValuesCopy(List rawAccessElementValues){ - final String[] parameterValues = new String[values.size()]; + final Object[] parameterValues = new Object[rawAccessElementValues.size()]; int i = 0; - for (final Object xValue : values.getList()) { - parameterValues[i] = (String) xValue; + for (final Object xValue : rawAccessElementValues) { + parameterValues[i] = xValue; i++; } return parameterValues; } - + @Override - public void push(final JsonArray accessEvent) { + public void push(final List rawAccessElementValues, Map internalValues) { - final long metaTimestamp = this.timestampPosition < 0 ? System.currentTimeMillis() : Long.parseLong(accessEvent.getString(this.timestampPosition)); - - // Just send the accesslog event to the indexer - JsonObject jsonMeta = new JsonObject(); - jsonMeta.put(Field.TIMESTAMP, metaTimestamp); - jsonMeta.put(Field.INSTANCE_IDENTIFIER, this.instanceIdentifier); + // Just send the accesslog event to the indexer + JsonObject jsonMeta = new JsonObject(); + jsonMeta.put(Field.TIMESTAMP, (Long) internalValues.get(AccessLoggerConstants.InternalValues.TIMESTAMP)); + jsonMeta.put(Field.INSTANCE_IDENTIFIER, this.instanceIdentifier); - JsonObject jsonMessage = new JsonObject(); + JsonObject jsonMessage = new JsonObject(); - String [] parameterValues = getParameterValues(accessEvent); + // TODO do we really need a copy? + Object [] nativeParameterValues = getParameterValuesCopy(rawAccessElementValues); - int i = 0; - for(String fieldName : fieldNames) { - if(this.timestampPosition != i) { - jsonMessage.put(fieldName, parameterValues[i]); - } - i++; + int i = 0; + for(String fieldName : fieldNames) { + + if(nativeParameterValues[i] != null){ + // Values having no value we dont send either + jsonMessage.put(fieldName, nativeParameterValues[i]); } + + i++; + } - JsonObject json = new JsonObject() + JsonObject json = new JsonObject() .put(Field.META, jsonMeta) .put(Field.MESSAGE, jsonMessage); - this.vertxEventBus.send(ElasticSearchAppenderConfig.ELASTICSEARCH_INDEXER_EVENTBUS_EVENT_NAME, json); + this.vertxEventBus.send(ElasticSearchAppenderConfig.ELASTICSEARCH_INDEXER_EVENTBUS_EVENT_NAME, json); } diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/eventbus/impl/EventBusAppender.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/eventbus/impl/EventBusAppender.java index ac57f80..49ef57a 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/eventbus/impl/EventBusAppender.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/eventbus/impl/EventBusAppender.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -12,6 +12,9 @@ */ package com.romanpierson.vertx.web.accesslogger.appender.eventbus.impl; +import java.util.List; +import java.util.Map; + import com.romanpierson.vertx.web.accesslogger.appender.Appender; import io.vertx.core.Vertx; @@ -52,10 +55,21 @@ public EventBusAppender(final JsonObject config){ } @Override - public void push(final JsonArray accessEvent) { + public void push(final List rawAccessElementValues, Map internalValues) { + + // TODO should we make a copy? + + vertxEventBus.send(this.eventBusTargetAddress, convertToJsonArray(rawAccessElementValues)); + + } + + private JsonArray convertToJsonArray(List rawAccessElementValues){ + + JsonArray s = new JsonArray(); - vertxEventBus.send(this.eventBusTargetAddress, accessEvent); + rawAccessElementValues.forEach(x -> s.add(x)); + return s; } } diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/logging/impl/LoggingAppender.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/logging/impl/LoggingAppender.java index 70c52eb..68122b4 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/logging/impl/LoggingAppender.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/appender/logging/impl/LoggingAppender.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -18,9 +18,13 @@ import io.vertx.core.impl.logging.Logger; import io.vertx.core.impl.logging.LoggerFactory; -import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; +import static com.romanpierson.vertx.web.accesslogger.util.FormatUtility.getStringifiedParameterValues; + +import java.util.List; +import java.util.Map; + /** * * An implementation of {@link Appender} that writes to standard log @@ -50,28 +54,13 @@ public LoggingAppender(final JsonObject config) { } @Override - public void push(JsonArray accessEvent) { - - Object[] parameterValues = getParameterValues(accessEvent); + public void push(List rawAccessElementValues, Map internalValues) { - final String formattedString = String.format(this.resolvedPattern, parameterValues); + final String formattedString = String.format(this.resolvedPattern, getStringifiedParameterValues(rawAccessElementValues)); this.logger.info(formattedString); } - private Object[] getParameterValues(final JsonArray values) { - - final String[] parameterValues = new String[values.size()]; - - int i = 0; - for (final Object xValue : values.getList()) { - parameterValues[i] = (String) xValue; - i++; - } - - return parameterValues; - - } } diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/AccessLogElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/AccessLogElement.java index 5cf13be..151163d 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/AccessLogElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/AccessLogElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -65,9 +65,7 @@ default Collection claimDataParts(){ } - String getFormattedValue(JsonObject values); - - + Object getNativeValue(JsonObject values); } diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/BytesSentElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/BytesSentElement.java index cf580be..075ffbd 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/BytesSentElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/BytesSentElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -56,14 +56,14 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { - + public Object getNativeValue(final JsonObject values) { + final long bytes = values.getLong(Data.Type.BYTES_SENT.getFieldName(), DEFAULT_VALUE); if(bytes > 0) { - return Long.toString(bytes); + return Long.valueOf(bytes); } else { - return Mode.NO_BYTES_DASH.equals(this.mode) ? "-" : "0"; + return Mode.NO_BYTES_DASH.equals(this.mode) ? "-" : Long.valueOf(0); } } diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/CookieElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/CookieElement.java index c2afabf..354efdf 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/CookieElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/CookieElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -50,7 +50,7 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { if(!values.containsKey(Data.Type.COOKIES.getFieldName())){ return null; diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/DateTimeElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/DateTimeElement.java index 882c97e..2fc6b5c 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/DateTimeElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/DateTimeElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -98,10 +98,10 @@ else if(configurationTokens != null){ } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { if(this.dateFormat == null) { - return values.getLong(Data.Type.START_TS_MILLIS.getFieldName()).toString(); + return values.getLong(Data.Type.START_TS_MILLIS.getFieldName()); } else { return this.dateFormat.format(values.getLong(Data.Type.START_TS_MILLIS.getFieldName())); } diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/DurationElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/DurationElement.java index 550a13e..8d6a026 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/DurationElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/DurationElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -54,7 +54,7 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { final Long startTS = values.getLong(Data.Type.START_TS_MILLIS.getFieldName()); final Long endTS = values.getLong(Data.Type.END_TS_MILLIS.getFieldName()); @@ -65,7 +65,8 @@ public String getFormattedValue(final JsonObject values) { duration = duration / 1000; } - return duration > 0 ? Long.toString(duration) : "0"; + return duration > 0 ? duration : Long.valueOf(0); } + } diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/EnvironmentValueElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/EnvironmentValueElement.java index 51b27ee..9b391ae 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/EnvironmentValueElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/EnvironmentValueElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -48,7 +48,7 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { return this.value; diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/HeaderElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/HeaderElement.java index 638f724..d0968bf 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/HeaderElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/HeaderElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -61,7 +61,7 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { final JsonObject headers = Mode.INCOMING.equals(this.mode) ? values.getJsonObject(Data.Type.REQUEST_HEADERS.getFieldName()) : values.getJsonObject(Data.Type.RESPONSE_HEADERS.getFieldName()); diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/HostElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/HostElement.java index a92f545..2333cee 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/HostElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/HostElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -62,7 +62,7 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { switch (this.mode){ diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/MethodElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/MethodElement.java index 0ede535..5e48f5a 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/MethodElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/MethodElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -40,7 +40,7 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { return FormatUtility.getStringOrNull(values, Data.Type.METHOD.getFieldName()); diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/RequestElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/RequestElement.java index 49c6e83..9203300 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/RequestElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/RequestElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -61,7 +61,7 @@ public Collection findInRawPatternInternal(final String rawPa @Override - public String getFormattedValue(JsonObject values) { + public Object getNativeValue(JsonObject values) { final StringBuilder sb = new StringBuilder(); diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/StaticValueElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/StaticValueElement.java index 5aea77f..2164c9c 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/StaticValueElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/StaticValueElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -47,7 +47,7 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { return this.value; diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/StatusElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/StatusElement.java index 27e6327..4148e15 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/StatusElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/StatusElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -38,9 +38,9 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { - return Integer.toString(values.getInteger(Data.Type.STATUS.getFieldName())); + return values.getInteger(Data.Type.STATUS.getFieldName()); } diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/VersionElement.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/VersionElement.java index 67313cc..1063eb6 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/VersionElement.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/VersionElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -36,7 +36,7 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { return VersionUtility.getFormattedValue(values); diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/ExtractedPosition.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/ExtractedPosition.java index 0c79da9..f195133 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/ExtractedPosition.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/ExtractedPosition.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/PatternResolver.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/PatternResolver.java index 9a45132..bb0383f 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/PatternResolver.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/PatternResolver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/ResolvedPatternResult.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/ResolvedPatternResult.java index 7e8a22c..43ce950 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/ResolvedPatternResult.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/ResolvedPatternResult.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/exception/AccessLoggerException.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/exception/AccessLoggerException.java index 12db505..d49b345 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/exception/AccessLoggerException.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/exception/AccessLoggerException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/impl/AccessLoggerHandlerImpl.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/impl/AccessLoggerHandlerImpl.java index 853b346..e889394 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/impl/AccessLoggerHandlerImpl.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/impl/AccessLoggerHandlerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -90,6 +90,7 @@ public AccessLoggerHandlerImpl(final JsonObject handlerConfiguration) { } }); + } } } diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/util/FormatUtility.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/util/FormatUtility.java index 43e9fbf..405ad00 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/util/FormatUtility.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/util/FormatUtility.java @@ -1,10 +1,28 @@ +/* + * Copyright (c) 2016-2024 Roman Pierson + * ------------------------------------------------------ + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License v2.0 + * which accompanies this distribution. + * + * The Apache License v2.0 is available at + * http://www.opensource.org/licenses/apache2.0.php + * + * You may elect to redistribute this code under either of these licenses. + */ package com.romanpierson.vertx.web.accesslogger.util; - import io.vertx.core.json.JsonObject; +import java.util.List; + +import io.vertx.core.impl.logging.Logger; +import io.vertx.core.impl.logging.LoggerFactory; + public class FormatUtility { - + + private final static Logger logger = LoggerFactory.getLogger(FormatUtility.class.getName()); + private FormatUtility() {} public static String getStringOrNull(final JsonObject values, final String fieldName) { @@ -19,5 +37,31 @@ public static String getIntegerOrNull(final JsonObject values, final String fiel } - + public static Object[] getStringifiedParameterValues(final List rawValues){ + + final String[] parameterValues = new String[rawValues.size()]; + + int i = 0; + for (final Object xValue : rawValues) { + + if(xValue == null){ + parameterValues[i] = ""; + } + else if (xValue instanceof Long) { + parameterValues[i] = Long.toString((Long) xValue); + } else if (xValue instanceof Integer) { + parameterValues[i] = Integer.toString((Integer) xValue); + }else if (xValue instanceof String) { + parameterValues[i] = (String) xValue; + } else { + logger.error("Unrecognized type" + xValue.getClass()); + } + + i++; + } + + return parameterValues; + + } + } diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/util/VersionUtility.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/util/VersionUtility.java index 8f1b07f..9435a3f 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/util/VersionUtility.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/util/VersionUtility.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/verticle/AccessLoggerProducerVerticle.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/verticle/AccessLoggerProducerVerticle.java index e547013..0af0645 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/verticle/AccessLoggerProducerVerticle.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/verticle/AccessLoggerProducerVerticle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -12,9 +12,11 @@ */ package com.romanpierson.vertx.web.accesslogger.verticle; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; @@ -59,17 +61,18 @@ public void start() throws Exception { vertx.eventBus().consumer(AccessLoggerConstants.EVENTBUS_RAW_EVENT_NAME, event -> { - JsonArray identifiers = event.body().getJsonArray(RawEvent.Request.IDENTIFIERS); - + JsonObject eventBody = event.body(); + JsonArray identifiers = eventBody.getJsonArray(RawEvent.Request.IDENTIFIERS); + for (Object x : identifiers.getList()) { String identifier = (String) x; if (resolvedLoggerConfigurations.containsKey(identifier)) { - JsonArray formatted = getFormattedValues( - resolvedLoggerConfigurations.get(identifier).getResolvedLogElements(), event.body()); - + List nativeValues = getNativeValues(resolvedLoggerConfigurations.get(identifier).getResolvedLogElements(), event.body()); + Map internalValues = getInternalValues(eventBody); + for (Appender appender : resolvedLoggerConfigurations.get(identifier).getRawAppender()) { - appender.push(formatted); + appender.push(nativeValues, internalValues); } } } @@ -83,6 +86,12 @@ public void start() throws Exception { ); } + + private Map getInternalValues(final JsonObject eventBody){ + + return Map.of(AccessLoggerConstants.InternalValues.TIMESTAMP, eventBody.getLong(Data.Type.START_TS_MILLIS.getFieldName())); + + } @SuppressWarnings({ "rawtypes", "unchecked" }) private synchronized JsonObject performRegistration(final JsonObject request) { @@ -170,16 +179,16 @@ private void populateResponse(final JsonObject response, final ResolvedLoggerCon } - private JsonArray getFormattedValues(final Collection logElements, final JsonObject rawValue) { - - JsonArray value = new JsonArray(); + + private List getNativeValues(final Collection logElements, final JsonObject rawValue) { + + List values = new ArrayList<>(logElements.size()); for (final AccessLogElement alElement : logElements) { - final String formattedValue = alElement.getFormattedValue(rawValue); - value.add(formattedValue != null ? formattedValue : ""); + values.add(alElement.getNativeValue(rawValue)); } - - return value; + + return values; } diff --git a/src/main/java/com/romanpierson/vertx/web/accesslogger/verticle/ResolvedLoggerConfiguration.java b/src/main/java/com/romanpierson/vertx/web/accesslogger/verticle/ResolvedLoggerConfiguration.java index adad07e..3318061 100644 --- a/src/main/java/com/romanpierson/vertx/web/accesslogger/verticle/ResolvedLoggerConfiguration.java +++ b/src/main/java/com/romanpierson/vertx/web/accesslogger/verticle/ResolvedLoggerConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 diff --git a/src/test/java/com/romanpierson/custom/element/ShouldNotShowElement.java b/src/test/java/com/romanpierson/custom/element/ShouldNotShowElement.java index 3ba2c8a..afae869 100644 --- a/src/test/java/com/romanpierson/custom/element/ShouldNotShowElement.java +++ b/src/test/java/com/romanpierson/custom/element/ShouldNotShowElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -36,7 +36,7 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { return "shouldNotShow"; diff --git a/src/test/java/com/romanpierson/custom/element/ShouldShowElement.java b/src/test/java/com/romanpierson/custom/element/ShouldShowElement.java index be2a29e..f1534b6 100644 --- a/src/test/java/com/romanpierson/custom/element/ShouldShowElement.java +++ b/src/test/java/com/romanpierson/custom/element/ShouldShowElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -36,7 +36,7 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { return "shouldShow"; diff --git a/src/test/java/com/romanpierson/vertx/web/accesslogger/ElasticSearchAppenderTest.java b/src/test/java/com/romanpierson/vertx/web/accesslogger/ElasticSearchAppenderTest.java index 51cc1b6..7bffa2c 100644 --- a/src/test/java/com/romanpierson/vertx/web/accesslogger/ElasticSearchAppenderTest.java +++ b/src/test/java/com/romanpierson/vertx/web/accesslogger/ElasticSearchAppenderTest.java @@ -19,7 +19,7 @@ import io.vertx.core.http.HttpClient; import io.vertx.core.http.HttpClientResponse; import io.vertx.core.http.HttpMethod; -import io.vertx.core.json.JsonArray; +import io.vertx.core.json.JsonObject; import io.vertx.junit5.VertxExtension; import io.vertx.junit5.VertxTestContext; @@ -76,11 +76,22 @@ void testValid(Vertx vertx, VertxTestContext testContext) { testContext.failNow(throwable); }); - vertx.eventBus().consumer(ElasticSearchAppenderConfig.ELASTICSEARCH_INDEXER_EVENTBUS_EVENT_NAME, message -> { - //assertEquals(1, message.body().size()); - //assertEquals("/test", message.body().getString(0)); - System.out.println(message.body()); - // TODO verify content + vertx.eventBus().consumer(ElasticSearchAppenderConfig.ELASTICSEARCH_INDEXER_EVENTBUS_EVENT_NAME, message -> { + + // Verify the meta data + JsonObject logEntry = message.body(); + + // Verify the meta section + JsonObject metaEntry = logEntry.getJsonObject("meta"); + assertEquals("esInstance", metaEntry.getString("instance_identifier")); + assertTrue(metaEntry.getLong("timestamp").longValue() > 0); + + + // Verify the data section + JsonObject messageEntry = logEntry.getJsonObject("message"); + assertEquals("/test", messageEntry.getString("uri")); + assertTrue(messageEntry.getLong("duration").longValue() >= 0); + testContext.completeNow(); }); diff --git a/src/test/java/com/romanpierson/vertx/web/accesslogger/appender/MemoryAppender.java b/src/test/java/com/romanpierson/vertx/web/accesslogger/appender/MemoryAppender.java index 05b035f..1467e35 100644 --- a/src/test/java/com/romanpierson/vertx/web/accesslogger/appender/MemoryAppender.java +++ b/src/test/java/com/romanpierson/vertx/web/accesslogger/appender/MemoryAppender.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -12,13 +12,17 @@ */ package com.romanpierson.vertx.web.accesslogger.appender; +import java.util.List; +import java.util.Map; + import com.romanpierson.vertx.web.accesslogger.AccessLoggerConstants; import io.vertx.core.impl.logging.Logger; import io.vertx.core.impl.logging.LoggerFactory; -import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; +import static com.romanpierson.vertx.web.accesslogger.util.FormatUtility.getStringifiedParameterValues; + /** * * An implementation of {@link Appender} that writes to System.out @@ -45,28 +49,13 @@ public MemoryAppender(final JsonObject config){ } @Override - public void push(JsonArray accessEvent) { - - Object [] parameterValues = getParameterValues(accessEvent); + public void push(List rawAccessElementValues, Map internalValues) { - final String formattedString = String.format(this.resolvedPattern, parameterValues); + final String formattedString = String.format(this.resolvedPattern, getStringifiedParameterValues(rawAccessElementValues)); System.out.println(formattedString); } - private Object[] getParameterValues(final JsonArray values){ - - final String[] parameterValues = new String[values.size()]; - - int i = 0; - for (final Object xValue : values.getList()) { - parameterValues[i] = (String) xValue; - i++; - } - - return parameterValues; - - } } diff --git a/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/InvalidElement.java b/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/InvalidElement.java index 863b829..e6b00f5 100644 --- a/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/InvalidElement.java +++ b/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/InvalidElement.java @@ -21,7 +21,7 @@ public Collection findInRawPatternInternal(String rawPattern) } @Override - public String getFormattedValue(JsonObject values) { + public Object getNativeValue(JsonObject values) { return null; diff --git a/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/InvalidElement2.java b/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/InvalidElement2.java index c5268ac..df4089f 100644 --- a/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/InvalidElement2.java +++ b/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/InvalidElement2.java @@ -24,7 +24,7 @@ public Collection findInRawPatternInternal(String rawPattern) } @Override - public String getFormattedValue(JsonObject values) { + public Object getNativeValue(JsonObject values) { return null; diff --git a/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/ShouldNotShowElement.java b/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/ShouldNotShowElement.java index 15b61e7..8e99df7 100644 --- a/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/ShouldNotShowElement.java +++ b/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/element/impl/ShouldNotShowElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -36,7 +36,7 @@ public Collection findInRawPatternInternal(final String rawPa } @Override - public String getFormattedValue(final JsonObject values) { + public Object getNativeValue(final JsonObject values) { return "shouldNotShow"; diff --git a/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/DurationElementCustomTest.java b/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/DurationElementCustomTest.java index 4db85dc..b7baa51 100644 --- a/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/DurationElementCustomTest.java +++ b/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/DurationElementCustomTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 @@ -17,9 +17,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.ServiceLoader; - -import org.junit.jupiter.api.Test; import com.romanpierson.vertx.web.accesslogger.AccessLoggerConstants.Request.Data; import com.romanpierson.vertx.web.accesslogger.configuration.element.impl.DurationElement; @@ -56,8 +53,8 @@ public void testFindInRawPatternApacheFirstRequestLine(){ assertEquals("%r".length(), ep.getOffset()); // Test if the output of the looked up element is correct - assertEquals(expectedOutputWithQuery, ep.getElementSupplier().get().getFormattedValue(new JsonObject(valuesWithQuery))); - assertEquals(expectedOutputWithoutQuery, ep.getElementSupplier().get().getFormattedValue(new JsonObject(valuesWithoutQuery))); + assertEquals(expectedOutputWithQuery, ep.getElementSupplier().get().getNativeValue(new JsonObject(valuesWithQuery))); + assertEquals(expectedOutputWithoutQuery, ep.getElementSupplier().get().getNativeValue(new JsonObject(valuesWithoutQuery))); } /** diff --git a/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/RequestElementTest.java b/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/RequestElementTest.java index 6c5c659..9313a18 100644 --- a/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/RequestElementTest.java +++ b/src/test/java/com/romanpierson/vertx/web/accesslogger/configuration/pattern/RequestElementTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 diff --git a/src/test/java/com/romanpierson/vertx/web/accesslogger/element/ElementTest.java b/src/test/java/com/romanpierson/vertx/web/accesslogger/element/ElementTest.java index 1e89f3c..5f9ad7f 100644 --- a/src/test/java/com/romanpierson/vertx/web/accesslogger/element/ElementTest.java +++ b/src/test/java/com/romanpierson/vertx/web/accesslogger/element/ElementTest.java @@ -17,6 +17,7 @@ import io.vertx.core.http.HttpClientResponse; import io.vertx.core.http.HttpMethod; import io.vertx.core.json.JsonArray; +import io.vertx.core.json.JsonObject; import io.vertx.ext.web.client.WebClient; import io.vertx.junit5.VertxExtension; import io.vertx.junit5.VertxTestContext; @@ -33,6 +34,7 @@ class ElementTest { * @param vertx * @param testContext */ + @Test void testWithEmptyResponse(Vertx vertx, VertxTestContext testContext) { @@ -44,7 +46,7 @@ void testWithEmptyResponse(Vertx vertx, VertxTestContext testContext) { assertEquals(2, message.body().size()); assertEquals("-", message.body().getString(0)); - assertEquals("0", message.body().getString(1)); + assertEquals(0, message.body().getLong(1)); testContext.completeNow(); }); @@ -98,12 +100,12 @@ void testWithNonEmptyResponse(Vertx vertx, VertxTestContext testContext) { assertEquals(32, message.body().size()); - assertEquals("33", message.body().getString(0)); - assertEquals("33", message.body().getString(1)); - assertTrue(Long.parseLong(message.body().getString(2)) >= 0); - assertTrue(Long.parseLong(message.body().getString(3)) >= 0); - assertEquals("200", message.body().getString(4)); - assertEquals("200", message.body().getString(5)); + assertEquals(33, message.body().getLong(0)); + assertEquals(33, message.body().getLong(1)); + assertTrue(message.body().getLong(2) >= 0); + assertTrue(message.body().getLong(3) >= 0); + assertEquals(200, message.body().getInteger(4)); + assertEquals(200, message.body().getInteger(5)); assertEquals("HTTP/1.1", message.body().getString(6)); assertNotNull(message.body().getString(7)); assertEquals("localhost", message.body().getString(8)); @@ -123,13 +125,13 @@ void testWithNonEmptyResponse(Vertx vertx, VertxTestContext testContext) { assertEquals("envVal1", message.body().getString(22)); assertEquals("header1val", message.body().getString(23)); assertEquals("header1val", message.body().getString(24)); - assertEquals("", message.body().getString(25)); + assertEquals(null, message.body().getString(25)); assertEquals("application/json; charset=utf-8", message.body().getString(26)); assertEquals("application/json; charset=utf-8", message.body().getString(27)); - assertEquals("", message.body().getString(28)); + assertEquals(null, message.body().getString(28)); assertEquals("cookie1Value", message.body().getString(29)); assertEquals("cookie2Value", message.body().getString(30)); - assertEquals("", message.body().getString(31)); + assertEquals(null, message.body().getString(31)); testContext.completeNow(); }); diff --git a/src/test/java/com/romanpierson/vertx/web/accesslogger/util/FormatUtilityTest.java b/src/test/java/com/romanpierson/vertx/web/accesslogger/util/FormatUtilityTest.java index 1860451..169a0f9 100644 --- a/src/test/java/com/romanpierson/vertx/web/accesslogger/util/FormatUtilityTest.java +++ b/src/test/java/com/romanpierson/vertx/web/accesslogger/util/FormatUtilityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 diff --git a/src/test/java/com/romanpierson/vertx/web/accesslogger/util/VersionUtilityTest.java b/src/test/java/com/romanpierson/vertx/web/accesslogger/util/VersionUtilityTest.java index a5c896d..6c79067 100644 --- a/src/test/java/com/romanpierson/vertx/web/accesslogger/util/VersionUtilityTest.java +++ b/src/test/java/com/romanpierson/vertx/web/accesslogger/util/VersionUtilityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2023 Roman Pierson + * Copyright (c) 2016-2024 Roman Pierson * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Apache License v2.0 diff --git a/src/test/resources/accesslog-config-elasticsearch-appender-valid.yaml b/src/test/resources/accesslog-config-elasticsearch-appender-valid.yaml index b71e381..d2f6cbc 100644 --- a/src/test/resources/accesslog-config-elasticsearch-appender-valid.yaml +++ b/src/test/resources/accesslog-config-elasticsearch-appender-valid.yaml @@ -1,11 +1,11 @@ isAutoDeployProducerVerticle: false configurations: - identifier: accesslog-formatted - logPattern: '"%{msec}t cs-uri"' + logPattern: 'cs-uri %D' appenders: - appenderClassName : com.romanpierson.vertx.web.accesslogger.appender.elasticsearch.impl.ElasticSearchAppender config: instanceIdentifier: esInstance fieldNames: - - timestamp - - uri \ No newline at end of file + - uri + - duration \ No newline at end of file