Standalone TCA with EELF Logger
[dcaegen2/analytics/tca-gen2.git] / dcae-analytics / dcae-analytics-tca-core / src / main / java / org / onap / dcae / analytics / tca / core / util / function / calculation / TcaAbatementCalculator.java
1 /*
2  * ================================================================================
3  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  * ============LICENSE_END=========================================================
17  *
18  */
19
20 package org.onap.dcae.analytics.tca.core.util.function.calculation;
21
22 import java.util.Comparator;
23 import java.util.List;
24 import java.util.stream.Collectors;
25 import java.util.stream.Stream;
26
27 import org.onap.dcae.analytics.model.TcaModelConstants;
28 import org.onap.dcae.analytics.model.cef.EventListener;
29 import org.onap.dcae.analytics.tca.core.exception.TcaProcessingException;
30 import org.onap.dcae.analytics.tca.core.service.TcaAbatementContext;
31 import org.onap.dcae.analytics.tca.core.service.TcaAbatementEntity;
32 import org.onap.dcae.analytics.tca.core.service.TcaAbatementRepository;
33 import org.onap.dcae.analytics.tca.core.service.TcaExecutionContext;
34 import org.onap.dcae.analytics.tca.core.service.TcaProcessingContext;
35 import org.onap.dcae.analytics.tca.core.service.TcaResultContext;
36 import org.onap.dcae.analytics.tca.model.policy.ClosedLoopEventStatus;
37 import org.onap.dcae.analytics.tca.model.policy.MetricsPerEventName;
38 import org.onap.dcae.analytics.tca.model.policy.Threshold;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 /**
43  * @author Rajiv Singla
44  */
45 public class TcaAbatementCalculator implements TcaCalculationFunction {
46
47     private static final Logger logger = LoggerFactory.getLogger(TcaAbatementCalculator.class);
48
49     @Override
50     public TcaExecutionContext calculate(final TcaExecutionContext tcaExecutionContext) {
51
52         final TcaAbatementContext abatementContext = tcaExecutionContext.getTcaAbatementContext();
53         final TcaAbatementRepository abatementPersistenceContext = abatementContext
54                 .getTcaAbatementRepository();
55         final TcaResultContext resultContext = tcaExecutionContext.getTcaResultContext();
56         final TcaProcessingContext processingContext = tcaExecutionContext.getTcaProcessingContext();
57
58
59         // Skip Abatement processing - if it is not enabled
60         if (!abatementContext.isAbatementEnabled() ||
61                 // Skip if no threshold violations are present
62                 !resultContext.isThresholdViolationsPresent()) {
63             return tcaExecutionContext;
64         }
65
66
67         final EventListener eventListener = processingContext.getEventListener();
68         final MetricsPerEventName violatedMetricsPerEventName = resultContext.getViolatedMetricsPerEventName();
69         final Threshold violatedThreshold = violatedMetricsPerEventName.getThresholds().get(0);
70         final ClosedLoopEventStatus closedLoopEventStatus = violatedThreshold.getClosedLoopEventStatus();
71         final String requestId = tcaExecutionContext.getRequestId();
72         final String lookupKey = createLookupKey(eventListener, violatedMetricsPerEventName);
73
74
75         switch (closedLoopEventStatus) {
76
77             // ONSET - save alert info in database so that next abated event can fetch its request id for abated
78             // alert
79             case ONSET:
80
81                 final TcaAbatementEntity tcaAbatementEntity =
82                         abatementContext.create(lookupKey, requestId, false);
83                 logger.debug("Request Id: {}. Alert ClosedLoop Status is ONSET. " +
84                                 "Saving abatement Entity to repository with lookupKey: {}",
85                         requestId, tcaAbatementEntity.getLookupKey());
86                 abatementPersistenceContext.save(tcaAbatementEntity);
87                 return tcaExecutionContext;
88
89             // ABATED - look up previous saved request id from db
90             case ABATED:
91
92                 final List<TcaAbatementEntity> previousTcaAbatementEntities =
93                         abatementPersistenceContext.findByLookupKey(lookupKey);
94
95                 // if previous abatement are indeed present - sort them my last modified date and get latest entity
96                 if (previousTcaAbatementEntities != null && !previousTcaAbatementEntities.isEmpty()) {
97                     previousTcaAbatementEntities.sort(
98                             Comparator.comparing(TcaAbatementEntity::getLastModificationDate));
99                     final TcaAbatementEntity previousTcaAbatementEntity =
100                             previousTcaAbatementEntities.get(previousTcaAbatementEntities.size() - 1);
101
102                     logger.debug("Request Id: {}. Found previous Abatement Entity: {}", requestId,
103                             previousTcaAbatementEntity);
104
105                     // previous abatement entity was found - but it was already sent before - so ignore alert creation
106                     if (previousTcaAbatementEntity.isAbatementAlertSent()) {
107                         final String terminatingMessage = "Abatement alert was already sent before on: " +
108                                 previousTcaAbatementEntity.getLastModificationDate();
109                         setTerminatingMessage(terminatingMessage, tcaExecutionContext, false);
110                         return tcaExecutionContext;
111                     }
112
113                     // no previous abatement was sent
114                     final String previousRequestId = previousTcaAbatementEntity.getRequestId();
115                     // set abated alert request id to previous ONSET alert request id
116                     logger.debug("Request Id: {}. No previous abated alert was sent. Setting previous request id: {}",
117                             requestId, previousRequestId);
118                     resultContext.setPreviousRequestId(previousRequestId);
119                     // save new entity with alert as sent
120                     final TcaAbatementEntity newTcaAbatementEntity =
121                             abatementContext.create(lookupKey, previousRequestId, true);
122                     logger.debug("Request Id: {}. Saving new entity with alert as sent: {}",
123                             requestId, newTcaAbatementEntity);
124                     abatementPersistenceContext.save(newTcaAbatementEntity);
125                     return tcaExecutionContext;
126
127                 } else {
128                     // no previous onset event found
129                     final String terminatingMessage =
130                             "Ignored orphan Abated Message. No previous ONSET event found for lookup key: " + lookupKey;
131                     setTerminatingMessage(terminatingMessage, tcaExecutionContext, false);
132                     return tcaExecutionContext;
133                 }
134
135                 // Only ONSET and ABATED closed loop status are supported
136             default:
137                 final String errorMessage = String.format(
138                         "Request Id: %s. Unexpected ClosedLoopEventStatus: %s - Only ONSET and ABATED are supported.",
139                         requestId, closedLoopEventStatus);
140                 throw new TcaProcessingException(errorMessage, new IllegalStateException(errorMessage));
141         }
142
143     }
144
145     private static String createLookupKey(final EventListener eventListener,
146                                           final MetricsPerEventName violatedMetricsPerEventName) {
147         // no null check required as all are required fields
148         final String eventName = violatedMetricsPerEventName.getEventName();
149         final String sourceName = eventListener.getEvent().getCommonEventHeader().getSourceName();
150         final String reportingEntityName = eventListener.getEvent().getCommonEventHeader().getReportingEntityName();
151         // violated threshold will always be present
152         final Threshold violatedThreshold = violatedMetricsPerEventName.getThresholds().get(0);
153         final String closedLoopControlName = violatedThreshold.getClosedLoopControlName();
154         final String fieldPath = violatedThreshold.getFieldPath();
155         return Stream.of(eventName, sourceName, reportingEntityName, closedLoopControlName, fieldPath)
156                 .collect(Collectors.joining(TcaModelConstants.TCA_ROW_KEY_DELIMITER));
157
158     }
159 }