--- /dev/null
+# Acumos Logging Standards
+
+This repository holds the POC of logging standards for Acumos Boreas Release.
+Adopt the MDC Key-Value pair approach and get rid of position specific pipe delimiters.
+
+
+## License
+
+Copyright (C) 2019 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+Acumos is distributed by AT&T and Tech Mahindra 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
+
+This file 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.
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ===============LICENSE_START=======================================================
+ Acumos
+ ===================================================================================
+ Copyright (C) 2019 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ ===================================================================================
+ This Acumos software file is distributed by AT&T and Tech Mahindra
+ 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
+
+ This file 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=========================================================
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.acumos.platform-oam</groupId>
+ <artifactId>logging-demo</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ <packaging>jar</packaging>
+ <name>logging-demo</name>
+ <description>Demo project for Logging</description>
+
+ <parent>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-parent</artifactId>
+ <version>2.1.0.RELEASE</version>
+ <relativePath /> <!-- lookup parent from repository -->
+ </parent>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <java.version>1.8</java.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+
+
+</project>
--- /dev/null
+/*
+ ===============LICENSE_START=======================================================
+ Acumos
+ ===================================================================================
+ Copyright (C) 2019 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ ===================================================================================
+ This Acumos software file is distributed by AT&T and Tech Mahindra
+ 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
+
+ This file 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.acumos.demo.logging;
+
+import java.util.concurrent.Executor;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+@SpringBootApplication
+@EnableAsync
+public class Application {
+
+ @Bean
+ public Executor asyncExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setTaskDecorator(new LoggingTaskDecorator());
+ executor.initialize();
+ return executor;
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
--- /dev/null
+/*
+ ===============LICENSE_START=======================================================
+ Acumos
+ ===================================================================================
+ Copyright (C) 2019 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ ===================================================================================
+ This Acumos software file is distributed by AT&T and Tech Mahindra
+ 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
+
+ This file 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.acumos.demo.logging;
+
+import java.util.UUID;
+import org.acumos.demo.logging.service.ApplicationService;
+import org.acumos.demo.logging.util.ACUMOSLogConstants.MDCs;
+import org.slf4j.MDC;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.stereotype.Component;
+
+@Component
+public class Execute implements CommandLineRunner {
+ private ApplicationService applicationService;
+
+ public Execute(ApplicationService applicationService) {
+ this.applicationService = applicationService;
+ }
+
+ @Override
+ public void run(String... args) {
+
+ String txId = UUID.randomUUID().toString();
+
+ MDC.put(MDCs.REQUEST_ID, txId);
+ MDC.put(MDCs.RESPONSE_CODE, "500");
+ MDC.put(MDCs.RESPONSE_DESCRIPTION, "Internal Server Error");
+ MDC.put(MDCs.RESPONSE_SEVERITY, "ERROR");
+ MDC.put(MDCs.STATUS_CODE, "ERROR");
+ MDC.put(MDCs.TARGET_ENTITY, "Onboarding");
+ MDC.put(MDCs.TARGET_SERVICE_NAME, "Onboarding/api/v2");
+ MDC.put(MDCs.CLIENT_IP_ADDRESS, "127.0.0.1");
+ MDC.put(MDCs.SERVER_FQDN, "put.your.host.name.here");
+
+ applicationService.logNormalThread();
+ applicationService.logAsyncThread();
+ }
+
+}
--- /dev/null
+/*
+ ===============LICENSE_START=======================================================
+ Acumos
+ ===================================================================================
+ Copyright (C) 2019 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ ===================================================================================
+ This Acumos software file is distributed by AT&T and Tech Mahindra
+ 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
+
+ This file 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.acumos.demo.logging;
+
+import java.util.Map;
+
+import org.slf4j.MDC;
+import org.springframework.core.task.TaskDecorator;
+
+/**
+ * Copy MDC data from a Web thread context onto the asynchronous threads’
+ * context.
+ *
+ */
+public class LoggingTaskDecorator implements TaskDecorator {
+
+ @Override
+ public Runnable decorate(Runnable runnable) {
+ // Right now: Web thread context !
+ // (Grab the current thread MDC data)
+ Map<String, String> contextMap = MDC.getCopyOfContextMap();
+ return () -> {
+ try {
+ // Right now: @Async thread context !
+ // (Restore the Web thread context's MDC data)
+ MDC.setContextMap(contextMap);
+ runnable.run();
+ } finally {
+ MDC.clear();
+ }
+ };
+ }
+
+}
--- /dev/null
+/*
+ ===============LICENSE_START=======================================================
+ Acumos
+ ===================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ ===================================================================================
+ This Acumos software file is distributed by AT&T and Tech Mahindra
+ 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
+
+ This file 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.acumos.demo.logging.service;
+
+import org.acumos.demo.logging.util.ACUMOSLogConstants.InvocationMode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ApplicationService {
+ private static final Logger log = LoggerFactory.getLogger(ApplicationService.class);
+
+
+ public void logNormalThread() {
+
+ log.info(InvocationMode.SYNCHRONOUS.getMarker(),"platform-oam");
+
+ }
+
+ @Async
+ public void logAsyncThread() {
+
+ log.info(InvocationMode.ASYNCHRONOUS.getMarker(),"platform-oam");
+
+ }
+
+}
--- /dev/null
+/*
+ ===============LICENSE_START=======================================================
+ Acumos
+ ===================================================================================
+ Copyright (C) 2019 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ ===================================================================================
+ This Acumos software file is distributed by AT&T and Tech Mahindra
+ 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
+
+ This file 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.acumos.demo.logging.util;
+
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+
+/**
+ * Constants for standard ACUMOS headers, MDCs, etc.
+ *
+ */
+public final class ACUMOSLogConstants {
+
+ /**
+ * Hide and forbid construction.
+ */
+ private ACUMOSLogConstants() {
+ throw new UnsupportedOperationException();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Inner classes.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Marker constants.
+ */
+ public static final class Markers {
+
+ /** Marker reporting invocation. */
+ public static final Marker INVOKE = MarkerFactory.getMarker("INVOKE");
+
+ /** Marker reporting invocation. */
+ public static final Marker INVOKE_RETURN = MarkerFactory.getMarker("INVOKE_RETURN");
+
+ /** Marker reporting synchronous invocation. */
+ public static final Marker INVOKE_SYNCHRONOUS = build("INVOKE", "SYNCHRONOUS");
+
+ /** Marker reporting asynchronous invocation. */
+ public static final Marker INVOKE_ASYNCHRONOUS = build("INVOKE", "ASYNCHRONOUS");
+
+ /** Marker reporting entry into a component. */
+ public static final Marker ENTRY = MarkerFactory.getMarker("ENTRY");
+
+ /** Marker reporting exit from a component. */
+ public static final Marker EXIT = MarkerFactory.getMarker("EXIT");
+
+ /**
+ * Build nested, detached marker.
+ *
+ * @param m1
+ * top token.
+ * @param m2
+ * sub-token.
+ * @return detached Marker.
+ */
+ private static Marker build(final String m1, final String m2) {
+ final Marker marker = MarkerFactory.getDetachedMarker(m1);
+ marker.add(MarkerFactory.getDetachedMarker(m2));
+ return marker;
+ }
+
+ /**
+ * Hide and forbid construction.
+ */
+ private Markers() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * MDC name constants.
+ */
+ public static final class MDCs {
+
+ // Tracing. ////////////////////////////////////////////////////////////
+
+ /** MDC correlating messages for a logical transaction. */
+ public static final String REQUEST_ID = "RequestID";
+
+ /** MDC recording target service. */
+ public static final String TARGET_SERVICE_NAME = "TargetServiceName";
+
+ /** MDC recording target entity. */
+ public static final String TARGET_ENTITY = "TargetEntity";
+
+ // 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 reporting outcome code. */
+ public static final String RESPONSE_CODE = "ResponseCode";
+
+ /** MDC reporting outcome description. */
+ public static final String RESPONSE_DESCRIPTION = "ResponseDescription";
+
+ /** MDC reporting outcome error level. */
+ public static final String RESPONSE_SEVERITY = "Severity";
+
+ /** MDC reporting outcome error level. */
+ public static final String STATUS_CODE = "StatusCode";
+
+ // Unsorted. ///////////////////////////////////////////////////////////
+
+ /**
+ * Hide and forbid construction.
+ */
+ private MDCs() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * Header name constants.
+ */
+ public static final class Headers {
+
+ /** HTTP X-ACUMOS-RequestID header. */
+ public static final String REQUEST_ID = "X-ACUMOS-RequestID";
+
+ /**
+ * Hide and forbid construction.
+ */
+ private Headers() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Enums.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Response success or not, for setting <tt>StatusCode</tt>.
+ */
+ public enum ResponseStatus {
+
+ /** Success. */
+ COMPLETED,
+
+ /** Not. */
+ ERROR,
+
+ /** In Progress. */
+ INPROGRESS
+ }
+
+ /**
+ * Synchronous or asynchronous execution, for setting invocation marker.
+ */
+ public enum InvocationMode {
+
+ /** Synchronous, blocking. */
+ SYNCHRONOUS("SYNCHRONOUS", Markers.INVOKE_SYNCHRONOUS),
+
+ /** Asynchronous, non-blocking. */
+ ASYNCHRONOUS("ASYNCHRONOUS", Markers.INVOKE_ASYNCHRONOUS);
+
+ /** Enum value. */
+ private String mString;
+
+ /** Corresponding marker. */
+ private Marker mMarker;
+
+ /**
+ * Construct enum.
+ *
+ * @param s
+ * enum value.
+ * @param m
+ * corresponding Marker.
+ */
+ InvocationMode(final String s, final Marker m) {
+ this.mString = s;
+ this.mMarker = m;
+ }
+
+ /**
+ * Get Marker for enum.
+ *
+ * @return Marker.
+ */
+ public Marker getMarker() {
+ return this.mMarker;
+ }
+
+ @Override
+ public String toString() {
+ return this.mString;
+ }
+ }
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ===============LICENSE_START=======================================================
+ Acumos ===================================================================================
+ Copyright (C) 2019 AT&T Intellectual Property & Tech Mahindra. All rights
+ reserved. ===================================================================================
+ This Acumos software file is distributed by AT&T and Tech Mahindra 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 This file 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========================================================= -->
+<configuration scan="true" scanPeriod="3 seconds" debug="false">
+
+ <!-- gather files in a subdirectory - usually a volume in docker -->
+ <property name="logDirPrefix" value="logs/platform-oam" />
+
+ <!-- component name is log file basename -->
+ <property name="componentName" value="OAM" />
+
+ <!-- The directories where logs are written -->
+ <property name="logDirectory" value="${logDirPrefix}/${componentName}" />
+
+ <!-- Based on https://wiki.acumos.org/display/OAM/Acumos+Log+Standards -->
+ <property name="LogTimestamp"
+ value="%d{"yyyy-MM-dd'T'HH:mm:ss.SSSXXX", UTC}" />
+ <property name="Level" value="%.-5level" />
+ <property name="Logger" value="%logger" />
+ <property name="Mdc"
+ value="%replace(%replace(%mdc){'\t','\\\\t'}){'\n','\\\\n'}" />
+ <property name="Marker"
+ value="%replace(%replace(%marker){'\t','\\\\t'}){'\n','\\\\n'}" />
+ <property name="Thread" value="%thread" />
+ <property name="Message"
+ value="%replace(%replace(%msg){'\t','\\\\t'}){'\n','\\\\n'}" />
+ <!-- Gather exception stack trace with no linebreaks -->
+ <property name="Exception"
+ value="%replace(%replace(%ex){'\t', '\\\\t'}){'\n','\\\\n'}" />
+
+
+ <!-- Use %nopexception to disable Logback default behavior of appending
+ %ex -->
+
+ <property name="singleLineBoreasPattern"
+ value="%nopexception${LogTimestamp}\t${Thread}\t${Level}\t${Logger}\t${Marker}\t${Mdc}\t${Message}\t${Exception}%n" />
+ <property name="multiLineBoreasPattern"
+ value="${LogTimestamp}\t${Thread}\t${Level}\t${Logger}\t${Marker}\t${Mdc}\t%msg\t%ex%n" />
+
+ <!-- Uncomment below code for filter if need to show events with level WARN
+ or above on the console (docker log) -->
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <!-- <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> <level>WARN</level>
+ </filter> -->
+ <encoder>
+ <pattern>${multiLineBoreasPattern}</pattern>
+ </encoder>
+ </appender>
+
+ <!-- Show all events in the rolling log file -->
+ <appender name="file-rolling"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/${componentName}.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <!-- daily rollover -->
+ <fileNamePattern>${logDirectory}/${componentName}.%d{yyyy-MM-dd}.log.zip
+ </fileNamePattern>
+ <!-- keep 30 days' worth of history capped at 3GB total size -->
+ <maxHistory>30</maxHistory>
+ <totalSizeCap>3GB</totalSizeCap>
+ </rollingPolicy>
+ <encoder>
+ <pattern>${singleLineBoreasPattern}</pattern>
+ </encoder>
+ </appender>
+ <appender name="file-async" class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>256</queueSize>
+ <includeCallerData>true</includeCallerData>
+ <appender-ref ref="file-rolling" />
+ </appender>
+
+ <!-- The root level is the default for all loggers, NOT a filter on any
+ appender. This level can be set with property logging.level.root=LEVEL. -->
+ <root level="INFO">
+ <appender-ref ref="file-async" />
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration>
--- /dev/null
+/*
+ ===============LICENSE_START=======================================================
+ Acumos
+ ===================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
+ ===================================================================================
+ This Acumos software file is distributed by AT&T and Tech Mahindra
+ 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
+
+ This file 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 com.example.demo;
+
+import org.acumos.demo.logging.Application;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class DemoApplicationTests {
+
+@Test
+public void contextLoads() {
+ }
+
+}