Add MDC Topic Filtering 44/83044/3
authorDaniel Cruz <dc443y@att.com>
Fri, 22 Mar 2019 13:33:29 +0000 (08:33 -0500)
committerDaniel Cruz <dc443y@att.com>
Mon, 25 Mar 2019 14:11:29 +0000 (09:11 -0500)
A feature to provide configurable properties for network topics
to extrac fields from JSON strings and place them in a mapped
diagnostic context.

Issue-ID: POLICY-1499
Change-Id: Icfca0be3b263ccf1612b79ed617e2b1ffb0317e6
Signed-off-by: Daniel Cruz <dc443y@att.com>
16 files changed:
feature-eelf/src/main/feature/config/logback-eelf.xml
feature-mdc-filters/pom.xml [new file with mode: 0755]
feature-mdc-filters/src/assembly/assemble_zip.xml [new file with mode: 0755]
feature-mdc-filters/src/main/feature/config/feature-mdc-filters.properties [new file with mode: 0755]
feature-mdc-filters/src/main/feature/install/disable [new file with mode: 0755]
feature-mdc-filters/src/main/feature/install/enable [new file with mode: 0755]
feature-mdc-filters/src/main/java/org/onap/policy/drools/mdc/filters/MdcFilterFeature.java [new file with mode: 0755]
feature-mdc-filters/src/main/java/org/onap/policy/drools/mdc/filters/MdcTopicFilter.java [new file with mode: 0755]
feature-mdc-filters/src/main/resources/META-INF/services/org.onap.policy.common.endpoints.features.NetLoggerFeatureApi [new file with mode: 0755]
feature-mdc-filters/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI [new file with mode: 0755]
feature-mdc-filters/src/test/java/org/onap/policy/drools/mdc/filters/MdcFilterFeatureTest.java [new file with mode: 0755]
feature-mdc-filters/src/test/java/org/onap/policy/drools/mdc/filters/MdcTopicFilterTest.java [new file with mode: 0755]
feature-mdc-filters/src/test/resources/onset.json [new file with mode: 0755]
packages/install/pom.xml
policy-management/src/main/server/config/logback.xml
pom.xml

index 90b7f45..c70a57a 100644 (file)
 
 <configuration scan="true" scanPeriod="60 seconds" debug="false">
 
-       <property name="errorLogName" value="error" />
-       <property name="metricsLogName" value="metrics" />
-       <property name="auditLogName" value="audit" />
-       <property name="debugLogName" value="debug" />
-       <property name="networkLogName" value="network" />
-
-       <property name="defaultPattern"
-               value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestID}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" />
-       <property name="defaultMetricPattern"
-               value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestID}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" />
-       <property name="defaultAuditPattern"
-               value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestID}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" />
-       <property name="defaultErrorPattern"
-               value="%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%X{RequestID}|%thread|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{ErrorCategory}|%X{ErrorCode}|%X{ErrorDesciption}|%msg%replace(%xException){'\n',' - '}%nopex%n" />
-               
-       <property name="networkPattern" value="[%d|%t]%m%n" />
-       <property name="debugPattern" value="[%date|%level|%logger{0}|%thread] %replace(%msg){'\n', ' '}%n" />
-
-       <property name="logDirectory" value="logs/Policy" />
-       <property name="debugLogDirectory" value="logs/Policy" />
-
-       <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
-               <encoder>
-                       <pattern>${defaultPattern}</pattern>
-               </encoder>
-       </appender>
-
-       <appender name="EELFAudit"
-               class="ch.qos.logback.core.rolling.RollingFileAppender">
-               <file>${logDirectory}/${auditLogName}.log</file>
-               <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
-                       <fileNamePattern>${logDirectory}/${auditLogName}.%i.log.zip
-                       </fileNamePattern>
-                       <minIndex>1</minIndex>
-                       <maxIndex>5</maxIndex>
-               </rollingPolicy>
-               <triggeringPolicy
-                       class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
-                       <maxFileSize>10MB</maxFileSize>
-               </triggeringPolicy>
-               <encoder>
-                       <pattern>${defaultAuditPattern}</pattern>
-               </encoder>
-       </appender>
-
-       <appender name="asyncEELFAudit" class="ch.qos.logback.classic.AsyncAppender">
-               <appender-ref ref="EELFAudit" />
-       </appender>
-
-       <appender name="EELFMetrics"
-               class="ch.qos.logback.core.rolling.RollingFileAppender">
-               <file>${logDirectory}/${metricsLogName}.log</file>
-               <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
-                       <fileNamePattern>${logDirectory}/${metricsLogName}.%i.log.zip
-                       </fileNamePattern>
-                       <minIndex>1</minIndex>
-                       <maxIndex>5</maxIndex>
-               </rollingPolicy>
-               <triggeringPolicy
-                       class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
-                       <maxFileSize>15MB</maxFileSize>
-               </triggeringPolicy>
-               <encoder>
-                       <pattern>${defaultMetricPattern}</pattern>
-               </encoder>
-       </appender>
-
-
-       <appender name="asyncEELFMetrics" class="ch.qos.logback.classic.AsyncAppender">
-               <appender-ref ref="EELFMetrics" />
-       </appender>
-
-       <appender name="EELFError"
-               class="ch.qos.logback.core.rolling.RollingFileAppender">
-               <file>${logDirectory}/${errorLogName}.log</file>
-               <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
-                       <fileNamePattern>${logDirectory}/${errorLogName}.%i.log.zip
-                       </fileNamePattern>
-                       <minIndex>1</minIndex>
-                       <maxIndex>5</maxIndex>
-               </rollingPolicy>
-               <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-                       <level>ERROR</level>
-               </filter>
-               <triggeringPolicy
-                       class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
-                       <maxFileSize>20MB</maxFileSize>
-               </triggeringPolicy>
-               <encoder>
-                       <pattern>${defaultErrorPattern}</pattern>
-               </encoder>
-       </appender>
-
-       <appender name="asyncEELFError" class="ch.qos.logback.classic.AsyncAppender">
-               <appender-ref ref="EELFError" />
-       </appender>
-
-       <appender name="EELFDebug"
-               class="ch.qos.logback.core.rolling.RollingFileAppender">
-               <file>${debugLogDirectory}/${debugLogName}.log</file>
-               <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
-                       <fileNamePattern>${debugLogDirectory}/${debugLogName}.%i.log.zip
-                       </fileNamePattern>
-                       <minIndex>1</minIndex>
-                       <maxIndex>5</maxIndex>
-               </rollingPolicy>
-               <triggeringPolicy
-                       class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
-                       <maxFileSize>20MB</maxFileSize>
-               </triggeringPolicy>
-               <encoder>
-                       <pattern>${debugPattern}</pattern>
-               </encoder>
-       </appender>
-
-       <appender name="asyncEELFDebug" class="ch.qos.logback.classic.AsyncAppender">
-               <appender-ref ref="EELFDebug" />
-       </appender>
-       
-       <appender name="NetworkOut" class="ch.qos.logback.core.rolling.RollingFileAppender">
-               <file>${logDirectory}/${networkLogName}.log</file>
-               <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
-                       <fileNamePattern>${logDirectory}/${networkLogName}.%i.log.zip
-                       </fileNamePattern>
-                       <minIndex>1</minIndex>
-                       <maxIndex>5</maxIndex>
-               </rollingPolicy>
-               <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
-                       <maxFileSize>15MB</maxFileSize>
-               </triggeringPolicy>
-               <encoder>
-                       <pattern>${networkPattern}</pattern>
-               </encoder>
-       </appender>
-       
-       <appender name="AsyncNetworkOut" class="ch.qos.logback.classic.AsyncAppender">
-               <appender-ref ref="NetworkOut" />
-       </appender>
-
-       <logger name="com.att.eelf.audit" level="info" additivity="false">
-               <appender-ref ref="asyncEELFAudit" />
-       </logger>
-
-       <logger name="com.att.eelf.metrics" level="info" additivity="false">
-               <appender-ref ref="asyncEELFMetrics" />
-       </logger>
-
-       <logger name="com.att.eelf.error" level="error" additivity="false">
-               <appender-ref ref="asyncEELFError" />
-       </logger>
-
-       <logger name="com.att.eelf.debug" level="info">
-               <appender-ref ref="asyncEELFDebug" />
-       </logger>
-
-       <logger name="network" level="INFO" additivity="false">
-               <appender-ref ref="AsyncNetworkOut" />          
-       </logger>
-       
-       <logger name="org.eclipse.jetty.server.RequestLog" level="info" additivity="false">
-               <appender-ref ref="AsyncNetworkOut" />
-       </logger>
-       
-       <root level="INFO">
-               <appender-ref ref="asyncEELFDebug" />
-               <appender-ref ref="asyncEELFError" />
-       </root>
+    <property name="errorLogName" value="error" />
+    <property name="metricsLogName" value="metrics" />
+    <property name="auditLogName" value="audit" />
+    <property name="debugLogName" value="debug" />
+    <property name="networkLogName" value="network" />
+
+    <property name="defaultPattern"
+        value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestID}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" />
+    <property name="defaultMetricPattern"
+        value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestID}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{TargetVirtualEntity}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" />
+    <property name="defaultAuditPattern"
+        value="%X{BeginTimestamp}|%X{EndTimestamp}|%X{RequestID}|%X{ServiceInstanceId}|%thread|%X{ServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}||%X{ProcessKey}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n" />
+    <property name="defaultErrorPattern"
+        value="%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%X{RequestID}|%thread|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{ErrorCategory}|%X{ErrorCode}|%X{ErrorDesciption}|%msg%replace(%xException){'\n',' - '}%nopex%n" />
+
+    <property name="networkPattern" value="[%d|%t]%m%n" />
+    <property name="abstractNetworkPattern"
+        value="[%d] [%X{networkEventType:-NULL}|%X{networkProtocol:-NULL}|%X{networkTopic:-NULL}|%X{requestID:-NULL}]%n" />
+    <property name="debugPattern" value="[%date|%level|%logger{0}|%thread] %replace(%msg){'\n', ' '}%n" />
+
+    <property name="logDirectory" value="logs/Policy" />
+    <property name="debugLogDirectory" value="logs/Policy" />
+
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>${defaultPattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="EELFAudit" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${logDirectory}/${auditLogName}.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+            <fileNamePattern>${logDirectory}/${auditLogName}.%i.log.zip
+            </fileNamePattern>
+            <minIndex>1</minIndex>
+            <maxIndex>5</maxIndex>
+        </rollingPolicy>
+        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+            <maxFileSize>10MB</maxFileSize>
+        </triggeringPolicy>
+        <encoder>
+            <pattern>${defaultAuditPattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="asyncEELFAudit" class="ch.qos.logback.classic.AsyncAppender">
+        <appender-ref ref="EELFAudit" />
+    </appender>
+
+    <appender name="EELFMetrics" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${logDirectory}/${metricsLogName}.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+            <fileNamePattern>${logDirectory}/${metricsLogName}.%i.log.zip
+            </fileNamePattern>
+            <minIndex>1</minIndex>
+            <maxIndex>5</maxIndex>
+        </rollingPolicy>
+        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+            <maxFileSize>15MB</maxFileSize>
+        </triggeringPolicy>
+        <encoder>
+            <pattern>${defaultMetricPattern}</pattern>
+        </encoder>
+    </appender>
+
+
+    <appender name="asyncEELFMetrics" class="ch.qos.logback.classic.AsyncAppender">
+        <appender-ref ref="EELFMetrics" />
+    </appender>
+
+    <appender name="EELFError" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${logDirectory}/${errorLogName}.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+            <fileNamePattern>${logDirectory}/${errorLogName}.%i.log.zip
+            </fileNamePattern>
+            <minIndex>1</minIndex>
+            <maxIndex>5</maxIndex>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>ERROR</level>
+        </filter>
+        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+            <maxFileSize>20MB</maxFileSize>
+        </triggeringPolicy>
+        <encoder>
+            <pattern>${defaultErrorPattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="asyncEELFError" class="ch.qos.logback.classic.AsyncAppender">
+        <appender-ref ref="EELFError" />
+    </appender>
+
+    <appender name="EELFDebug" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${debugLogDirectory}/${debugLogName}.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+            <fileNamePattern>${debugLogDirectory}/${debugLogName}.%i.log.zip
+            </fileNamePattern>
+            <minIndex>1</minIndex>
+            <maxIndex>5</maxIndex>
+        </rollingPolicy>
+        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+            <maxFileSize>20MB</maxFileSize>
+        </triggeringPolicy>
+        <encoder>
+            <pattern>${debugPattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="asyncEELFDebug" class="ch.qos.logback.classic.AsyncAppender">
+        <appender-ref ref="EELFDebug" />
+    </appender>
+
+    <appender name="NetworkOut" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${logDirectory}/${networkLogName}.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
+            <fileNamePattern>${logDirectory}/${networkLogName}.%i.log.zip
+            </fileNamePattern>
+            <minIndex>1</minIndex>
+            <maxIndex>5</maxIndex>
+        </rollingPolicy>
+        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
+            <maxFileSize>15MB</maxFileSize>
+        </triggeringPolicy>
+        <encoder>
+            <pattern>${networkPattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="AsyncNetworkOut" class="ch.qos.logback.classic.AsyncAppender">
+        <appender-ref ref="NetworkOut" />
+    </appender>
+
+    <logger name="com.att.eelf.audit" level="info" additivity="false">
+        <appender-ref ref="asyncEELFAudit" />
+    </logger>
+
+    <logger name="com.att.eelf.metrics" level="info" additivity="false">
+        <appender-ref ref="asyncEELFMetrics" />
+    </logger>
+
+    <logger name="com.att.eelf.error" level="error" additivity="false">
+        <appender-ref ref="asyncEELFError" />
+    </logger>
+
+    <logger name="com.att.eelf.debug" level="info">
+        <appender-ref ref="asyncEELFDebug" />
+    </logger>
+
+    <logger name="network" level="INFO" additivity="false">
+        <appender-ref ref="AsyncNetworkOut" />
+    </logger>
+
+    <logger name="org.eclipse.jetty.server.RequestLog" level="info" additivity="false">
+        <appender-ref ref="AsyncNetworkOut" />
+    </logger>
+
+    <root level="INFO">
+        <appender-ref ref="asyncEELFDebug" />
+        <appender-ref ref="asyncEELFError" />
+    </root>
 
 </configuration>
diff --git a/feature-mdc-filters/pom.xml b/feature-mdc-filters/pom.xml
new file mode 100755 (executable)
index 0000000..6ea654b
--- /dev/null
@@ -0,0 +1,119 @@
+<!--\r
+  ============LICENSE_START=======================================================\r
+  feature-mdc-filters\r
+  ================================================================================\r
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.\r
+  ================================================================================\r
+  Licensed under the Apache License, Version 2.0 (the "License");\r
+  you may not use this file except in compliance with the License.\r
+  You may obtain a copy of the License at\r
+  \r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+  \r
+  Unless required by applicable law or agreed to in writing, software\r
+  distributed under the License is distributed on an "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+  See the License for the specific language governing permissions and\r
+  limitations under the License.\r
+  ============LICENSE_END=========================================================\r
+  -->\r
+\r
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
+    <modelVersion>4.0.0</modelVersion>\r
+    <parent>\r
+        <artifactId>drools-pdp</artifactId>\r
+        <groupId>org.onap.policy.drools-pdp</groupId>\r
+        <version>1.4.0-SNAPSHOT</version>\r
+    </parent>\r
+\r
+    <artifactId>feature-mdc-filters</artifactId>\r
+\r
+    <name>feature-mdc-filters</name>\r
+    <description>Loadable module that marks key fields in messages through logback mdc.</description>\r
+\r
+    <properties>\r
+        <maven.compiler.source>1.8</maven.compiler.source>\r
+        <maven.compiler.target>1.8</maven.compiler.target>\r
+    </properties>\r
+\r
+    <build>\r
+        <plugins>\r
+            <plugin>\r
+                <artifactId>maven-assembly-plugin</artifactId>\r
+                <executions>\r
+                    <execution>\r
+                        <id>zipfile</id>\r
+                        <goals>\r
+                            <goal>single</goal>\r
+                        </goals>\r
+                        <phase>package</phase>\r
+                        <configuration>\r
+                            <attach>true</attach>\r
+                            <finalName>${project.artifactId}-${project.version}</finalName>\r
+                            <descriptors>\r
+                                <descriptor>src/assembly/assemble_zip.xml</descriptor>\r
+                            </descriptors>\r
+                            <appendAssemblyId>false</appendAssemblyId>\r
+                        </configuration>\r
+                    </execution>\r
+                </executions>\r
+            </plugin>\r
+            <plugin>\r
+                <groupId>org.apache.maven.plugins</groupId>\r
+                <artifactId>maven-dependency-plugin</artifactId>\r
+                <executions>\r
+                    <execution>\r
+                        <id>copy-dependencies</id>\r
+                        <goals>\r
+                            <goal>copy-dependencies</goal>\r
+                        </goals>\r
+                        <phase>prepare-package</phase>\r
+                        <configuration>\r
+                            <outputDirectory>${project.build.directory}/assembly/lib</outputDirectory>\r
+                            <overWriteReleases>false</overWriteReleases>\r
+                            <overWriteSnapshots>true</overWriteSnapshots>\r
+                            <overWriteIfNewer>true</overWriteIfNewer>\r
+                            <useRepositoryLayout>false</useRepositoryLayout>\r
+                            <addParentPoms>false</addParentPoms>\r
+                            <copyPom>false</copyPom>\r
+                            <includeScope>runtime</includeScope>\r
+                            <excludeTransitive>true</excludeTransitive>\r
+                        </configuration>\r
+                    </execution>\r
+                </executions>\r
+            </plugin>\r
+        </plugins>\r
+    </build>\r
+\r
+    <dependencies>\r
+        \r
+        <dependency>\r
+            <groupId>org.onap.policy.common</groupId>\r
+            <artifactId>policy-endpoints</artifactId>\r
+            <version>${policy.common.version}</version>\r
+            <scope>provided</scope>\r
+        </dependency>\r
+        \r
+        <dependency>\r
+            <groupId>org.onap.policy.drools-pdp</groupId>\r
+            <artifactId>policy-management</artifactId>\r
+            <version>${project.version}</version>\r
+            <scope>provided</scope>\r
+        </dependency>\r
+        \r
+        <dependency>\r
+            <groupId>org.mockito</groupId>\r
+            <artifactId>mockito-core</artifactId>\r
+            <version>2.13.0</version>\r
+            <scope>test</scope>\r
+        </dependency>\r
+        \r
+        <dependency>\r
+            <groupId>junit</groupId>\r
+            <artifactId>junit</artifactId>\r
+            <scope>test</scope>\r
+        </dependency>\r
+    \r
+    </dependencies>\r
+</project>\r
diff --git a/feature-mdc-filters/src/assembly/assemble_zip.xml b/feature-mdc-filters/src/assembly/assemble_zip.xml
new file mode 100755 (executable)
index 0000000..c85bbe5
--- /dev/null
@@ -0,0 +1,55 @@
+<!--\r
+  ============LICENSE_START=======================================================\r
+  feature-mdc-filters\r
+  ================================================================================\r
+  Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.\r
+  ================================================================================\r
+  Licensed under the Apache License, Version 2.0 (the "License");\r
+  you may not use this file except in compliance with the License.\r
+  You may obtain a copy of the License at\r
+  \r
+       http://www.apache.org/licenses/LICENSE-2.0\r
+  \r
+  Unless required by applicable law or agreed to in writing, software\r
+  distributed under the License is distributed on an "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+  See the License for the specific language governing permissions and\r
+  limitations under the License.\r
+  ============LICENSE_END=========================================================\r
+  -->\r
+\r
+<!-- Defines how we build the .zip file which is our distribution. -->\r
+\r
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"\r
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">\r
+    <id>feature-mdc-filters</id>\r
+    <formats>\r
+        <format>zip</format>\r
+    </formats>\r
+\r
+    <includeBaseDirectory>false</includeBaseDirectory>\r
+\r
+    <fileSets>\r
+        <fileSet>\r
+            <directory>target</directory>\r
+            <outputDirectory>lib/feature</outputDirectory>\r
+            <includes>\r
+                <include>feature-mdc-filters-${project.version}.jar</include>\r
+            </includes>\r
+        </fileSet>\r
+        <fileSet>\r
+            <directory>src/main/feature/config</directory>\r
+            <outputDirectory>config</outputDirectory>\r
+            <fileMode>0644</fileMode>\r
+            <excludes />\r
+        </fileSet>\r
+        <fileSet>\r
+            <directory>src/main/feature/install</directory>\r
+            <outputDirectory>install</outputDirectory>\r
+            <fileMode>0744</fileMode>\r
+            <excludes />\r
+        </fileSet>\r
+    </fileSets>\r
+\r
+</assembly>\r
diff --git a/feature-mdc-filters/src/main/feature/config/feature-mdc-filters.properties b/feature-mdc-filters/src/main/feature/config/feature-mdc-filters.properties
new file mode 100755 (executable)
index 0000000..0a53a9f
--- /dev/null
@@ -0,0 +1,54 @@
+###\r
+# ============LICENSE_START=======================================================\r
+# feature-mdc-filters\r
+# ================================================================================\r
+# Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.\r
+# ================================================================================\r
+# Licensed under the Apache License, Version 2.0 (the "License");\r
+# you may not use this file except in compliance with the License.\r
+# You may obtain a copy of the License at\r
+# \r
+#      http://www.apache.org/licenses/LICENSE-2.0\r
+# \r
+# Unless required by applicable law or agreed to in writing, software\r
+# distributed under the License is distributed on an "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+# See the License for the specific language governing permissions and\r
+# limitations under the License.\r
+# ============LICENSE_END=========================================================\r
+###\r
+\r
+# The properties keys follow the controller topic configurations followed by a\r
+# a new topic property, 'mdcFilters'.\r
+#<protocol>.<type>.topics.<topic-name>.mdcFilters\r
+\r
+# The value of the property is broken down to the MDC key name to be used by the \r
+# feature followed by the path(s) to the desired field's value.\r
+#dmaap.sink.topics.example.mdcFilters=sampleKey=$.path.to.sample.key\r
+\r
+# The path always begins with '$' as this signifies the root of the JSON document.\r
+# The underlying library used is Jayway JsonPath. The library's query syntax is \r
+# supported for searching a JSON document. The query syntax and some examples \r
+# can be found at: https://github.com/json-path/JsonPath\r
+\r
+# Multiple fields can be found for a given JSON document by a comma separated list\r
+# of <mdcKey,jsonPath> pairs.\r
+#dmaap.sink.topics.example.mdcFilters=field1=$.field1,field2=$.field2\r
+\r
+# If a given topic supports multiple message types that have fields with the same\r
+# name, a '|' separated list can define multiple paths to a field. The feature\r
+# will loop through each path until it finds a match and returns it.\r
+#dmaap.sink.topics.example.mdcFilters=field1=$.field1|$.body.field1\r
+\r
+# dmaap source filters\r
+dmaap.source.topics.PDPD-CONFIGURATION.mdcFilters=requestID=$.requestID\r
+dmaap.source.topics.DCAE_TOPIC.mdcFilters=requestID=$.requestID\r
+dmaap.source.topics.APPC-CL.mdcFilters=requestID=$.CommonHeader.RequestID\r
+dmaap.source.topics.APPC-LCM-WRITE.mdcFilters=requestID=$.body.output.common-header.request-id\r
+dmaap.source.topics.SDNR-CL-RSP.mdcFilters=requestID=$.body.CommonHeader.RequestID\r
+\r
+# dmaap sink filters\r
+dmaap.sink.topics.POLICY-CL-MGT.mdcFilters=requestID=$.requestID\r
+dmaap.sink.topics.APPC-CL.mdcFilters=requestID=$.CommonHeader.RequestID\r
+dmaap.sink.topics.APPC-LCM-READ.mdcFilters=requestID=$.body.input.common-header.request-id\r
+dmaap.sink.topics.SDNR-CL.mdcFilters=requestID=$.body.CommonHeader.RequestID\r
diff --git a/feature-mdc-filters/src/main/feature/install/disable b/feature-mdc-filters/src/main/feature/install/disable
new file mode 100755 (executable)
index 0000000..25d5737
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# feature-mdc-filters
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. 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=========================================================
+##
+
+if [[ "${DEBUG}" == "y" ]]; then
+    set -x
+fi
+
+CONFIG_DIR="${POLICY_HOME}"/config
+for mainConfig in ${CONFIG_DIR}/logback.xml ${CONFIG_DIR}/logback-eelf.xml; do
+    if [ -e "${mainConfig}" ]; then
+        sed -i --follow-symlinks 's/${abstractNetworkPattern}/${networkPattern}/' "${mainConfig}"
+    fi
+done
diff --git a/feature-mdc-filters/src/main/feature/install/enable b/feature-mdc-filters/src/main/feature/install/enable
new file mode 100755 (executable)
index 0000000..57c7cc4
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# feature-mdc-filters
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. 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=========================================================
+##
+
+if [[ "${DEBUG}" == "y" ]]; then
+    set -x
+fi
+
+CONFIG_DIR="${POLICY_HOME}"/config
+for mainConfig in ${CONFIG_DIR}/logback.xml ${CONFIG_DIR}/logback-eelf.xml; do
+    if [ -e "${mainConfig}" ]; then
+        sed -i --follow-symlinks 's/${networkPattern}/${abstractNetworkPattern}/' "${mainConfig}"
+    fi
+done
diff --git a/feature-mdc-filters/src/main/java/org/onap/policy/drools/mdc/filters/MdcFilterFeature.java b/feature-mdc-filters/src/main/java/org/onap/policy/drools/mdc/filters/MdcFilterFeature.java
new file mode 100755 (executable)
index 0000000..369c0aa
--- /dev/null
@@ -0,0 +1,201 @@
+/*\r
+ * ============LICENSE_START=======================================================\r
+ * feature-mdc-filters\r
+ * ================================================================================\r
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.\r
+ * ================================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * ============LICENSE_END=========================================================\r
+ */\r
+\r
+package org.onap.policy.drools.mdc.filters;\r
+\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Properties;\r
+import org.onap.policy.common.endpoints.event.comm.Topic;\r
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;\r
+import org.onap.policy.common.endpoints.features.NetLoggerFeatureApi;\r
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;\r
+import org.onap.policy.drools.features.PolicyControllerFeatureAPI;\r
+import org.onap.policy.drools.persistence.SystemPersistence;\r
+import org.onap.policy.drools.system.PolicyController;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.slf4j.MDC;\r
+\r
+public class MdcFilterFeature implements NetLoggerFeatureApi, PolicyControllerFeatureAPI {\r
+\r
+    /**\r
+     * Logger.\r
+     */\r
+    private static final Logger logger = LoggerFactory.getLogger(MdcFilterFeature.class);\r
+\r
+    /**\r
+     * Feature properties.\r
+     */\r
+    public static final String FEATURE_NAME = "feature-mdc-filters";\r
+    public static final String SOURCE = "source";\r
+    public static final String SINK = "sink";\r
+    public static final String MDC_FILTERS = ".mdcFilters";\r
+\r
+    /**\r
+     * Mapping of 'protocol:type:topic' key to a 'MdcTopicFilter' object.\r
+     */\r
+    private Map<String, MdcTopicFilter> topicFilters = new HashMap<>();\r
+\r
+    /**\r
+     * Feature properties map obtained from the feature properties file.\r
+     */\r
+    private Properties featureProps = null;\r
+\r
+    /**\r
+     * Constructor.\r
+     */\r
+    public MdcFilterFeature() {\r
+        super();\r
+        featureProps = getFeatureProps();\r
+    }\r
+\r
+    /**\r
+     * Gets the feature properties.\r
+     *\r
+     * @return the properties for this feature.\r
+     */\r
+    protected Properties getFeatureProps() {\r
+        return SystemPersistence.manager.getProperties(FEATURE_NAME);\r
+    }\r
+\r
+    /**\r
+     * Sequence number to be used for order of feature implementer execution.\r
+     */\r
+    @Override\r
+    public int getSequenceNumber() {\r
+        return 1;\r
+    }\r
+\r
+    /**\r
+     * Loops through all source and sink topics to find which topics have mdc filters and\r
+     * inserts an MdcTopicFilter in to the topicFilters map.\r
+     */\r
+    @Override\r
+    public boolean afterCreate(PolicyController controller) {\r
+        createSourceTopicFilters(controller);\r
+        createSinkTopicFilters(controller);\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Extracts the fields in a JSON string that are to be logged in an abbreviated\r
+     * message. The event delivery infrastructure details are put in the MDC as well using\r
+     * the keys networkEventType (IN/OUT), networkProtocol (UEB/DMAAP/NOOP/REST), and\r
+     * networkTopic.\r
+     */\r
+    @Override\r
+    public boolean beforeLog(Logger eventLogger, EventType type, CommInfrastructure protocol, String topic,\r
+                    String message) {\r
+\r
+        String filterKey = null;\r
+        if (type == EventType.IN) {\r
+            filterKey = getTopicKey(protocol.name().toLowerCase(), SOURCE, topic);\r
+        } else {\r
+            filterKey = getTopicKey(protocol.name().toLowerCase(), SINK, topic);\r
+        }\r
+\r
+        MDC.put("networkEventType", type.name());\r
+        MDC.put("networkProtocol", protocol.name());\r
+        MDC.put("networkTopic", topic);\r
+\r
+        MdcTopicFilter filter = topicFilters.get(filterKey);\r
+        if (filter != null) {\r
+            for (Map.Entry<String, List<String>> entry : filter.find(message).entrySet()) {\r
+                String mdcKey = entry.getKey();\r
+                List<String> results = entry.getValue();\r
+                if (results.isEmpty()) {\r
+                    logger.debug("No results found for key {}", mdcKey);\r
+                } else if (results.size() > 1) {\r
+                    logger.debug("Multple results found for key {}, returning list as a string", mdcKey);\r
+                    MDC.put(mdcKey, results.toString());\r
+                } else {\r
+                    MDC.put(mdcKey, results.get(0));\r
+                }\r
+            }\r
+        } else {\r
+            logger.debug("No mdc topic filters exist for key {}", filterKey);\r
+        }\r
+\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Clears the MDC mapping after a message is logged.\r
+     */\r
+    @Override\r
+    public boolean afterLog(Logger eventLogger, EventType type, CommInfrastructure protocol, String topic,\r
+                    String message) {\r
+        MDC.clear();\r
+        return false;\r
+    }\r
+\r
+    /**\r
+     * Creates a key using the protocol, type, and topic name.\r
+     *\r
+     * @param protocol defined as ueb, dmaap, noop\r
+     * @param type defined as source or sink\r
+     * @param topic name of the topic\r
+     * @return a key that is the concatenation of the protocol, type, and topic name\r
+     */\r
+    private String getTopicKey(String protocol, String type, String topic) {\r
+        return protocol + ":" + type + ":" + topic;\r
+    }\r
+\r
+    /**\r
+     * Creates MdcTopicFilters for a source/sink topic based on the type.\r
+     *\r
+     * @param topic the topic name\r
+     * @param type 'source' or 'sink'\r
+     */\r
+    private void createTopicFilter(Topic topic, String type) {\r
+        String protocol = topic.getTopicCommInfrastructure().name().toLowerCase();\r
+        String topicName = topic.getTopic();\r
+\r
+        String propertyKey = protocol + "." + type + ".topics." + topicName + MDC_FILTERS;\r
+        String propertyValue = featureProps.getProperty(propertyKey);\r
+        if (propertyValue != null) {\r
+            String topicKey = getTopicKey(protocol, type, topicName);\r
+            if (!topicFilters.containsKey(topicKey)) {\r
+                logger.debug("MdcTopicFilter created for {} {} topic {}", protocol, type, topicName);\r
+                topicFilters.put(topicKey, new MdcTopicFilter(propertyValue));\r
+            } else {\r
+                logger.debug("An MdcTopicFilter already exists for key {}", topicKey);\r
+            }\r
+        } else {\r
+            logger.debug("No MDC filters defined for {} {} topic {}", protocol, type, topicName);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Creates MdcTopicFilters for the controller's source topics.\r
+     */\r
+    private void createSourceTopicFilters(PolicyController controller) {\r
+        controller.getTopicSources().forEach(sourceTopic -> createTopicFilter(sourceTopic, SOURCE));\r
+    }\r
+\r
+    /**\r
+     * Creates MdcTopicFilters for the controller's sink topics.\r
+     */\r
+    private void createSinkTopicFilters(PolicyController controller) {\r
+        controller.getTopicSinks().forEach(sinkTopic -> createTopicFilter(sinkTopic, SINK));\r
+    }\r
+}\r
diff --git a/feature-mdc-filters/src/main/java/org/onap/policy/drools/mdc/filters/MdcTopicFilter.java b/feature-mdc-filters/src/main/java/org/onap/policy/drools/mdc/filters/MdcTopicFilter.java
new file mode 100755 (executable)
index 0000000..d0813a9
--- /dev/null
@@ -0,0 +1,337 @@
+/*\r
+ * ============LICENSE_START=======================================================\r
+ * feature-mdc-filters\r
+ * ================================================================================\r
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.\r
+ * ================================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * ============LICENSE_END=========================================================\r
+ */\r
+\r
+package org.onap.policy.drools.mdc.filters;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.HashMap;\r
+import java.util.List;\r
+import java.util.Map;\r
+import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+public class MdcTopicFilter {\r
+\r
+    private static final Logger logger = LoggerFactory.getLogger(MdcTopicFilter.class);\r
+\r
+    public static final String MDC_KEY_ERROR = "mdcKey must be provided";\r
+    public static final String JSON_PATH_ERROR = "json path(s) must be provided";\r
+\r
+    private Map<String, FilterRule> rules = new HashMap<>();\r
+\r
+    public static class FilterRule {\r
+        private String mdcKey;\r
+        private List<String> paths;\r
+\r
+        public FilterRule(String mdcKey, String path) {\r
+            this.mdcKey = mdcKey;\r
+            this.paths = Arrays.asList(path);\r
+        }\r
+\r
+        /**\r
+         * Constructor.\r
+         *\r
+         * @param mdcKey the key to the filter rule\r
+         * @param paths the list of potential paths to the key\r
+         */\r
+        public FilterRule(String mdcKey, List<String> paths) {\r
+            this.mdcKey = mdcKey;\r
+            this.paths = paths;\r
+        }\r
+\r
+        public String getMdcKey() {\r
+            return mdcKey;\r
+        }\r
+\r
+        public List<String> getPaths() {\r
+            return paths;\r
+        }\r
+\r
+        protected void setMdcKey(String mdcKey) {\r
+            if (mdcKey == null || mdcKey.isEmpty()) {\r
+                throw new IllegalArgumentException(MDC_KEY_ERROR);\r
+            }\r
+            this.mdcKey = mdcKey;\r
+        }\r
+\r
+        protected void setPaths(List<String> paths) {\r
+            if (paths == null || paths.isEmpty()) {\r
+                throw new IllegalArgumentException(JSON_PATH_ERROR);\r
+            }\r
+            this.paths = paths;\r
+        }\r
+\r
+        protected void addPaths(List<String> paths) {\r
+            if (paths == null || paths.isEmpty()) {\r
+                throw new IllegalArgumentException(JSON_PATH_ERROR);\r
+            }\r
+            this.paths.addAll(paths);\r
+        }\r
+\r
+        protected void addPath(String path) {\r
+            if (path == null || path.isEmpty()) {\r
+                throw new IllegalArgumentException(JSON_PATH_ERROR);\r
+            }\r
+            this.paths.add(path);\r
+        }\r
+    }\r
+\r
+    protected MdcTopicFilter(String rawFilters) {\r
+        for (String filter : rawFilters.split("\\s*,\\s*")) {\r
+            FilterRule rule = createFilterRule(filter);\r
+            rules.put(rule.mdcKey, rule);\r
+        }\r
+    }\r
+\r
+    private FilterRule createFilterRule(String filter) {\r
+        String[] filterKeyPaths = filter.split("\\s*=\\s*");\r
+        if (filterKeyPaths.length != 2) {\r
+            throw new IllegalArgumentException("could not parse filter rule");\r
+        }\r
+\r
+        String filterKey = filterKeyPaths[0];\r
+        String paths = filterKeyPaths[1];\r
+        List<String> filterPaths = new ArrayList<>(Arrays.asList(paths.split("(?<!\\|)\\|(?!\\|)")));\r
+        return new FilterRule(filterKey, filterPaths);\r
+    }\r
+\r
+    /**\r
+     * Gets all the filter rules for the topic.\r
+     *\r
+     * @return an array list of the rules for the topic\r
+     */\r
+    protected List<FilterRule> getFilterRule() {\r
+        return new ArrayList<>(rules.values());\r
+    }\r
+\r
+    /**\r
+     * Gets the filter rule for the specified key.\r
+     *\r
+     * @param mdcKey the key to the filter rule\r
+     * @return the filter rule associated with the key\r
+     */\r
+    protected FilterRule getFilterRule(String mdcKey) {\r
+        if (mdcKey == null || mdcKey.isEmpty()) {\r
+            throw new IllegalArgumentException(MDC_KEY_ERROR);\r
+        }\r
+        return rules.get(mdcKey);\r
+    }\r
+\r
+    /**\r
+     * Adds a filter rule for the specified key and path.\r
+     *\r
+     * @param mdcKey the key to the filter rule\r
+     * @param path the json path to the key\r
+     * @return the filter rule that was added for the topic\r
+     */\r
+    protected FilterRule addFilterRule(String mdcKey, String path) {\r
+        if (path == null || path.isEmpty()) {\r
+            throw new IllegalArgumentException(JSON_PATH_ERROR);\r
+        }\r
+        return addFilterRule(mdcKey, Arrays.asList(path));\r
+    }\r
+\r
+    /**\r
+     * Adds a filter rule for the specified key and paths.\r
+     *\r
+     * @param mdcKey the key to the filter rule\r
+     * @param paths the list of potential paths to the key\r
+     * @return the filter rule that was added for the topic\r
+     */\r
+    protected FilterRule addFilterRule(String mdcKey, List<String> paths) {\r
+        if (mdcKey == null || mdcKey.isEmpty()) {\r
+            throw new IllegalArgumentException(MDC_KEY_ERROR);\r
+        }\r
+\r
+        if (paths == null || paths.isEmpty()) {\r
+            throw new IllegalArgumentException(JSON_PATH_ERROR);\r
+        }\r
+\r
+        if (rules.containsKey(mdcKey)) {\r
+            throw new IllegalArgumentException("a filter rule already exists for key: " + mdcKey);\r
+        }\r
+\r
+        FilterRule rule = new FilterRule(mdcKey, paths);\r
+        rules.put(mdcKey, rule);\r
+        return rule;\r
+    }\r
+\r
+    /**\r
+     * Modifies an existing filter rule by adding the specified path.\r
+     *\r
+     * @param mdcKey the key to the filter rule\r
+     * @param path the path to the key\r
+     * @return the filter rule that was modified\r
+     */\r
+    protected FilterRule modifyFilterRule(String mdcKey, String path) {\r
+        if (path == null || path.isEmpty()) {\r
+            throw new IllegalArgumentException(JSON_PATH_ERROR);\r
+        }\r
+        return modifyFilterRule(mdcKey, Arrays.asList(path));\r
+    }\r
+\r
+    /**\r
+     * Modifies an existing filter rule by adding the specified paths.\r
+     *\r
+     * @param mdcKey the key to the filter rule\r
+     * @param paths the list of potential paths to the key\r
+     * @return the filter rule that was modified\r
+     */\r
+    protected FilterRule modifyFilterRule(String mdcKey, List<String> paths) {\r
+        if (mdcKey == null || mdcKey.isEmpty()) {\r
+            throw new IllegalArgumentException(MDC_KEY_ERROR);\r
+        }\r
+\r
+        if (paths == null || paths.isEmpty()) {\r
+            throw new IllegalArgumentException(JSON_PATH_ERROR);\r
+        }\r
+\r
+        if (!rules.containsKey(mdcKey)) {\r
+            throw new IllegalArgumentException("a filter rule doesn't exist for key: " + mdcKey);\r
+        }\r
+\r
+        FilterRule rule = rules.get(mdcKey);\r
+        rule.addPaths(paths);\r
+        return rule;\r
+    }\r
+\r
+    /**\r
+     * Modifies an existing filter rule's key and replaces the paths with the specified\r
+     * paths.\r
+     *\r
+     * @param oldMdcKey the old key to the filter rule\r
+     * @param newMdcKey the new key to the filter rule\r
+     * @param paths the list of potential paths to the key\r
+     * @return the filter rule that was modified\r
+     */\r
+    protected FilterRule modifyFilterRule(String oldMdcKey, String newMdcKey, List<String> paths) {\r
+        if (oldMdcKey == null || oldMdcKey.isEmpty()) {\r
+            throw new IllegalArgumentException("current mdcKey must be provided");\r
+        }\r
+\r
+        if (newMdcKey == null || newMdcKey.isEmpty()) {\r
+            throw new IllegalArgumentException("new mdcKey must be provided");\r
+        }\r
+\r
+        if (oldMdcKey.equals(newMdcKey)) {\r
+            throw new IllegalArgumentException("the old and new mdcKey are equivalent");\r
+        }\r
+        if (paths == null || paths.isEmpty()) {\r
+            throw new IllegalArgumentException(JSON_PATH_ERROR);\r
+        }\r
+\r
+        if (rules.containsKey(newMdcKey)) {\r
+            throw new IllegalArgumentException("a filter rule already exists for key: " + newMdcKey);\r
+        }\r
+\r
+        FilterRule rule = rules.remove(oldMdcKey);\r
+        if (rule == null) {\r
+            throw new IllegalArgumentException("a filter rule doesn't exist for key: " + oldMdcKey);\r
+        }\r
+\r
+        rule.setMdcKey(newMdcKey);\r
+        rule.setPaths(paths);\r
+        rules.put(newMdcKey, rule);\r
+        return rule;\r
+    }\r
+\r
+    /**\r
+     * Deletes all filter rules for the topic filter.\r
+     */\r
+    protected void deleteFilterRule() {\r
+        rules.clear();\r
+    }\r
+\r
+    /**\r
+     * Deletes an existing filter rule.\r
+     *\r
+     * @param mdcKey the key to the filter rule\r
+     * @return the filter rule that was deleted\r
+     */\r
+    protected FilterRule deleteFilterRule(String mdcKey) {\r
+        if (mdcKey == null || mdcKey.isEmpty()) {\r
+            throw new IllegalArgumentException(MDC_KEY_ERROR);\r
+        }\r
+        return rules.remove(mdcKey);\r
+    }\r
+\r
+    /**\r
+     * Finds all fields for each topic filter rule. The results are stored in a map that\r
+     * is indexed by the MDC key. Each MDC key has a list of results as multiple\r
+     * occurrences of a key can be found in a JSON document.\r
+     *\r
+     * @param json the json string to be parsed\r
+     * @return a map of mdc keys and list of results for each key\r
+     */\r
+    protected Map<String, List<String>> find(String json) {\r
+        Map<String, List<String>> results = new HashMap<>();\r
+        for (FilterRule rule : rules.values()) {\r
+            List<String> matches = new ArrayList<>();\r
+            for (String path : rule.getPaths()) {\r
+\r
+                try {\r
+                    matches = JsonProtocolFilter.filter(json, path);\r
+                } catch (Exception e) {\r
+                    logger.debug("Could not filter on path {} because of {}", path, e.getMessage(), e);\r
+                }\r
+\r
+                if (!matches.isEmpty()) {\r
+                    break;\r
+                } else {\r
+                    logger.error("Could not find path {} in json {}", path, json);\r
+                }\r
+\r
+            }\r
+            results.put(rule.getMdcKey(), matches);\r
+        }\r
+        return results;\r
+    }\r
+\r
+    /**\r
+     * Finds all occurrences of a field in a JSON document based on the filter rule paths.\r
+     *\r
+     * @param json the json string to be parsed\r
+     * @return a list of matches from the JSON document\r
+     */\r
+    protected List<String> find(String json, String mdcKey) {\r
+        List<String> matches = new ArrayList<>();\r
+        for (String path : rules.get(mdcKey).getPaths()) {\r
+\r
+            try {\r
+                matches = JsonProtocolFilter.filter(json, path);\r
+            } catch (Exception e) {\r
+                logger.debug("Could not filter on path {} because of {}", path, e.getMessage(), e);\r
+            }\r
+\r
+            if (!matches.isEmpty()) {\r
+                break;\r
+            }\r
+\r
+        }\r
+\r
+        if (matches.isEmpty()) {\r
+            logger.error("Could not find any matches for key {} in json {}", mdcKey, json);\r
+        }\r
+\r
+        return matches;\r
+    }\r
+}\r
diff --git a/feature-mdc-filters/src/main/resources/META-INF/services/org.onap.policy.common.endpoints.features.NetLoggerFeatureApi b/feature-mdc-filters/src/main/resources/META-INF/services/org.onap.policy.common.endpoints.features.NetLoggerFeatureApi
new file mode 100755 (executable)
index 0000000..f2fdb40
--- /dev/null
@@ -0,0 +1 @@
+org.onap.policy.drools.mdc.filters.MdcFilterFeature\r
diff --git a/feature-mdc-filters/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI b/feature-mdc-filters/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureAPI
new file mode 100755 (executable)
index 0000000..f2fdb40
--- /dev/null
@@ -0,0 +1 @@
+org.onap.policy.drools.mdc.filters.MdcFilterFeature\r
diff --git a/feature-mdc-filters/src/test/java/org/onap/policy/drools/mdc/filters/MdcFilterFeatureTest.java b/feature-mdc-filters/src/test/java/org/onap/policy/drools/mdc/filters/MdcFilterFeatureTest.java
new file mode 100755 (executable)
index 0000000..afe6df3
--- /dev/null
@@ -0,0 +1,170 @@
+/*\r
+ * ============LICENSE_START=======================================================\r
+ * feature-mdc-filters\r
+ * ================================================================================\r
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.\r
+ * ================================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * ============LICENSE_END=========================================================\r
+ */\r
+\r
+package org.onap.policy.drools.mdc.filters;\r
+\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertNotNull;\r
+import static org.junit.Assert.assertNull;\r
+import static org.mockito.Mockito.doReturn;\r
+import static org.mockito.Mockito.mock;\r
+\r
+import java.io.IOException;\r
+import java.nio.file.Files;\r
+import java.nio.file.Paths;\r
+import java.util.List;\r
+import java.util.Properties;\r
+\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;\r
+import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;\r
+import org.onap.policy.common.endpoints.event.comm.TopicSink;\r
+import org.onap.policy.common.endpoints.event.comm.TopicSource;\r
+import org.onap.policy.common.endpoints.utils.NetLoggerUtil.EventType;\r
+import org.onap.policy.drools.system.PolicyController;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.slf4j.MDC;\r
+\r
+public class MdcFilterFeatureTest {\r
+\r
+    /**\r
+     * Logger.\r
+     */\r
+    private static final Logger logger = LoggerFactory.getLogger(MdcFilterFeatureTest.class);\r
+\r
+    /**\r
+     * Test topic names for mdc topic filters.\r
+     */\r
+    private static final String TEST_TOPIC_A = "org.onap.policy.test-topic-a";\r
+    private static final String TEST_TOPIC_B = "org.onap.policy.test-topic-b";\r
+\r
+    /**\r
+     * The mock PolicyController to be used for the junits.\r
+     */\r
+    private PolicyController controller;\r
+\r
+    /**\r
+     * The mock properties to be used for the junits.\r
+     */\r
+    private Properties props;\r
+\r
+    /**\r
+     * An instance of the MdcFilterFeature.\r
+     */\r
+    private MdcFilterFeature mdcFilterFeature;\r
+\r
+    /**\r
+     * Sample json string to be logged.\r
+     */\r
+    private String message;\r
+\r
+    /**\r
+     * Setup.\r
+     * @throws IOException thrown if onset.json file could not be read\r
+     */\r
+    @Before\r
+    public void setUp() throws IOException {\r
+        message = new String(Files.readAllBytes(Paths.get("src/test/resources/onset.json")));\r
+\r
+        props = mockFeatureProperties();\r
+        controller = mock(PolicyController.class);\r
+\r
+        props.setProperty("dmaap.source.topics", TEST_TOPIC_A);\r
+        props.setProperty("dmaap.source.topics." + TEST_TOPIC_A + ".servers", "http://testing123.com/");\r
+        props.setProperty("noop.sink.topics", TEST_TOPIC_B);\r
+\r
+        List<TopicSource> topicSources = TopicEndpoint.manager.addTopicSources(props);\r
+        doReturn(topicSources).when(controller).getTopicSources();\r
+\r
+        List<TopicSink> topicSinks = TopicEndpoint.manager.addTopicSinks(props);\r
+        doReturn(topicSinks).when(controller).getTopicSinks();\r
+\r
+        mdcFilterFeature = new MdcFilterFeatureImpl();\r
+        mdcFilterFeature.afterCreate(controller);\r
+    }\r
+\r
+    /**\r
+     * Tests extracting fields from a JSON message and place them in the MDC and\r
+     * then clearing the MDC.\r
+     */\r
+    @Test\r
+    public void mdcLogTest() {\r
+        mdcFilterFeature.beforeLog(logger, EventType.IN,\r
+                CommInfrastructure.DMAAP, TEST_TOPIC_A, message);\r
+\r
+        assertEquals("8c1b8bd8-06f7-493f-8ed7-daaa4cc481bc", MDC.get("requestID"));\r
+        assertEquals("CL-TEST", MDC.get("closedLoopControlName"));\r
+\r
+        assertNotNull(MDC.getCopyOfContextMap());\r
+\r
+        mdcFilterFeature.afterLog(logger, EventType.IN,\r
+                CommInfrastructure.DMAAP, TEST_TOPIC_A, message);\r
+\r
+        assertNull(MDC.getCopyOfContextMap());\r
+    }\r
+\r
+    /**\r
+     * Tests that the feature does not search for fields in a JSON message\r
+     * if there is not an MdcTopicFilter object for the generated key.\r
+     */\r
+    @Test\r
+    public void noTopicFilterTest() {\r
+        mdcFilterFeature.beforeLog(logger, EventType.OUT,\r
+                CommInfrastructure.NOOP, "no-topic", message);\r
+\r
+        assertEquals("OUT", MDC.get("networkEventType"));\r
+        assertEquals("NOOP", MDC.get("networkProtocol"));\r
+        assertEquals("no-topic", MDC.get("networkTopic"));\r
+        assertNull(MDC.get("requestID"));\r
+    }\r
+\r
+    /**\r
+     * Creates a simple properties map containing an mdc filter for a test\r
+     * topic.\r
+     *\r
+     * @return a properties map with mdc filter properties.\r
+     */\r
+    private Properties mockFeatureProperties() {\r
+        Properties props = new Properties();\r
+\r
+        String key = "dmaap.source.topics." + TEST_TOPIC_A + ".mdcFilters";\r
+        String value = "requestID=$.requestID,closedLoopControlName=$.closedLoopControlName";\r
+        props.setProperty(key, value);\r
+\r
+        return props;\r
+    }\r
+\r
+    /**\r
+     * Subclass of MdcFilterFeature for junit usage.\r
+     */\r
+    private class MdcFilterFeatureImpl extends MdcFilterFeature {\r
+\r
+        public MdcFilterFeatureImpl() {\r
+            super();\r
+        }\r
+\r
+        @Override\r
+        protected Properties getFeatureProps() {\r
+            return props;\r
+        }\r
+    }\r
+}\r
diff --git a/feature-mdc-filters/src/test/java/org/onap/policy/drools/mdc/filters/MdcTopicFilterTest.java b/feature-mdc-filters/src/test/java/org/onap/policy/drools/mdc/filters/MdcTopicFilterTest.java
new file mode 100755 (executable)
index 0000000..2a5a875
--- /dev/null
@@ -0,0 +1,564 @@
+/*\r
+ * ============LICENSE_START=======================================================\r
+ * feature-mdc-filters\r
+ * ================================================================================\r
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.\r
+ * ================================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ * \r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ * \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ * ============LICENSE_END=========================================================\r
+ */\r
+\r
+package org.onap.policy.drools.mdc.filters;\r
+\r
+import static org.junit.Assert.assertEquals;\r
+import static org.junit.Assert.assertNotNull;\r
+\r
+import java.util.Arrays;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.junit.Test;\r
+import org.onap.policy.drools.mdc.filters.MdcTopicFilter.FilterRule;\r
+\r
+public class MdcTopicFilterTest {\r
+\r
+    /**\r
+     * Test the simple case of having one filter rule for a key.\r
+     */\r
+    @Test\r
+    public void singleFilterOnePathTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        FilterRule rule = topicFilter.getFilterRule("requestID");\r
+        assertEquals("requestID", rule.getMdcKey());\r
+        assertEquals("[$.requestID]", rule.getPaths().toString());\r
+    }\r
+\r
+    /**\r
+     * Tests having one filter rule with a set of potential paths to the key.\r
+     */\r
+    @Test\r
+    public void singleFilterMultiPathTest() {\r
+        String topicFilterProp = "requestID=$.requestID|$.request-id";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        FilterRule rule = topicFilter.getFilterRule("requestID");\r
+        assertEquals("requestID", rule.getMdcKey());\r
+        assertEquals(2, rule.getPaths().size());\r
+        assertEquals("[$.requestID, $.request-id]", rule.getPaths().toString());\r
+    }\r
+\r
+    /**\r
+     * Tests having two filter rules that each have one key/path pair.\r
+     */\r
+    @Test\r
+    public void multiFilterSinglePathTest() {\r
+        String topicFilterProp = "requestID=$.requestID,closedLoopControlName=$.closedLoopControlName";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        FilterRule rule = topicFilter.getFilterRule("requestID");\r
+        assertEquals("requestID", rule.getMdcKey());\r
+        assertEquals(1, rule.getPaths().size());\r
+        assertEquals("[$.requestID]", rule.getPaths().toString());\r
+\r
+        FilterRule rule2 = topicFilter.getFilterRule("closedLoopControlName");\r
+        assertEquals("closedLoopControlName", rule2.getMdcKey());\r
+        assertEquals(1, rule2.getPaths().size());\r
+        assertEquals("[$.closedLoopControlName]", rule2.getPaths().toString());\r
+    }\r
+\r
+    /**\r
+     * Tests having two filter rules that each have two key/path pairs.\r
+     */\r
+    @Test\r
+    public void multiFilterMultiPathTest() {\r
+        String topicFilterProp = "requestID=$.requestID|$.body.request-id," \r
+                + "closedLoopControlName=$.closedLoopControlName"\r
+                + "|$.body.closedLoopControlName";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        FilterRule rule = topicFilter.getFilterRule("requestID");\r
+        assertEquals("requestID", rule.getMdcKey());\r
+        assertEquals(2, rule.getPaths().size());\r
+        assertEquals("[$.requestID, $.body.request-id]", rule.getPaths().toString());\r
+\r
+        FilterRule rule2 = topicFilter.getFilterRule("closedLoopControlName");\r
+        assertEquals("closedLoopControlName", rule2.getMdcKey());\r
+        assertEquals(2, rule2.getPaths().size());\r
+        assertEquals("[$.closedLoopControlName, $.body.closedLoopControlName]", rule2.getPaths().toString());\r
+    }\r
+\r
+    /**\r
+     * Tests that the regex split logic for '|' in the feature code doesn't\r
+     * break parsing when "||" is used as a predicate in a JsonPath query.\r
+     */\r
+    @Test\r
+    public void addOrPredicateFilterTest() {\r
+        String topicFilterProp = "requestID=$.requestID||$.body.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        assertEquals(1, topicFilter.getFilterRule().size());\r
+        assertEquals("requestID", topicFilter.getFilterRule("requestID").getMdcKey());\r
+        assertEquals(Arrays.asList("$.requestID||$.body.requestID"), topicFilter\r
+                .getFilterRule("requestID").getPaths());\r
+    }\r
+\r
+    /**\r
+     * Tests getting all filter rules for a given topic.\r
+     */\r
+    @Test\r
+    public void getAllFilterRulesTest() {\r
+        String topicFilterProp = "requestID=$.requestID,subRequestID=$.subRequestID,"\r
+                + "closedLoopControlName=$.closedLoopControlName";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        assertEquals(3, topicFilter.getFilterRule().size());\r
+    }\r
+\r
+    /**\r
+     * Tests getting a filter rule by its key.\r
+     */\r
+    @Test\r
+    public void getFilterRuleTest() {\r
+        String topicFilterProp = "requestID=$.requestID,subRequestID=$.subRequestID,"\r
+                + "closedLoopControlName=$.closedLoopControlName";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        FilterRule rule = topicFilter.getFilterRule("requestID");\r
+        assertNotNull(rule);\r
+    }\r
+\r
+    /**\r
+     * Tests throwing an exception for passing in a null key.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void getFilterRuleNullKeyTest() {\r
+        String topicFilterProp = "requestID=$.requestID,subRequestID=$.subRequestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.getFilterRule(null);\r
+    }\r
+\r
+    /**\r
+     * Tests throwing an exception for passing in an empty key.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void getFilterRuleEmptyKeyTest() {\r
+        String topicFilterProp = "requestID=$.requestID,subRequestID=$.subRequestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.getFilterRule("");\r
+    }\r
+\r
+    /**\r
+     * Tests adding a filter rule with a single path.\r
+     */\r
+    @Test\r
+    public void addFilterRuleSinglePathTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        String key = "subRequestID";\r
+        String path = "$.subRequestID";\r
+        FilterRule rule = topicFilter.addFilterRule(key, path);\r
+        assertEquals(topicFilter.getFilterRule(key), rule);\r
+    }\r
+\r
+    /**\r
+     * Tests adding a filter rule with multiple paths.\r
+     */\r
+    @Test\r
+    public void addFilterRuleMultiPathTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        String key = "subRequestID";\r
+        List<String> paths = Arrays.asList("$.subRequestID", "$.sub-request-id");\r
+        FilterRule rule = topicFilter.addFilterRule(key, paths);\r
+        assertEquals(topicFilter.getFilterRule(key), rule);\r
+    }\r
+\r
+    /**\r
+     * Tests throwing an exception for passing a null key and a\r
+     * single path.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void addFilterRuleNullKeyStringPathTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.addFilterRule(null, "$.subRequestID");\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception for passing a null key and a list\r
+     * of paths.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void addFilterRuleNullKeyPathListTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.addFilterRule(null, Arrays.asList("$.subRequestID"));\r
+    }\r
+\r
+    /**\r
+     * Tests throwing an exception for passing an empty key and\r
+     * a single path.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void addFilterRuleEmptyKeyStringPathTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.addFilterRule("", "$.subRequestID");\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception for passing an empty key and\r
+     * a list of paths.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void addFilterRuleEmptyKeyPathListTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.addFilterRule("", Arrays.asList("$.subRequestID"));\r
+    }\r
+\r
+    /**\r
+     * Tests throwing an exception for passing an empty path string.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void addFilterRuleEmptyPathTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.addFilterRule("subRequestID", "");\r
+    }\r
+\r
+    /**\r
+     * Tests throwing an exception for passing an empty paths list.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void addFilterRuleEmptyPathsTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.addFilterRule("subRequestID", Arrays.asList());\r
+    }\r
+\r
+    /**\r
+     * Tests throwing an exception for trying to add a filter with a key that\r
+     * already exists with a single filter.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void addExistingFilterRuleStringTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.addFilterRule("requestID", "$.test");\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception for trying to add a filter with a key that\r
+     * already exists with a list of filters.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void addExistingFilterRuleListTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.addFilterRule("requestID", Arrays.asList("$.test"));\r
+    }\r
+\r
+    /**\r
+     * Tests modifying a filter rule to add a new path.\r
+     */\r
+    @Test\r
+    public void modifyFilterRuleSinglePathTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        FilterRule rule = topicFilter.modifyFilterRule("requestID", "$.request-id");\r
+        assertEquals(topicFilter.getFilterRule("requestID"), rule);\r
+        assertEquals(Arrays.asList("$.requestID", "$.request-id"), rule.getPaths());\r
+    }\r
+\r
+    /**\r
+     * Tests modifying a filter rule to add a list of new paths.\r
+     */\r
+    @Test\r
+    public void modifyFilterRuleMultiPathTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        FilterRule rule = topicFilter.modifyFilterRule("requestID",\r
+                Arrays.asList("$.request-id", "$.requestId"));\r
+        assertEquals(topicFilter.getFilterRule("requestID"), rule);\r
+        assertEquals(\r
+                Arrays.asList("$.requestID", "$.request-id", "$.requestId"),\r
+                rule.getPaths());\r
+    }\r
+\r
+    /**\r
+     * Tests modifying a filter rule key.\r
+     */\r
+    @Test\r
+    public void modifyFilterRuleKeyTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        FilterRule rule = topicFilter.modifyFilterRule("requestID",\r
+                "request-id", Arrays.asList("$.request-id"));\r
+        assertEquals(topicFilter.getFilterRule("request-id"), rule);\r
+        assertEquals("[$.request-id]", rule.getPaths().toString());\r
+    }\r
+\r
+    /**\r
+     * Tests throwing an exception when passing a null key and\r
+     * a single path.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleNullKeyStringPathTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule(null, "$.request-id");\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when passing a null key and\r
+     * a list of multiple paths.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleNullKeyPathListTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule(null, Arrays.asList("$.request-id"));\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when passing an empty key and\r
+     * a single path.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleEmptyKeyStringPathTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule("", "$.request-id");\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when passing an empty key and\r
+     * a list of multiple paths.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleEmptyKeyPathListTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule("", Arrays.asList("$.request-id"));\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when passing an empty string path.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleEmptyPathStringTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule("requestID", "");\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when passing an empty list of paths.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleEmptyPathListTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule("requestID", Arrays.asList());\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when passing a key that is \r
+     * not in the filter rules map and a string path.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleMissingKeyStringPathTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule("request-id", "$.request-id");\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when passing a key that is \r
+     * not in the filter rules map and a list of paths.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleMissingKeyPathListTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule("request-id", Arrays.asList("$.request-id"));\r
+    }\r
+    \r
+    \r
+    /**\r
+     * Tests throwing an exception when passing a null oldKey.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleNullOldKeyTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule(null, "request-id", Arrays.asList("$.request-id"));\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when passing an empty oldKey.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleEmptyOldKeyTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule("", "request-id", Arrays.asList("$.request-id"));\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when passing a null newKey.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleNullNewKeyTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule("requestID", null, Arrays.asList("$.request-id"));\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when passing an empty newKey.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleEmptyNewKeyTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule("requestID", "", Arrays.asList("$.request-id"));\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when the old and new key are the same.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleSameKeyTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule("requestID", "requestID",\r
+                Arrays.asList("$.request-id"));\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when passing an empty paths list.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleEmptyPathsTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule("requestID", "request-id", Arrays.asList());\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception when the old key doesn't exist\r
+     * in the rules map.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void modifyFilterRuleNonExistingOldKeyTest() {\r
+        String topicFilterProp = "requestID=$.requestID";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.modifyFilterRule("request-id", "id", Arrays.asList("$.request-id"));\r
+    }\r
+\r
+    /**\r
+     * Tests deleting all filter rules in the rules map.\r
+     */\r
+    @Test\r
+    public void deleteAllFilterRulesTest() {\r
+        String topicFilterProp = "requestID=$.requestID,subRequestID=$.subRequestID,"\r
+                + "closedLoopControlName=$.closedLoopControlName";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        assertEquals(3, topicFilter.getFilterRule().size());\r
+        topicFilter.deleteFilterRule();\r
+        assertEquals(0, topicFilter.getFilterRule().size());\r
+    }\r
+\r
+    /**\r
+     * Tests deleting a single filter rule by its key from the rules map.\r
+     */\r
+    @Test\r
+    public void deleteFilterRuleTest() {\r
+        String topicFilterProp = "requestID=$.requestID,subRequestID=$.subRequestID,"\r
+                + "closedLoopControlName=$.closedLoopControlName";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        assertEquals(3, topicFilter.getFilterRule().size());\r
+        topicFilter.deleteFilterRule("closedLoopControlName");\r
+        assertEquals(2, topicFilter.getFilterRule().size());\r
+    }\r
+\r
+    /**\r
+     * Tests throwing an exception if the key is null.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void deleteFilterRuleNullKeyTest() {\r
+        String topicFilterProp = "requestID=$.requestID,subRequestID=$.subRequestID,"\r
+                + "closedLoopControlName=$.closedLoopControlName";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.deleteFilterRule(null);\r
+    }\r
+    \r
+    /**\r
+     * Tests throwing an exception if the key is empty.\r
+     */\r
+    @Test(expected = IllegalArgumentException.class)\r
+    public void deleteFilterRuleEmptyKeyTest() {\r
+        String topicFilterProp = "requestID=$.requestID,subRequestID=$.subRequestID,"\r
+                + "closedLoopControlName=$.closedLoopControlName";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+        topicFilter.deleteFilterRule("");\r
+    }\r
+\r
+    /**\r
+     * Tests finding all results for each filter rule corresponding to a topic.\r
+     */\r
+    @Test\r
+    public void findAllTest() {\r
+        String message = "{\"requestID\":\"38adde30-cc22-11e8-a8d5-f2801f1b9fd1\",\"entity\":\"controller\","\r
+                + "\"controllers\":[{\"name\":\"test-controller\","\r
+                + "\"drools\":{\"groupId\":\"org.onap.policy.drools.test\","\r
+                + "\"artifactId\":\"test\",\"version\":\"0.0.1\"},\"operation\":\"update\"}]}";\r
+\r
+        String topicFilterProp = "requestID=$.requestID,controllerName=$.controllers[0].name,"\r
+                + "operation=$.controllers[0].operation";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        Map<String, List<String>> results = topicFilter.find(message);\r
+        assertEquals("38adde30-cc22-11e8-a8d5-f2801f1b9fd1",\r
+                results.get("requestID").get(0));\r
+        assertEquals("test-controller", results.get("controllerName").get(0));\r
+        assertEquals("update", results.get("operation").get(0));\r
+    }\r
+\r
+    /**\r
+     * Tests finding field matches for a filter rule corresponding to a topic.\r
+     */\r
+    @Test\r
+    public void findTest() {\r
+        String message = "{\"requestID\":\"38adde30-cc22-11e8-a8d5-f2801f1b9fd1\",\"entity\":\"controller\","\r
+                + "\"controllers\":[{\"name\":\"test-controller\","\r
+                + "\"drools\":{\"groupId\":\"org.onap.policy.drools.test\","\r
+                + "\"artifactId\":\"test\",\"version\":\"0.0.1\"},\"operation\":\"update\"}]}";\r
+\r
+        String topicFilterProp = "requestID=$.requestID,controllerName=$.controllers[0].name,"\r
+                + "operation=$.controllers[0].operation";\r
+        MdcTopicFilter topicFilter = new MdcTopicFilter(topicFilterProp);\r
+\r
+        List<String> results = topicFilter.find(message, "requestID");\r
+        assertEquals("38adde30-cc22-11e8-a8d5-f2801f1b9fd1", results.get(0));\r
+    }\r
+}\r
diff --git a/feature-mdc-filters/src/test/resources/onset.json b/feature-mdc-filters/src/test/resources/onset.json
new file mode 100755 (executable)
index 0000000..fafc93a
--- /dev/null
@@ -0,0 +1,18 @@
+{\r
+    "closedLoopEventClient": "DCAE_INSTANCE_ID.dcae-tca",\r
+    "policyVersion": "1.0.0.5",\r
+    "policyName": "policyTest",\r
+    "policyScope": "type=SampleType,closedLoopControlName=SampleClosedLoop",\r
+    "target_type": "VM",\r
+    "AAI": {\r
+        "vserver.is-closed-loop-disabled": false,\r
+        "vserver.vserver-name": "example-vserver-name"\r
+    },\r
+    "closedLoopAlarmStart": 1484855291527925,\r
+    "closedLoopEventStatus": "ONSET",\r
+    "closedLoopControlName": "CL-TEST",\r
+    "version": "1.0.2",\r
+    "target": "vserver.vserver-name",\r
+    "requestID": "8c1b8bd8-06f7-493f-8ed7-daaa4cc481bc",\r
+    "from": "DCAE"\r
+}
\ No newline at end of file
index e603fb6..7fa5d50 100644 (file)
             <version>${project.version}</version>
             <type>zip</type>
         </dependency>
+        <dependency>
+            <groupId>org.onap.policy.drools-pdp</groupId>
+            <artifactId>feature-mdc-filters</artifactId>
+            <version>${project.version}</version>
+            <type>zip</type>
+        </dependency>
        </dependencies>
 
 </project>
index 4fb8276..bf08a5a 100644 (file)
   -->
 
 <configuration scan="true" scanPeriod="30 seconds" debug="false">
-    
-       <property name="logDir" value="${POLICY_LOGS}" />
-
-       <property name="errorLog" value="error" />
-       <property name="debugLog" value="debug" />
-       <property name="networkLog" value="network" />
-
-       <property name="metricLog" value="metric" />
-       <property name="transactionLog" value="audit" />
-
-       <property name="debugPattern" value="[%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%level|%logger{0}|%thread] %msg%n" />
-       <property name="errorPattern" value="${debugPattern}" />
-       <property name="networkPattern" value="[%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%t]%m%n" />
-
-       <property name="metricPattern" value="%X{RequestID}|%X{InvocationID}|%X{ServiceName}|%X{PartnerName}|%X{BeginTimestamp}|%X{EndTimestamp}|%X{ElapsedTime}|%X{ServiceInstanceID}|%X{VirtualServerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%X{Severity}|%X{TargetEntity}|%X{TargetServiceName}|%X{Server}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{ClientIPAddress}|%X{ProcessKey}|%X{RemoteHost}|%X{AlertSeverity}|%X{TargetVirtualEntity}|%level|%thread| %msg%n"/>
-       <property name="transactionPattern" value="${metricPattern}" />
-
-       <appender name="ErrorOut" class="ch.qos.logback.core.rolling.RollingFileAppender">
-               <file>${logDir}/${errorLog}.log</file>
-               <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-                       <fileNamePattern>${logDir}/${errorLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
-                       <maxFileSize>50MB</maxFileSize>
-                       <maxHistory>30</maxHistory>
-                       <totalSizeCap>10GB</totalSizeCap>
-               </rollingPolicy>
-               <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
-                       <level>WARN</level>
-               </filter>
-               <encoder>
-                       <pattern>${errorPattern}</pattern>
-               </encoder>
-       </appender>
-
-       <appender name="AsyncErrorOut" class="ch.qos.logback.classic.AsyncAppender">
-               <appender-ref ref="ErrorOut" />
-       </appender>
-       
-       <appender name="DebugOut" class="ch.qos.logback.core.rolling.RollingFileAppender">
-               <file>${logDir}/${debugLog}.log</file>
-               <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-                       <fileNamePattern>${logDir}/${debugLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
-                       <maxFileSize>50MB</maxFileSize>
-                       <maxHistory>30</maxHistory>
-                       <totalSizeCap>10GB</totalSizeCap>
-               </rollingPolicy>
-               <encoder>
-                       <pattern>${debugPattern}</pattern>
-               </encoder>
-       </appender>
-       
-       <appender name="AsyncDebugOut" class="ch.qos.logback.classic.AsyncAppender">
-               <appender-ref ref="DebugOut" />
-       </appender>
-
-       <appender name="NetworkOut" class="ch.qos.logback.core.rolling.RollingFileAppender">
-               <file>${logDir}/${networkLog}.log</file>
-               <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-                       <fileNamePattern>${logDir}/${networkLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
-                       <maxFileSize>50MB</maxFileSize>
-                       <maxHistory>30</maxHistory>
-                       <totalSizeCap>10GB</totalSizeCap>
-               </rollingPolicy>
-               <encoder>
-                       <pattern>${networkPattern}</pattern>
-               </encoder>              
-       </appender>
-       
-       <appender name="AsyncNetworkOut" class="ch.qos.logback.classic.AsyncAppender">
-               <appender-ref ref="NetworkOut" />
-       </appender>
-
-       <appender name="MetricOut" class="ch.qos.logback.core.rolling.RollingFileAppender">
-               <file>${logDir}/${metricLog}.log</file>
-               <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-                       <fileNamePattern>${logDir}/${metricLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
-                       <maxFileSize>50MB</maxFileSize>
-                       <maxHistory>30</maxHistory>
-                       <totalSizeCap>10GB</totalSizeCap>
-               </rollingPolicy>
-               <filter class="org.onap.policy.drools.utils.logging.LoggerMarkerFilter$MetricLoggerMarkerFilter" />
-               <encoder>
-                       <pattern>${metricPattern}</pattern>
-               </encoder>
-       </appender>
-
-       <appender name="AsyncMetricOut" class="ch.qos.logback.classic.AsyncAppender">
-               <appender-ref ref="MetricOut" />
-       </appender>
-
-       <appender name="TransactionOut" class="ch.qos.logback.core.rolling.RollingFileAppender">
-               <file>${logDir}/${transactionLog}.log</file>
-               <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-                       <fileNamePattern>${logDir}/${transactionLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
-                       <maxFileSize>50MB</maxFileSize>
-                       <maxHistory>30</maxHistory>
-                       <totalSizeCap>10GB</totalSizeCap>
-               </rollingPolicy>
-               <filter class="org.onap.policy.drools.utils.logging.LoggerMarkerFilter$TransactionLoggerMarkerFilter" />
-               <encoder>
-                       <pattern>${transactionPattern}</pattern>
-               </encoder>
-       </appender>
-
-       <appender name="AsyncTransactionOut" class="ch.qos.logback.classic.AsyncAppender">
-               <appender-ref ref="TransactionOut" />
-       </appender>
-
-       <logger name="network" level="INFO" additivity="false">
-               <appender-ref ref="AsyncNetworkOut" />          
-       </logger>
-       
-       <logger name="org.eclipse.jetty.server.RequestLog" level="info" additivity="false">
-               <appender-ref ref="AsyncNetworkOut" />
-       </logger>
-
-       <root level="INFO">
-               <appender-ref ref="AsyncDebugOut" />
-               <appender-ref ref="AsyncErrorOut" />
-               <appender-ref ref="AsyncMetricOut" />
-               <appender-ref ref="AsyncTransactionOut" />
-       </root>
+
+    <property name="logDir" value="${POLICY_LOGS}" />
+
+    <property name="errorLog" value="error" />
+    <property name="debugLog" value="debug" />
+    <property name="networkLog" value="network" />
+
+    <property name="metricLog" value="metric" />
+    <property name="transactionLog" value="audit" />
+
+    <property name="debugPattern"
+        value="[%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%level|%logger{0}|%thread] %msg%n" />
+    <property name="errorPattern" value="${debugPattern}" />
+    <property name="networkPattern" value="[%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%t]%m%n" />
+    <property name="abstractNetworkPattern"
+        value="[%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}] [%X{networkEventType:-NULL}|%X{networkProtocol:-NULL}|%X{networkTopic:-NULL}|%X{requestID:-NULL}]%n" />
+
+    <property name="metricPattern"
+        value="%X{RequestID}|%X{InvocationID}|%X{ServiceName}|%X{PartnerName}|%X{BeginTimestamp}|%X{EndTimestamp}|%X{ElapsedTime}|%X{ServiceInstanceID}|%X{VirtualServerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%X{Severity}|%X{TargetEntity}|%X{TargetServiceName}|%X{Server}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{ClientIPAddress}|%X{ProcessKey}|%X{RemoteHost}|%X{AlertSeverity}|%X{TargetVirtualEntity}|%level|%thread| %msg%n" />
+    <property name="transactionPattern" value="${metricPattern}" />
+
+    <appender name="ErrorOut" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${logDir}/${errorLog}.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${logDir}/${errorLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
+            <maxFileSize>50MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>WARN</level>
+        </filter>
+        <encoder>
+            <pattern>${errorPattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="AsyncErrorOut" class="ch.qos.logback.classic.AsyncAppender">
+        <appender-ref ref="ErrorOut" />
+    </appender>
+
+    <appender name="DebugOut" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${logDir}/${debugLog}.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${logDir}/${debugLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
+            <maxFileSize>50MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${debugPattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="AsyncDebugOut" class="ch.qos.logback.classic.AsyncAppender">
+        <appender-ref ref="DebugOut" />
+    </appender>
+
+    <appender name="NetworkOut" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${logDir}/${networkLog}.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${logDir}/${networkLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
+            <maxFileSize>50MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+        </rollingPolicy>
+        <encoder>
+            <pattern>${networkPattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="AsyncNetworkOut" class="ch.qos.logback.classic.AsyncAppender">
+        <appender-ref ref="NetworkOut" />
+    </appender>
+
+    <appender name="MetricOut" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${logDir}/${metricLog}.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${logDir}/${metricLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
+            <maxFileSize>50MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+        </rollingPolicy>
+        <filter class="org.onap.policy.drools.utils.logging.LoggerMarkerFilter$MetricLoggerMarkerFilter" />
+        <encoder>
+            <pattern>${metricPattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="AsyncMetricOut" class="ch.qos.logback.classic.AsyncAppender">
+        <appender-ref ref="MetricOut" />
+    </appender>
+
+    <appender name="TransactionOut" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${logDir}/${transactionLog}.log</file>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${logDir}/${transactionLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern>
+            <maxFileSize>50MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+        </rollingPolicy>
+        <filter class="org.onap.policy.drools.utils.logging.LoggerMarkerFilter$TransactionLoggerMarkerFilter" />
+        <encoder>
+            <pattern>${transactionPattern}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="AsyncTransactionOut" class="ch.qos.logback.classic.AsyncAppender">
+        <appender-ref ref="TransactionOut" />
+    </appender>
+
+    <logger name="network" level="INFO" additivity="false">
+        <appender-ref ref="AsyncNetworkOut" />
+    </logger>
+
+    <logger name="org.eclipse.jetty.server.RequestLog" level="info" additivity="false">
+        <appender-ref ref="AsyncNetworkOut" />
+    </logger>
+
+    <root level="INFO">
+        <appender-ref ref="AsyncDebugOut" />
+        <appender-ref ref="AsyncErrorOut" />
+        <appender-ref ref="AsyncMetricOut" />
+        <appender-ref ref="AsyncTransactionOut" />
+    </root>
 
 </configuration>
diff --git a/pom.xml b/pom.xml
index c2733c8..8a41bed 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -81,6 +81,7 @@
         <module>feature-simulators</module>
         <module>feature-distributed-locking</module>
         <module>feature-controller-logging</module>
+        <module>feature-mdc-filters</module>
         <module>packages</module>
     </modules>