Rename slf4j ref impl, add constants 33/48433/2
authorLuke Parker <lparker@amdocs.com>
Tue, 22 May 2018 07:35:18 +0000 (17:35 +1000)
committerLuke Parker <lparker@amdocs.com>
Thu, 24 May 2018 06:48:24 +0000 (16:48 +1000)
Change-Id: Ib3f24c3aa4974ac8c87fa969613192e884674f00
Issue-ID: LOG-115
Signed-off-by: Luke Parker <lparker@amdocs.com>
47 files changed:
.gitignore [new file with mode: 0644]
pom.xml
reference/logging-slf4j-demo/README.md [moved from reference/slf4j-reference/README.md with 100% similarity]
reference/logging-slf4j-demo/pom.xml [moved from reference/slf4j-reference/pom.xml with 94% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/SLF4JRefApplication.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/SLF4JRefApplication.java with 74% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/bean/AbstractBean.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/AbstractBean.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/bean/Request.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/Request.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/bean/Response.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/Response.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/bean/package-info.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/bean/package-info.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/component/AbstractComponent.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/AbstractComponent.java with 98% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/component/alpha/ComponentAlpha.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/alpha/ComponentAlpha.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/component/alpha/package-info.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/alpha/package-info.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/component/beta/ComponentBeta.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/beta/ComponentBeta.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/component/beta/package-info.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/beta/package-info.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/component/delta/ComponentDelta.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/delta/ComponentDelta.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/component/delta/package-info.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/delta/package-info.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/component/gamma/ComponentGamma.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/gamma/ComponentGamma.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/component/gamma/package-info.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/gamma/package-info.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/component/package-info.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/component/package-info.java with 100% similarity]
reference/logging-slf4j-demo/src/main/java/org/onap/logging/ref/slf4j/demo/package-info.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/demo/package-info.java with 100% similarity]
reference/logging-slf4j-demo/src/main/resources/logback.xml [moved from reference/slf4j-reference/src/main/resources/logback.xml with 100% similarity]
reference/logging-slf4j-demo/src/main/webapp/WEB-INF/web.xml [moved from reference/slf4j-reference/src/main/webapp/WEB-INF/web.xml with 100% similarity]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/CallGraphTest.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/CallGraphTest.java with 100% similarity]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/analysis/CallGraphAnalyzer.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/analysis/CallGraphAnalyzer.java with 100% similarity]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/analysis/CallGraphReportWriter.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/analysis/CallGraphReportWriter.java with 100% similarity]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/analysis/LogEntry.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/analysis/LogEntry.java with 100% similarity]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/analysis/LogEntryTest.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/analysis/LogEntryTest.java with 100% similarity]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/demo/SLF4JRefApplicationTest.java [new file with mode: 0644]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/demo/bean/RequestTest.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/demo/bean/RequestTest.java with 100% similarity]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/demo/bean/ResponseTest.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/demo/bean/ResponseTest.java with 100% similarity]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/demo/component/AbstractComponentTest.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/demo/component/AbstractComponentTest.java with 100% similarity]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/demo/component/alpha/ComponentAlphaTest.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/demo/component/alpha/ComponentAlphaTest.java with 100% similarity]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/demo/component/beta/ComponentBetaTest.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/demo/component/beta/ComponentBetaTest.java with 100% similarity]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/demo/component/delta/ComponentDeltaTest.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/demo/component/delta/ComponentDeltaTest.java with 100% similarity]
reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/demo/component/gamma/ComponentGammaTest.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/demo/component/gamma/ComponentGammaTest.java with 100% similarity]
reference/logging-slf4j-demo/src/test/java/testng.xml [moved from reference/slf4j-reference/src/test/java/testng.xml with 100% similarity]
reference/logging-slf4j/README.md [new file with mode: 0644]
reference/logging-slf4j/pom.xml [new file with mode: 0644]
reference/logging-slf4j/src/main/java/org/onap/logging/ref/slf4j/ONAPLogAdapter.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/ONAPLogAdapter.java with 98% similarity]
reference/logging-slf4j/src/main/java/org/onap/logging/ref/slf4j/ONAPLogConstants.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/ONAPLogConstants.java with 85% similarity]
reference/logging-slf4j/src/main/java/org/onap/logging/ref/slf4j/package-info.java [moved from reference/slf4j-reference/src/main/java/org/onap/logging/ref/slf4j/common/package-info.java with 96% similarity]
reference/logging-slf4j/src/test/java/org/onap/logging/ref/slf4j/ONAPLogAdapterOutputTest.java [new file with mode: 0644]
reference/logging-slf4j/src/test/java/org/onap/logging/ref/slf4j/ONAPLogAdapterTest.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/common/ONAPLogAdapterTest.java with 62% similarity]
reference/logging-slf4j/src/test/java/org/onap/logging/ref/slf4j/ONAPLogConstantsTest.java [moved from reference/slf4j-reference/src/test/java/org/onap/logging/ref/slf4j/common/ONAPLogConstantsTest.java with 53% similarity]
reference/logging-slf4j/src/test/java/testng.xml [new file with mode: 0644]
reference/logging-slf4j/src/test/resources/logback.xml [new file with mode: 0644]
reference/pom.xml

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..8a809f2
--- /dev/null
@@ -0,0 +1,13 @@
+.idea
+.project
+.classpath
+.settings
+*.iml
+npm-debug.log
+node_modules/
+node_install/
+test_output/
+test-output/
+target/
+dist/
+
diff --git a/pom.xml b/pom.xml
index f8e1482..f17b3a8 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
   <parent>
       <groupId>org.onap.oparent</groupId>
       <artifactId>oparent</artifactId>
-      <version>1.1.1-SNAPSHOT</version>
+      <version>1.1.2-SNAPSHOT</version>
   </parent>
   <groupId>org.onap.logging-analytics</groupId>
   <artifactId>logging-analytics</artifactId>
similarity index 94%
rename from reference/slf4j-reference/pom.xml
rename to reference/logging-slf4j-demo/pom.xml
index 16caa92..c4542b3 100644 (file)
@@ -1,19 +1,14 @@
 <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>
-
-    <!--
     <parent>
       <groupId>org.onap.logging-analytics</groupId>
       <artifactId>logging-reference</artifactId>
       <version>1.2.0-SNAPSHOT</version>
       <relativePath>..</relativePath>
     </parent>
-    -->
-
-    <groupId>org.onap.logging-analytics</groupId>
-    <artifactId>slf4j-reference</artifactId>
+    <artifactId>logging-slf4j-demo</artifactId>
+    <name>logging-slf4j-demo</name>
     <packaging>war</packaging>
-    <name>logging-demo</name>
     <version>1.2.0-SNAPSHOT</version>
 
     <properties>
     </properties>
 
     <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>logging-slf4j</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
@@ -30,13 +30,25 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
 @SpringBootApplication
 public class SLF4JRefApplication {
 
+    /** System property override, read by embedded Logback configuration. */
+    public static final String SLF4J_OUTPUT_DIRECTORY = "SLF4J_OUTPUT_DIRECTORY";
+
     /**
      * Launch from CLI.
      * @param args command-line args.
      * @throws Exception launch error.
      */
     public static void main(final String[] args) throws Exception {
-        System.getProperties().setProperty("SLF4J_OUTPUT_DIRECTORY", ".");
+        initOutputDirectory();
         SpringApplication.run(SLF4JRefApplication.class, args);
     }
+
+    /**
+     * Make sure the output directory has a default value. (It'll be
+     * overridden by tests, but not in services.)
+     */
+    static void initOutputDirectory() {
+        System.getProperties().setProperty(SLF4J_OUTPUT_DIRECTORY,
+                System.getProperty(SLF4J_OUTPUT_DIRECTORY, "."));
+    }
 }
\ No newline at end of file
@@ -33,8 +33,8 @@ import com.mashape.unirest.http.Unirest;
 import com.mashape.unirest.http.exceptions.UnirestException;
 import org.apache.commons.lang3.StringUtils;
 import org.json.JSONObject;
-import org.onap.logging.ref.slf4j.common.ONAPLogAdapter;
-import org.onap.logging.ref.slf4j.common.ONAPLogConstants;
+import org.onap.logging.ref.slf4j.ONAPLogAdapter;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
 import org.onap.logging.ref.slf4j.demo.bean.Request;
 import org.onap.logging.ref.slf4j.demo.bean.Response;
 import org.slf4j.Logger;
diff --git a/reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/demo/SLF4JRefApplicationTest.java b/reference/logging-slf4j-demo/src/test/java/org/onap/logging/ref/slf4j/demo/SLF4JRefApplicationTest.java
new file mode 100644 (file)
index 0000000..a01cbe8
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.logging.ref.slf4j.demo;
+
+import org.testng.annotations.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+
+/**
+ * Tests for {@link SLF4JRefApplication}.
+ */
+public class SLF4JRefApplicationTest {
+
+    @Test
+    public void testProperty() {
+        assertThat(SLF4JRefApplication.SLF4J_OUTPUT_DIRECTORY,
+                is("SLF4J_OUTPUT_DIRECTORY"));
+    }
+
+    @Test
+    public void testInitOutputDirectory() throws Exception {
+        SLF4JRefApplication.initOutputDirectory();
+        assertThat(System.getProperty(SLF4JRefApplication.SLF4J_OUTPUT_DIRECTORY),
+                notNullValue());
+    }
+}
diff --git a/reference/logging-slf4j/README.md b/reference/logging-slf4j/README.md
new file mode 100644 (file)
index 0000000..2796a21
--- /dev/null
@@ -0,0 +1,50 @@
+# README - slf4j-reference
+
+This project gives an example of ONAP-compliant logging using SLF4J logging.
+
+## Adapter
+
+In ```org.onap.logging.ref.slf4j```, there are TWO classes:
+1. ```org.onap.logging.ref.slf4j.ONAPLogConstants```, providing declarations of standard ONAP Markers, MDCs and HTTP headers.
+2. ```org.onap.logging.ref.slf4j.ONAPLogAdapter```, providing a lightweight, compliant implementation of the ONAP logging spec.
+
+The adapter provides:
+1. A loosely-coupled SLF4j logging wrapper:
+ * To be used for logging ONAP ```entry```, ```exit``` and ```invoke``` behavior.
+ * Devolving all *application* logging to the component, via the regular SLF4J ```Logger``` facade.
+2. Customization options:
+ * *Cheap*, by way of bean properties. This is suited to most Use Cases.
+ * *Sophisticated*:
+    * By OPTIONALLY implementing one of a number of adapters:
+      * ```RequestAdapter``` to read incoming headers.
+      * ```ServiceDescriptor``` for reporting attributes of the current service.
+      * ```ResponseDescriptor``` for reporting outcomes.
+      * ```RequestBuilder``` for setting southbound request headers.
+    * By OPTIONALLY overriding methods like ```ONAPLogAdapter#setMDCs(RequestAdapter)```.
+
+Note that:
+* The adapter implementation uses static inner classes in order to fit in a single source file. This was an objective. 
+
+## WAR
+
+Building produces a simple (spring-boot](https://projects.spring.io/spring-boot/) example WAR, which can be launched from this directory with:
+
+```bash
+$ java -war target/*war
+```
+
+The example WAR in ```logging-slf4j-demo``` publishes four web services:
+1. ```services/alpha```
+2. ```services/beta```
+3. ```services/gamma```
+4. ```services/delta```
+
+... each of which can invoke the others.
+
+The purpose of the WAR is to demonstrate minimalist ONAP-compliant logging for web components, but a secondary purpose is to demonstrate that the call graph can be generated for a (mostly) representative set of interacting REST services.
+
+## Tests
+
+Tests for:
+1. Code in the (potentially) reusable ``common`` package.
+2. Validating that emitted logs can be used to generate an unambiguous call graph.
diff --git a/reference/logging-slf4j/pom.xml b/reference/logging-slf4j/pom.xml
new file mode 100644 (file)
index 0000000..9cc9d4b
--- /dev/null
@@ -0,0 +1,91 @@
+<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>
+    <parent>
+      <groupId>org.onap.logging-analytics</groupId>
+      <artifactId>logging-reference</artifactId>
+      <version>1.2.0-SNAPSHOT</version>
+      <relativePath>..</relativePath>
+    </parent>
+    <artifactId>logging-slf4j</artifactId>
+    <name>logging-slf4j</name>
+    <packaging>jar</packaging>
+    <version>1.2.0-SNAPSHOT</version>
+
+    <dependencies>
+        <!-- Exported dependencies. -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <!-- Provided dependencies. -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <!-- Test dependencies. -->
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.testng</groupId>
+            <artifactId>testng</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>hamcrest-all</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>1.7.25</version>
+            </dependency>
+            <dependency>
+                <groupId>javax.servlet</groupId>
+                <artifactId>javax.servlet-api</artifactId>
+                <version>3.1.0</version>
+                <scope>provided</scope>
+            </dependency>
+            <dependency>
+                <groupId>ch.qos.logback</groupId>
+                <artifactId>logback-classic</artifactId>
+                <version>1.2.3</version>
+            </dependency>
+            <dependency>
+                <groupId>org.testng</groupId>
+                <artifactId>testng</artifactId>
+                <version>6.8.5</version>
+                <exclusions>
+                    <exclusion>
+                        <groupId>junit</groupId>
+                        <artifactId>junit</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>org.hamcrest</groupId>
+                <artifactId>hamcrest-all</artifactId>
+                <version>1.3</version>
+            </dependency>
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring-test</artifactId>
+                <version>5.0.5.RELEASE</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+</project>
@@ -19,7 +19,7 @@
  * ============LICENSE_END=========================================================
  */
 
-package org.onap.logging.ref.slf4j.common;
+package org.onap.logging.ref.slf4j;
 
 import java.time.LocalDateTime;
 import java.util.UUID;
@@ -315,7 +315,7 @@ public class ONAPLogAdapter {
         // depending on where you need them to appear, OR extend the
         // ServiceDescriptor to add them.
 
-        MDC.put(ONAPLogConstants.MDCs.ENTRY_TIMESTAMP, LocalDateTime.now().toString());
+        MDC.put(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP, LocalDateTime.now().toString());
         MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, requestID);
         MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, invocationID);
         MDC.put(ONAPLogConstants.MDCs.PARTNER_NAME, partnerName);
@@ -495,7 +495,7 @@ public class ONAPLogAdapter {
             MDC.put(ONAPLogConstants.MDCs.RESPONSE_CODE, defaultToEmpty(this.mCode));
             MDC.put(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION, defaultToEmpty(this.mDescription));
             MDC.put(ONAPLogConstants.MDCs.RESPONSE_SEVERITY, defaultToEmpty(this.mSeverity));
-            MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS, defaultToEmpty(this.mStatus));
+            MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, defaultToEmpty(this.mStatus));
         }
     }
 
@@ -19,7 +19,7 @@
  * ============LICENSE_END=========================================================
  */
 
-package org.onap.logging.ref.slf4j.common;
+package org.onap.logging.ref.slf4j;
 
 import org.slf4j.Marker;
 import org.slf4j.MarkerFactory;
@@ -95,30 +95,53 @@ public final class ONAPLogConstants {
      */
     public static final class MDCs {
 
-        /** MDC correlating messages for a logical transaction. */
-        public static final String REQUEST_ID = "RequestID";
+        // Tracing. ////////////////////////////////////////////////////////////
 
         /** MDC correlating messages for an invocation. */
         public static final String INVOCATION_ID = "InvocationID";
 
-        /** MDC recording current service. */
-        public static final String SERVICE_NAME = "ServiceName";
+        /** MDC correlating messages for a logical transaction. */
+        public static final String REQUEST_ID = "RequestID";
 
         /** MDC recording calling service. */
         public static final String PARTNER_NAME = "PartnerName";
 
+        /** MDC recording current service. */
+        public static final String SERVICE_NAME = "ServiceName";
+
+        /** MDC recording target service. */
+        public static final String TARGET_SERVICE_NAME = "TargetServiceName";
+
         /** MDC recording current service instance. */
         public static final String INSTANCE_UUID = "InstanceUUID";
 
+        // Network. ////////////////////////////////////////////////////////////
+
         /** MDC recording caller address. */
         public static final String CLIENT_IP_ADDRESS = "ClientIPAddress";
 
         /** MDC recording server address. */
         public static final String SERVER_FQDN = "ServerFQDN";
 
-        /** MDC recording timestamp at the start of the current invocation. */
+        /**
+         * MDC recording timestamp at the start of the current request,
+         * with the same scope as {@link #REQUEST_ID}.
+         *
+         * <p>Open issues:
+         * <ul>
+         *     <ul>Easily confused with {@link #INVOKE_TIMESTAMP}.</ul>
+         *     <ul>No mechanism for propagation between components, e.g. via HTTP headers.</ul>
+         *     <ul>Whatever mechanism we define, it's going to be costly.</ul>
+         * </ul>
+         * </p>
+         * */
         public static final String ENTRY_TIMESTAMP = "EntryTimestamp";
 
+        /** MDC recording timestamp at the start of the current invocation. */
+        public static final String INVOKE_TIMESTAMP = "InvokeTimestamp";
+
+        // Outcomes. ///////////////////////////////////////////////////////////
+
         /** MDC reporting outcome code. */
         public static final String RESPONSE_CODE = "ResponseCode";
 
@@ -129,7 +152,9 @@ public final class ONAPLogConstants {
         public static final String RESPONSE_SEVERITY = "Severity";
 
         /** MDC reporting outcome error level. */
-        public static final String RESPONSE_STATUS = "StatusCode";
+        public static final String RESPONSE_STATUS_CODE = "StatusCode";
+
+        // Unsorted. ///////////////////////////////////////////////////////////
 
         /**
          * Hide and forbid construction.
@@ -188,7 +213,7 @@ public final class ONAPLogConstants {
         SYNCHRONOUS("SYNCHRONOUS", Markers.INVOKE_SYNCHRONOUS),
 
         /** Asynchronous, non-blocking. */
-        ASYNCHRONOUS("", Markers.INVOKE_ASYNCHRONOUS);
+        ASYNCHRONOUS("ASYNCHRONOUS", Markers.INVOKE_ASYNCHRONOUS);
 
         /** Enum value. */
         private String mString;
@@ -19,7 +19,7 @@
  * ============LICENSE_END=========================================================
  */
 
-package org.onap.logging.ref.slf4j.common;
+package org.onap.logging.ref.slf4j;
 
 /**
  * <p>Code in here has potential application outside this reference
diff --git a/reference/logging-slf4j/src/test/java/org/onap/logging/ref/slf4j/ONAPLogAdapterOutputTest.java b/reference/logging-slf4j/src/test/java/org/onap/logging/ref/slf4j/ONAPLogAdapterOutputTest.java
new file mode 100644 (file)
index 0000000..bab74bb
--- /dev/null
@@ -0,0 +1,162 @@
+/**
+ * ============LICENSE_START=======================================================
+ * org.onap.logging
+ * ================================================================================
+ * Copyright © 2018 Amdocs
+ * All rights reserved.
+ * ================================================================================
+ * Licensed 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.logging.ref.slf4j;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.xml.bind.DatatypeConverter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.springframework.mock.web.MockHttpServletRequest;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.hamcrest.number.OrderingComparison.greaterThan;
+
+/**
+ * Smoketest output, though the embedded configuration isn't necessarily
+ * canonical.
+ *
+ * <p>There are more comprehensive tests in the <tt>logging-slf4j-demo</tt>
+ * project.</p>
+ */
+public class ONAPLogAdapterOutputTest {
+
+    /** Temporary directory into which logfiles are written. */
+    private static File sDir;
+
+    @BeforeSuite
+    public static void setUp() throws Exception {
+        sDir = Files.createTempDirectory(ONAPLogAdapterOutputTest.class.getName()).toFile();
+        System.getProperties().setProperty("SLF4J_OUTPUT_DIRECTORY", sDir.getAbsolutePath());
+        LoggerFactory.getLogger(ONAPLogAdapterOutputTest.class).info("Starting.");
+    }
+
+    @AfterSuite
+    public static void tearDown() throws Exception {
+        LoggerFactory.getLogger(ONAPLogAdapterOutputTest.class).info("Ending.");
+        Thread.sleep(1000L);
+        if (sDir != null) {
+            System.err.println("Should be deleting [" + sDir.getAbsolutePath() + "]...");
+        }
+    }
+
+    @Test
+    public void testOutput() throws Exception {
+
+        assertThat(sDir, notNullValue());
+        assertThat(sDir.isDirectory(), is(true));
+
+        final String uuid = UUID.randomUUID().toString();
+        final String errorcode = UUID.randomUUID().toString();
+        final Logger logger = LoggerFactory.getLogger(ONAPLogAdapterOutputTest.class);
+
+        try {
+            MDC.put("uuid", uuid);
+            final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
+            final ONAPLogAdapter.HttpServletRequestAdapter http
+                    = new ONAPLogAdapter.HttpServletRequestAdapter(new MockHttpServletRequest());
+            adapter.entering(http);
+            adapter.unwrap().warn("a_warning");
+            try {
+                throw new Exception("errorcode=" + errorcode);
+            }
+            catch (final Exception e) {
+                adapter.unwrap().error("an_error", e);
+            }
+
+            Thread.sleep(1000L);
+        }
+        finally {
+            MDC.clear();
+        }
+
+        final List<String> lines = new ArrayList<>();
+        for (final File f : sDir.listFiles()) {
+            try (BufferedReader reader = new BufferedReader(new FileReader(f))) {
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    if (line.contains(uuid)) {
+                        lines.add(line);
+                    }
+                }
+            }
+        }
+
+        assertThat(lines.size(), is(3));
+
+        assertThat(lines.get(0), containsString("ENTRY"));
+        final String [] line0 = lines.get(0).split("\t", -1);
+        assertThat(line0.length, is(9));
+        DatatypeConverter.parseDateTime(line0[0]);
+        assertThat(line0[1].trim().length(), greaterThan(1));
+        assertThat(line0[2], is("INFO"));
+        assertThat(line0[3], is(this.getClass().getName()));
+        assertThat(line0[4], containsString("uuid=" + uuid));
+        assertThat(line0[5], is(""));
+        assertThat(line0[6], is(""));
+        assertThat(line0[7], is("ENTRY"));
+        System.err.println(lines.get(0));
+
+        assertThat(lines.get(1), not(containsString("ENTRY")));
+        assertThat(lines.get(1), containsString("a_warning"));
+        final String [] line1 = lines.get(1).split("\t", -1);
+        assertThat(line1.length, is(9));
+        DatatypeConverter.parseDateTime(line1[0]);
+        assertThat(line1[1].trim().length(), greaterThan(1));
+        assertThat(line1[2], is("WARN"));
+        assertThat(line1[3], is(this.getClass().getName()));
+        assertThat(line1[4], containsString("uuid=" + uuid));
+        assertThat(line1[5], is("a_warning"));
+        assertThat(line1[6], is(""));
+        assertThat(line1[7], is(""));
+        System.err.println(lines.get(1));
+
+        assertThat(lines.get(2), not(containsString("ENTRY")));
+        assertThat(lines.get(2), containsString("an_error"));
+        final String [] line2 = lines.get(2).split("\t", -1);
+        assertThat(line2.length, is(9));
+        DatatypeConverter.parseDateTime(line2[0]);
+        assertThat(line2[1].trim().length(), greaterThan(1));
+        assertThat(line2[2], is("ERROR"));
+        assertThat(line2[3], is(this.getClass().getName()));
+        assertThat(line2[4], containsString("uuid=" + uuid));
+        assertThat(line2[5], is("an_error"));
+        assertThat(line2[6], containsString("errorcode=" + errorcode));
+        assertThat(line2[7], is(""));
+        System.err.println(lines.get(2));
+    }
+}
@@ -19,7 +19,7 @@
  * ============LICENSE_END=========================================================
  */
 
-package org.onap.logging.ref.slf4j.common;
+package org.onap.logging.ref.slf4j;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -36,8 +36,10 @@ import org.testng.annotations.Test;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
 import static org.hamcrest.core.IsNull.notNullValue;
 import static org.hamcrest.core.IsNull.nullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
 
 /**
  * Tests for {@link ONAPLogAdapter}.
@@ -120,6 +122,37 @@ public class ONAPLogAdapterTest {
         }
     }
 
+    @Test
+    public void testSetServiceDescriptor() {
+        final ONAPLogAdapter.ServiceDescriptor override = new ONAPLogAdapter.ServiceDescriptor();
+        final Logger logger = LoggerFactory.getLogger(this.getClass());
+        final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
+        final ONAPLogAdapter.ServiceDescriptor before = adapter.getServiceDescriptor();
+        adapter.setServiceDescriptor(override);
+        final ONAPLogAdapter.ServiceDescriptor after = adapter.getServiceDescriptor();
+        assertThat(after, not(sameInstance(before)));
+        assertThat(after, is(override));
+    }
+
+    @Test
+    public void testSetResponseDescriptor() {
+        final ONAPLogAdapter.ResponseDescriptor override = new ONAPLogAdapter.ResponseDescriptor();
+        final Logger logger = LoggerFactory.getLogger(this.getClass());
+        final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
+        final ONAPLogAdapter.ResponseDescriptor before = adapter.getResponseDescriptor();
+        adapter.setResponseDescriptor(override);
+        final ONAPLogAdapter.ResponseDescriptor after = adapter.getResponseDescriptor();
+        assertThat(after, not(sameInstance(before)));
+        assertThat(after, is(override));
+    }
+
+    @Test
+    public void testUnwrap() {
+        final Logger logger = LoggerFactory.getLogger(this.getClass());
+        final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
+        assertThat(adapter.unwrap(), is(logger));
+    }
+
     /**
      * Test EXITING.
      */
@@ -190,6 +223,94 @@ public class ONAPLogAdapterTest {
         }
     }
 
+    /**
+     * Test INVOKE, with RequestAdapter.
+     */
+    @Test
+    public void testInvokeWithAdapterAndNull() throws Exception {
+
+        final Logger logger = LoggerFactory.getLogger(this.getClass());
+        final ONAPLogAdapter adapter = new ONAPLogAdapter(logger);
+
+        final Map<String, String> headers = new HashMap<>();
+        final ONAPLogAdapter.RequestBuilder builder = new ONAPLogAdapter.RequestBuilder<ONAPLogAdapter.RequestBuilder>() {
+            @Override
+            public ONAPLogAdapter.RequestBuilder setHeader(final String name, final String value) {
+                headers.put(name, value);
+                return this;
+            }
+        };
+
+        try {
+            final UUID uuid = adapter.invoke(builder);
+            assertThat(uuid, notNullValue());
+            assertThat(headers.get(ONAPLogConstants.Headers.INVOCATION_ID), is(uuid.toString()));
+            assertThat(headers.containsKey(ONAPLogConstants.Headers.PARTNER_NAME), is(true));
+            assertThat(headers.containsKey(ONAPLogConstants.Headers.REQUEST_ID), is(true));
+        }
+        finally {
+            MDC.clear();
+        }
+    }
+
+    @Test
+    public void testHttpServletRequestAdapter() {
+
+        final UUID uuid = UUID.randomUUID();
+        final MockHttpServletRequest request = new MockHttpServletRequest();
+        request.addHeader("uuid", uuid.toString());
+        request.setRequestURI("/ctx0");
+        request.setServerName("srv0");
+
+        final ONAPLogAdapter.HttpServletRequestAdapter adapter
+                = new ONAPLogAdapter.HttpServletRequestAdapter(request);
+        assertThat(adapter.getHeader("uuid"), is(uuid.toString()));
+        assertThat(adapter.getRequestURI(), is("/ctx0"));
+        assertThat(adapter.getServerAddress(), is("srv0"));
+    }
+
+    @Test
+    public void testServiceDescriptor() {
+        final String uuid = UUID.randomUUID().toString();
+
+        final ONAPLogAdapter.ServiceDescriptor adapter
+                = new ONAPLogAdapter.ServiceDescriptor();
+        adapter.setServiceUUID(uuid);
+        adapter.setServiceName("name0");
+
+        assertThat(MDC.get(ONAPLogConstants.MDCs.SERVICE_NAME), nullValue());
+        assertThat(MDC.get(ONAPLogConstants.MDCs.INSTANCE_UUID), nullValue());
+
+        adapter.setMDCs();
+
+        assertThat(MDC.get(ONAPLogConstants.MDCs.SERVICE_NAME), is("name0"));
+        assertThat(MDC.get(ONAPLogConstants.MDCs.INSTANCE_UUID), is(uuid));
+    }
+
+    @Test
+    public void testResponseDescriptor() {
+        final String uuid = UUID.randomUUID().toString();
+
+        final ONAPLogAdapter.ResponseDescriptor adapter
+                = new ONAPLogAdapter.ResponseDescriptor();
+        adapter.setResponseCode("code0");
+        adapter.setResponseDescription("desc0");
+        adapter.setResponseSeverity(Level.INFO);
+        adapter.setResponseStatus(ONAPLogConstants.ResponseStatus.COMPLETED);
+
+        assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_CODE), nullValue());
+        assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION), nullValue());
+        assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_SEVERITY), nullValue());
+        assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE), nullValue());
+
+        adapter.setMDCs();
+
+        assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_CODE), is("code0"));
+        assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION), is("desc0"));
+        assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_SEVERITY), is("INFO"));
+        assertThat(MDC.get(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE), is("COMPLETED"));
+    }
+
     /**
      * Exercise the contract, for a caller that's happy to have their
      * service name automatically derived. (This validates nothing
@@ -19,7 +19,7 @@
  * ============LICENSE_END=========================================================
  */
 
-package org.onap.logging.ref.slf4j.common;
+package org.onap.logging.ref.slf4j;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
@@ -37,14 +37,11 @@ import static org.hamcrest.core.IsInstanceOf.instanceOf;
 public class ONAPLogConstantsTest {
 
     @Test
-    public void testConstructor() throws Exception {
-        try {
-            ONAPLogConstants.class.getDeclaredConstructors()[0].newInstance();
-            Assert.fail("Should fail for hidden constructor.");
-        }
-        catch (final IllegalAccessException e) {
-
-        }
+    public void testConstructors() throws Exception {
+        assertInaccessibleConstructor(ONAPLogConstants.class);
+        assertInaccessibleConstructor(ONAPLogConstants.MDCs.class);
+        assertInaccessibleConstructor(ONAPLogConstants.Markers.class);
+        assertInaccessibleConstructor(ONAPLogConstants.Headers.class);
     }
 
     @Test
@@ -62,9 +59,9 @@ public class ONAPLogConstantsTest {
 
     @Test
     public void testHeaders() {
-        assertThat(ONAPLogConstants.Headers.REQUEST_ID.toString(), is("X-ONAP-RequestID"));
-        assertThat(ONAPLogConstants.Headers.INVOCATION_ID.toString(), is("X-ONAP-InvocationID"));
-        assertThat(ONAPLogConstants.Headers.PARTNER_NAME.toString(), is("X-ONAP-PartnerName"));
+        assertThat(ONAPLogConstants.Headers.REQUEST_ID, is("X-ONAP-RequestID"));
+        assertThat(ONAPLogConstants.Headers.INVOCATION_ID, is("X-ONAP-InvocationID"));
+        assertThat(ONAPLogConstants.Headers.PARTNER_NAME, is("X-ONAP-PartnerName"));
     }
 
     @Test
@@ -83,4 +80,54 @@ public class ONAPLogConstantsTest {
         assertThat(ONAPLogConstants.InvocationMode.ASYNCHRONOUS.getMarker(),
                 is(ONAPLogConstants.Markers.INVOKE_ASYNCHRONOUS));
     }
+
+    @Test
+    public void testInvocationModeToString() {
+        assertThat(ONAPLogConstants.InvocationMode.SYNCHRONOUS.toString(),
+                is("SYNCHRONOUS"));
+    }
+
+    @Test
+    public void testResponseStatus() {
+        assertThat(ONAPLogConstants.ResponseStatus.COMPLETED.toString(), is("COMPLETED"));
+        assertThat(ONAPLogConstants.ResponseStatus.ERROR.toString(), is("ERROR"));
+    }
+
+    @Test
+    public void testMDCs() {
+
+        assertThat(ONAPLogConstants.MDCs.CLIENT_IP_ADDRESS.toString(), is("ClientIPAddress"));
+        assertThat(ONAPLogConstants.MDCs.SERVER_FQDN.toString(), is("ServerFQDN"));
+
+        assertThat(ONAPLogConstants.MDCs.ENTRY_TIMESTAMP.toString(), is("EntryTimestamp"));
+        assertThat(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP.toString(), is("InvokeTimestamp"));
+
+        assertThat(ONAPLogConstants.MDCs.REQUEST_ID.toString(), is("RequestID"));
+        assertThat(ONAPLogConstants.MDCs.INVOCATION_ID.toString(), is("InvocationID"));
+        assertThat(ONAPLogConstants.MDCs.PARTNER_NAME.toString(), is("PartnerName"));
+        assertThat(ONAPLogConstants.MDCs.INSTANCE_UUID.toString(), is("InstanceUUID"));
+        assertThat(ONAPLogConstants.MDCs.SERVICE_NAME.toString(), is("ServiceName"));
+        assertThat(ONAPLogConstants.MDCs.TARGET_SERVICE_NAME.toString(), is("TargetServiceName"));
+
+    }
+
+    static void assertInaccessibleConstructor(final Class<?> c) throws Exception {
+        try {
+            c.getDeclaredConstructors()[0].newInstance();
+            Assert.fail("Should fail for hidden constructor.");
+        }
+        catch (final IllegalAccessException e) {
+
+        }
+
+        try {
+            final Constructor<?> constructor = c.getDeclaredConstructors()[0];
+            constructor.setAccessible(true);
+            constructor.newInstance();
+            Assert.fail("Should fail even when invoked.");
+        }
+        catch (final InvocationTargetException e) {
+            assertThat(e.getCause(), instanceOf(UnsupportedOperationException.class));
+        }
+    }
 }
diff --git a/reference/logging-slf4j/src/test/java/testng.xml b/reference/logging-slf4j/src/test/java/testng.xml
new file mode 100644 (file)
index 0000000..7b31c26
--- /dev/null
@@ -0,0 +1,8 @@
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
+<suite name="org.onap.logging.ref.slf4j" verbose="9" thread-count="1" parallel="methods">
+    <test name="all" thread-count="1" enabled="true">
+        <packages>
+            <package name="org.onap.logging.ref.slf4j.*"/>
+        </packages>
+    </test>
+</suite>
\ No newline at end of file
diff --git a/reference/logging-slf4j/src/test/resources/logback.xml b/reference/logging-slf4j/src/test/resources/logback.xml
new file mode 100644 (file)
index 0000000..554d712
--- /dev/null
@@ -0,0 +1,35 @@
+<configuration>
+
+    <property name="p_tim" value="%d{&quot;yyyy-MM-dd'T'HH:mm:ss.SSSXXX&quot;, UTC}"/>
+    <property name="p_lvl" value="%level"/>
+    <property name="p_log" value="%logger"/>
+    <property name="p_mdc" value="%replace(%replace(%mdc){'\t','\\\\t'}){'\n', '\\\\n'}"/>
+    <property name="p_msg" value="%replace(%replace(%msg){'\t', '\\\\t'}){'\n','\\\\n'}"/>
+    <property name="p_exc" value="%replace(%replace(%rootException){'\t', '\\\\t'}){'\n','\\\\n'}"/>
+    <property name="p_mak" value="%replace(%replace(%marker){'\t', '\\\\t'}){'\n','\\\\n'}"/>
+    <property name="p_thr" value="%thread"/>
+    <property name="pattern" value="%nopexception${p_tim}\t${p_thr}\t${p_lvl}\t${p_log}\t${p_mdc}\t${p_msg}\t${p_exc}\t${p_mak}\t%n"/>
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>${pattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+        <file>${SLF4J_OUTPUT_DIRECTORY}/output.log</file>
+        <encoder>
+            <pattern>${pattern}</pattern>
+        </encoder>
+    </appender>
+
+    <logger level="debug" name="org.onap.logging.ref.slf4j" additivity="false">
+        <appender-ref ref="STDOUT" />
+        <appender-ref ref="FILE" />
+    </logger>
+
+    <root level="error">
+        <appender-ref ref="STDOUT" />
+    </root>
+
+</configuration>
index b3f99ba..7bb5f64 100644 (file)
@@ -16,6 +16,8 @@
     <module>logging-mock-service</module>
     <module>logging-docker-root</module>
     <module>logging-kubernetes</module>
+    <module>logging-slf4j</module>
+    <module>logging-slf4j-demo</module>
   </modules>
   <build>
       <pluginManagement>