2 * ============LICENSE_START=======================================================
3 * ONAP : ccsdk features
4 * ================================================================================
5 * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.ccsdk.features.sdnr.wt.websocketmanager.utils;
24 import java.time.Duration;
25 import java.time.Instant;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
30 * Problems of to many notifications during mount of thousand of devices:
32 * <li>Overload ODLUX with notification flood -> ODLUX App can not control notifications rate
33 * <li>Notification processing blocks user -> App design with notifications popups
37 * <li>Do not use a thread -> Do nothing if there are no notifications
38 * <li>Parameter1 integrationTime : Measurement or integration time for period
39 * <li>Parameter2 readMaxCount : Specifies event number per interval indicating overload
40 * <li>Start measurement on event received that comes later then
44 * Example (e: Event received, rateMaxCount=3)
45 * eee e e e e e e e e e e e e e e
46 * ---//--|--------------|-----//-------|--------------|--------------|--------------|---//----|--------------|
47 * P1 P2 P1 P2 P3 P7 P1
48 *Overload no no yes yes no no
52 * 1. Construct with parameters for WS stream to handle
57 public class RateFilter {
59 private static final Logger LOG = LoggerFactory.getLogger(RateFilter.class.getName());
61 private final Duration integrationTime; // Integration time to measure event rate
62 private final long rateMaxCount; //Rate for dropping packets
63 private Instant timeStampPeriodStart; //Time stamp period beginn
64 private Instant timeStampLastEvent; //Measurement interval
65 private long rateCount; // >0: integration running 0: no integration running
66 private boolean overload; //true means in overload status. Change at end of period only.
70 * Allow testing with own timestamp provider
72 public interface GetNow {
76 public RateFilter(Duration integrationTime, long rateMaxCount, GetNow getNowMethod) {
77 this.integrationTime = integrationTime;
78 this.rateMaxCount = rateMaxCount;
79 this.get = getNowMethod;
80 this.timeStampLastEvent = Instant.MIN;
83 public RateFilter(Duration integrationTime, long rateMaxCount) {
84 this(integrationTime, rateMaxCount, () -> Instant.now());
87 public synchronized boolean getOverloadStatus() {
92 * Handle filter on event received
94 public synchronized void filterEvent() {
95 final Instant now = get.now();
96 final Duration durationSinceLastEvent = Duration.between(timeStampLastEvent, now);
97 this.timeStampLastEvent = now;
99 if (durationSinceLastEvent.compareTo(integrationTime) >= 0) {
100 //No measurement. Sync and start with period
102 timeStampPeriodStart = now;
103 rateCount = 1; //Reset event count .. is part of the
106 Duration durationPeriod = Duration.between(timeStampPeriodStart, now);
108 boolean endOfPeriod = durationPeriod.compareTo(integrationTime) >= 0;
109 LOG.debug("Period start{}: now:{} end:{} dur:{} int:{}", timeStampPeriodStart, now, endOfPeriod, durationPeriod, integrationTime);
111 //Only if end of Period
112 overload = rateCount > rateMaxCount;
113 LOG.debug("Reset overload {}", overload);
114 timeStampPeriodStart = timeStampPeriodStart.plus(integrationTime);
121 public String toString() {
122 StringBuilder builder = new StringBuilder();
123 builder.append("RateFilter [integrationTime=");
124 builder.append(integrationTime);
125 builder.append(", rateMaxCount=");
126 builder.append(rateMaxCount);
127 builder.append(", timeStampPeriodStart=");
128 builder.append(timeStampPeriodStart);
129 builder.append(", timeStampLastEvent=");
130 builder.append(timeStampLastEvent);
131 builder.append(", rateCount=");
132 builder.append(rateCount);
133 builder.append(", overload=");
134 builder.append(overload);
136 return builder.toString();