Work in progress
diff --git a/audit-service-api/src/main/resources/catalog.json b/audit-service-api/src/main/resources/catalog.json
index 2bee559..6890287 100644
--- a/audit-service-api/src/main/resources/catalog.json
+++ b/audit-service-api/src/main/resources/catalog.json
@@ -37,7 +37,7 @@
"displayName" : "Login",
"description" : "User Login",
"aliases" : null,
- "attributes" : null
+ "attributes" : [{"name" : "userId", "required" : false}, {"name" : "accountNumber", "required" : false}]
}, {
"name" : "transfer",
"displayName" : "Transfer",
diff --git a/pom.xml b/pom.xml
index bb82ff4..cc9b420 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,7 +34,7 @@
<maven.javadoc.failOnError>false</maven.javadoc.failOnError>
<classmate.version>1.2.0</classmate.version>
<jackson.version>2.8.5</jackson.version>
- <log4j.version>2.9.0</log4j.version>
+ <log4j.version>2.10.0</log4j.version>
<log4j-audit.version>1.0.0-SNAPSHOT</log4j-audit.version>
<slf4j.version>1.6.2</slf4j.version>
<spring.version>4.3.3.RELEASE</spring.version>
@@ -407,5 +407,6 @@
<modules>
<module>audit-service-war</module>
<module>audit-service-api</module>
+ <module>sample-app</module>
</modules>
</project>
diff --git a/sample-app/pom.xml b/sample-app/pom.xml
new file mode 100644
index 0000000..506ff8d
--- /dev/null
+++ b/sample-app/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+ <!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache license, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the license for the specific language governing permissions and
+ ~ limitations under the license.
+ -->
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>audit-sample-parent</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>sample-app</artifactId>
+
+ <description>Audit Logging Sample Application</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-audit-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>audit-service-api</artifactId>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+
+ </plugins>
+ </build>
+</project>
diff --git a/sample-app/sample-app.sh b/sample-app/sample-app.sh
new file mode 100755
index 0000000..cab984e
--- /dev/null
+++ b/sample-app/sample-app.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+DEBUG=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005
+CLASSPATH=target/classes:$HOME/.m2/repository/org/apache/logging/log4j/log4j-api/2.10.0/log4j-api-2.10.0.jar:$HOME/.m2/repository/org/apache/logging/log4j/log4j-core/2.10.0/log4j-core-2.10.0.jar:$HOME/.m2/repository/org/apache/logging/log4j/log4j-audit-api/1.0.0-SNAPSHOT/log4j-audit-api-1.0.0-SNAPSHOT.jar:$HOME/.m2/repository/org/apache/logging/log4j/log4j-catalog-api/1.0.0-SNAPSHOT/log4j-catalog-api-1.0.0-SNAPSHOT.jar:$HOME/.m2/repository/io/springfox/springfox-swagger2/2.2.2/springfox-swagger2-2.2.2.jar:$HOME/.m2/repository/org/mapstruct/mapstruct/1.0.0.CR1/mapstruct-1.0.0.CR1.jar:$HOME/.m2/repository/io/swagger/swagger-annotations/1.5.3/swagger-annotations-1.5.3.jar:$HOME/.m2/repository/io/swagger/swagger-models/1.5.3/swagger-models-1.5.3.jar:$HOME/.m2/repository/io/springfox/springfox-spi/2.2.2/springfox-spi-2.2.2.jar:$HOME/.m2/repository/io/springfox/springfox-core/2.2.2/springfox-core-2.2.2.jar:$HOME/.m2/repository/io/springfox/springfox-schema/2.2.2/springfox-schema-2.2.2.jar:$HOME/.m2/repository/io/springfox/springfox-swagger-common/2.2.2/springfox-swagger-common-2.2.2.jar:$HOME/.m2/repository/io/springfox/springfox-spring-web/2.2.2/springfox-spring-web-2.2.2.jar:$HOME/.m2/repository/com/google/guava/guava/18.0/guava-18.0.jar:$HOME/.m2/repository/org/slf4j/slf4j-api/1.6.2/slf4j-api-1.6.2.jar:$HOME/.m2/repository/org/aspectj/aspectjweaver/1.8.6/aspectjweaver-1.8.6.jar:$HOME/.m2/repository/org/springframework/plugin/spring-plugin-core/1.2.0.RELEASE/spring-plugin-core-1.2.0.RELEASE.jar:$HOME/.m2/repository/org/springframework/plugin/spring-plugin-metadata/1.2.0.RELEASE/spring-plugin-metadata-1.2.0.RELEASE.jar:$HOME/.m2/repository/org/springframework/hateoas/spring-hateoas/0.18.0.RELEASE/spring-hateoas-0.18.0.RELEASE.jar:$HOME/.m2/repository/org/springframework/spring-web/4.3.3.RELEASE/spring-web-4.3.3.RELEASE.jar:$HOME/.m2/repository/org/springframework/spring-webmvc/4.3.3.RELEASE/spring-webmvc-4.3.3.RELEASE.jar:$HOME/.m2/repository/com/fasterxml/classmate/1.2.0/classmate-1.2.0.jar:$HOME/.m2/repository/org/apache/commons/commons-lang3/3.4/commons-lang3-3.4.jar:$HOME/.m2/repository/org/springframework/spring-context/4.3.3.RELEASE/spring-context-4.3.3.RELEASE.jar:$HOME/.m2/repository/org/springframework/spring-expression/4.3.3.RELEASE/spring-expression-4.3.3.RELEASE.jar:$HOME/.m2/repository/org/springframework/spring-context-support/4.3.3.RELEASE/spring-context-support-4.3.3.RELEASE.jar:$HOME/.m2/repository/org/springframework/spring-beans/4.3.3.RELEASE/spring-beans-4.3.3.RELEASE.jar:$HOME/.m2/repository/org/springframework/spring-core/4.3.3.RELEASE/spring-core-4.3.3.RELEASE.jar:$HOME/.m2/repository/org/springframework/spring-aop/4.3.3.RELEASE/spring-aop-4.3.3.RELEASE.jar:$HOME/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.8.5/jackson-core-2.8.5.jar:$HOME/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.8.5/jackson-databind-2.8.5.jar:$HOME/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.8.5/jackson-annotations-2.8.5.jar:$HOME/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.8.5/jackson-datatype-jsr310-2.8.5.jar:$HOME/.m2/repository/net/sf/jopt-simple/jopt-simple/4.9/jopt-simple-4.9.jar:$HOME/.m2/repository/org/apache/logging/log4j/log4j-jcl/2.10.0/log4j-jcl-2.10.0.jar:$HOME/.m2/repository/commons-logging/commons-logging/1.2/commons-logging-1.2.jar:$HOME/.m2/repository/org/apache/logging/log4j/audit-service-api/1.0.0-SNAPSHOT/audit-service-api-1.0.0-SNAPSHOT.jar
+$JAVA_HOME/bin/java -classpath $CLASSPATH org.apache.logging.audit.SampleApp
diff --git a/sample-app/src/main/java/org/apache/logging/audit/RequestContext.java b/sample-app/src/main/java/org/apache/logging/audit/RequestContext.java
new file mode 100644
index 0000000..5019001
--- /dev/null
+++ b/sample-app/src/main/java/org/apache/logging/audit/RequestContext.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.audit;
+
+import java.util.UUID;
+
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.audit.request.ChainedMapping;
+import org.apache.logging.log4j.audit.request.ClientServerMapping;
+import org.apache.logging.log4j.audit.request.LocalMapping;
+import org.apache.logging.log4j.audit.request.RequestContextBase;
+import org.apache.logging.log4j.audit.request.RequestContextMapping;
+import org.apache.logging.log4j.audit.request.RequestContextMappings;
+import org.apache.logging.log4j.core.util.UuidUtil;
+
+public class RequestContext extends RequestContextBase {
+ private static final String REQUEST_ID = "requestId";
+ private static final String SESSION_ID = "sessionId";
+ private static final String ACCOUNT_NUMBER = "accountNumber";
+ private static final String IP_ADDRESS = "ipAddress";
+ private static final String USER_ID = "userId";
+ private static final String LOGIN_ID = "loginId";
+ private static final String HOST_NAME = "hostName";
+ private static final String CALLING_HOST = "callingHost";
+
+ private static final String HEADER_PREFIX = "mycorp-context-";
+
+ private static RequestContextMapping[] mappingArray =
+ new RequestContextMapping[] { new ClientServerMapping(LOGIN_ID),
+ new ClientServerMapping(ACCOUNT_NUMBER), new ClientServerMapping(IP_ADDRESS),
+ new ClientServerMapping(USER_ID),
+ new ClientServerMapping(REQUEST_ID), new ClientServerMapping(SESSION_ID),
+ new ChainedMapping(HOST_NAME, CALLING_HOST), new LocalMapping(CALLING_HOST)};
+
+ static {
+ RequestContextBase.setMappings(new RequestContextMappings(mappingArray, HEADER_PREFIX));
+ }
+
+ public static String getRequestId() {
+ String uuidStr = ThreadContext.get(REQUEST_ID);
+ UUID uuid;
+ if (uuidStr == null) {
+ uuid = UuidUtil.getTimeBasedUuid();
+ ThreadContext.put(REQUEST_ID, uuid.toString());
+ }
+ return uuidStr;
+ }
+
+ private static void setRequestId(String requestId) {
+ if (requestId != null) {
+ ThreadContext.put(REQUEST_ID, requestId);
+ }
+ }
+
+ public static void setSessionId(UUID sessionId) {
+ if (sessionId != null) {
+ ThreadContext.put(SESSION_ID, sessionId.toString());
+ }
+ }
+
+ public static void setSessionId(String sessionId) {
+ if (sessionId != null) {
+ ThreadContext.put(SESSION_ID, sessionId);
+ }
+ }
+
+ public static void setAccountNumber(Long accountNumber) {
+ ThreadContext.put(ACCOUNT_NUMBER, accountNumber.toString());
+ }
+
+ public static Long getAccountNumber() {
+ String value = ThreadContext.get(ACCOUNT_NUMBER);
+ if (value == null || value.length() == 0) {
+ return 0L;
+ }
+ try {
+ return Long.parseLong(value);
+ } catch (Exception e) {
+ return 0L;
+ }
+ }
+
+ public static void setIpAddress(String address) {
+ ThreadContext.put(IP_ADDRESS, address);
+ }
+
+ public static String getIpAddress() {
+ return ThreadContext.get(IP_ADDRESS);
+ }
+
+ public static void setUserId(String userId) {
+ ThreadContext.put(USER_ID, userId);
+ }
+
+ public static String getUserId() {
+ return ThreadContext.get(USER_ID);
+ }
+
+ public static void setLoginId(String loginId) {
+ ThreadContext.put(LOGIN_ID, loginId);
+ }
+
+ public static String getLoginId() {
+ return ThreadContext.get(LOGIN_ID);
+ }
+
+ public static String getHostName() {
+ return ThreadContext.get(HOST_NAME);
+ }
+
+ public static void setHostName(String hostName) {
+ ThreadContext.put(HOST_NAME, hostName);
+ }
+
+ public static String getCallingHost() {
+ return ThreadContext.get(CALLING_HOST);
+ }
+
+ public static void setCallingHost(String hostName) {
+ ThreadContext.put(CALLING_HOST, hostName);
+ }
+}
diff --git a/sample-app/src/main/java/org/apache/logging/audit/SampleApp.java b/sample-app/src/main/java/org/apache/logging/audit/SampleApp.java
new file mode 100644
index 0000000..c3de8cc
--- /dev/null
+++ b/sample-app/src/main/java/org/apache/logging/audit/SampleApp.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.audit;
+
+import java.math.BigDecimal;
+import java.net.InetAddress;
+
+import org.apache.logging.log4j.audit.LogEventFactory;
+import org.apache.logging.log4j.audit.event.Deposit;
+import org.apache.logging.log4j.audit.event.Login;
+import org.apache.logging.log4j.core.util.NetUtils;
+
+public class SampleApp {
+
+ public static void main(String[] args) throws Exception {
+ String hostName = NetUtils.getLocalHostname();
+ RequestContext.setHostName(hostName);
+ String inetAddress = InetAddress.getLocalHost().getHostAddress();
+ RequestContext.setIpAddress(inetAddress);
+ RequestContext.setLoginId("testuser");
+ Login login = LogEventFactory.getEvent(Login.class);
+ login.logEvent();
+ String result = login("testuser");
+ login.setCompletionStatus(result);
+ login.logEvent();
+ Deposit deposit = LogEventFactory.getEvent(Deposit.class);
+ deposit.setAccount(123456);
+ deposit.setAmount(new BigDecimal(100.00));
+ deposit.logEvent();
+ result = deposit(deposit);
+ deposit.setCompletionStatus(result);
+ deposit.logEvent();
+ RequestContext.clear();
+ }
+
+ private static String login(String user) {
+ RequestContext.setUserId("1111");
+ RequestContext.setAccountNumber(12345L);
+ return "Success";
+ }
+
+ private static String deposit(Deposit deposit) {
+ return "Success";
+ }
+}
diff --git a/sample-app/src/main/resources/log4j2.xml b/sample-app/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..87ff4e9
--- /dev/null
+++ b/sample-app/src/main/resources/log4j2.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+~ Licensed to the Apache Software Foundation (ASF) under one or more
+~ contributor license agreements. See the NOTICE file distributed with
+~ this work for additional information regarding copyright ownership.
+~ The ASF licenses this file to You under the Apache license, Version 2.0
+~ (the "License"); you may not use this file except in compliance with
+~ the License. You may obtain a copy of the License at
+~
+~ http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the license for the specific language governing permissions and
+~ limitations under the license.
+-->
+<Configuration status="ERROR">
+ <properties>
+ <property name="LOG_DIR">target/logs</property>
+ </properties>
+ <MarkerFilter marker="FLOW" onMatch="ACCEPT" onMismatch="NEUTRAL"/>
+ <MarkerFilter marker="Audit" onMatch="ACCEPT" onMisMatch="NEUTRAL"/>
+ <Appenders>
+ <Console name="Console" target="SYSTEM_OUT">
+ <PatternLayout pattern="%d{ABSOLUTE} %-5level # %class.%method %m%n" />
+ </Console>
+
+ <RollingFile name="log4j" fileName="${LOG_DIR}/log4j.txt" filePattern="${LOG_DIR}/archive/log4j.txt.%d{yyyyMMdd_HHmmss}-%i">
+ <PatternLayout>
+ <MarkerPatternSelector defaultPattern="%d [%t] %-5p %X{loginId, userId, ipAddress, corpAcctNumber} %C{1.}.%M:%L - %m%n">
+ <PatternMatch key="FLOW" pattern="%d [%t] %-5p %X{loginId, userId, ipAddress, corpAcctNumber} -------- %C{1.}.%M:%L %msg --------%n"/>
+ </MarkerPatternSelector>
+ </PatternLayout>
+ <Policies>
+ <SizeBasedTriggeringPolicy size="30 MB"/>
+ </Policies>
+ <!-- A max of 20 will allow 20 files per second with the date pattern specified on the RollingFile declaration.
+ Hopefully that is a ridiculous value -->
+ <DefaultRolloverStrategy min="1" max="20">
+ <Delete basePath="${LOG_DIR}/archive">
+ <!-- Nested conditions: the inner condition is only evaluated on files for which the outer conditions are true. -->
+ <IfFileName glob="log4j.txt.*">
+ <!-- Only allow 1 GB of files to accumulate -->
+ <IfAccumulatedFileSize exceeds="1 GB"/>
+ </IfFileName>
+ </Delete>
+ </DefaultRolloverStrategy>
+ </RollingFile>
+ <RollingFile name="audit" fileName="${LOG_DIR}/audit.log" filePattern="${LOG_DIR}/archive/audit.log.%d{yyyyMMdd_HHmmss}-%i">
+ <RFC5424Layout enterpriseNumber="18060" includeMDC="true" mdcId="RequestContext" appName="SampleApp"
+ mdcPrefix="" newLine="true"/>
+ <Policies>
+ <SizeBasedTriggeringPolicy size="30 MB"/>
+ </Policies>
+ <!-- A max of 20 will allow 20 files per second with the date pattern specified on the RollingFile declaration.
+ Hopefully that is a ridiculous value -->
+ <DefaultRolloverStrategy min="1" max="20">
+ <Delete basePath="${LOG_DIR}/archive">
+ <!-- Nested conditions: the inner condition is only evaluated on files for which the outer conditions are true. -->
+ <IfFileName glob="audit.log.*">
+ <!-- Only allow 1 GB of files to accumulate -->
+ <IfAccumulatedFileSize exceeds="1 GB"/>
+ </IfFileName>
+ </Delete>
+ </DefaultRolloverStrategy>
+ </RollingFile>
+ </Appenders>
+ <Loggers>
+ <Logger name="org.apache.logging.log4j.audit" level="info" additivity="false">
+ <AppenderRef ref="log4j"/>
+ </Logger>
+ <Logger name="AuditLogger" level="trace" additivity="false">
+ <AppenderRef ref="audit"/>
+ </Logger>
+ <Root level="warn">
+ <AppenderRef ref="log4j" />
+ </Root>
+ </Loggers>
+</Configuration>
\ No newline at end of file