Remove trailing whitespace
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / statistics / StatisticsCounters.java
1 /*
2  * Copyright (c) 2014 Pantheon Technologies s.r.o. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.openflowjava.statistics;
9
10 import java.util.Map;
11 import java.util.Timer;
12 import java.util.TimerTask;
13 import java.util.concurrent.ConcurrentHashMap;
14
15 import org.opendaylight.openflowjava.protocol.spi.statistics.StatisticsHandler;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
18
19 /**
20  * Singleton class to hold and process counters
21  * @author madamjak
22  *
23  */
24 public final class StatisticsCounters implements StatisticsHandler {
25
26     /**
27      * Default delay between two writings into log (milliseconds)
28      */
29     public static final int DEFAULT_LOG_REPORT_PERIOD = 10000;
30     /**
31      * Minimal delay between two writings into log (milliseconds)
32      */
33     public static final int MINIMAL_LOG_REPORT_PERIOD = 500;
34     private static StatisticsCounters instanceHolder;
35     private static final Logger LOGGER = LoggerFactory.getLogger(StatisticsCounters.class);
36
37     private Timer logReporter;
38     private int logReportPeriod;
39     private boolean runLogReport;
40     private Map<CounterEventTypes, Counter> countersMap;
41     private boolean runCounting;
42     // array to hold enabled counter types
43     private CounterEventTypes[] enabledCounters = {
44                     CounterEventTypes.DS_ENCODE_FAIL,
45                     CounterEventTypes.DS_ENCODE_SUCCESS,
46                     CounterEventTypes.DS_ENTERED_OFJAVA,
47                     CounterEventTypes.DS_FLOW_MODS_ENTERED,
48                     CounterEventTypes.DS_FLOW_MODS_SENT,
49                     CounterEventTypes.US_DECODE_FAIL,
50                     CounterEventTypes.US_DECODE_SUCCESS,
51                     CounterEventTypes.US_MESSAGE_PASS,
52                     CounterEventTypes.US_RECEIVED_IN_OFJAVA};
53
54     /**
55      * Get instance of statistics counters, first created object does not start counting and log reporting
56      * @return an instance
57      */
58     public synchronized static StatisticsCounters getInstance() {
59         if (instanceHolder == null) {
60             instanceHolder = new StatisticsCounters();
61         }
62         return instanceHolder;
63     }
64
65     private StatisticsCounters() {
66         countersMap = new ConcurrentHashMap<>();
67         for(CounterEventTypes cet : enabledCounters){
68             countersMap.put(cet, new Counter());
69         }
70         runCounting = false;
71         this.logReportPeriod = 0;
72         this.runLogReport = false;
73         LOGGER.debug("StaticsCounters has been created");
74     }
75
76     /**
77      * Start counting (counters are set to 0 before counting starts)
78      * @param reportToLogs - true = statistic counters will periodically log
79      * @param logReportDelay - delay between two logs (in milliseconds)
80      */
81     public void startCounting(boolean reportToLogs, int logReportDelay){
82         if (runCounting) {
83             return;
84         }
85         resetCounters();
86         LOGGER.debug("Counting started...");
87         if(reportToLogs){
88             startLogReport(logReportDelay);
89         }
90         runCounting = true;
91     }
92
93     /**
94      * Stop counting, values in counters are untouched, log reporter is stopped
95      */
96     public void stopCounting(){
97         runCounting = false;
98         LOGGER.debug("Stop counting...");
99         stopLogReport();
100     }
101
102     /**
103      * Give an information if counting is running
104      * @return true, if counting is running, otherwise false
105      */
106     public boolean isRunCounting(){
107         return runCounting;
108     }
109
110     /**
111      * Prints statistics with given delay between logs
112      * @param logReportDelay - delay between two logs (in milliseconds)
113      * @exception IllegalArgumentException if logReportDelay is less than 0
114      */
115     public void startLogReport(int logReportDelay){
116         if(runLogReport){
117             return;
118         }
119         if(logReportDelay <= 0){
120             throw new IllegalArgumentException("logReportDelay has to be greater than 0");
121         }
122         if(logReportDelay < MINIMAL_LOG_REPORT_PERIOD){
123             this.logReportPeriod = MINIMAL_LOG_REPORT_PERIOD;
124         } else {
125             this.logReportPeriod = logReportDelay;
126         }
127         logReporter = new Timer("SC_Timer");
128         logReporter.schedule(new LogReporterTask(this), this.logReportPeriod, this.logReportPeriod);
129         runLogReport = true;
130         LOGGER.debug("Statistics log reporter has been scheduled with period {} ms", this.logReportPeriod);
131     }
132
133     /**
134      * Stops logging, counting continues
135      */
136     public void stopLogReport(){
137         if(runLogReport){
138             if(logReporter != null){
139                 logReporter.cancel();
140                 LOGGER.debug("Statistics log reporter has been canceled");
141             }
142             runLogReport = false;
143         }
144     }
145
146     /**
147      * Give an information if log reporter is running (statistics are write into logs).
148      * @return true if log reporter writes statistics into log, otherwise false
149      */
150     public boolean isRunLogReport(){
151         return runLogReport;
152     }
153
154     /**
155      * @return the current delay between two writings into logs
156      */
157     public int getLogReportPeriod() {
158         return logReportPeriod;
159     }
160
161     /**
162      * @return the enabled counters
163      */
164     protected CounterEventTypes[] getEnabledCounters() {
165         return enabledCounters;
166     }
167     /**
168      * @return the countersMap
169      */
170     protected Map<CounterEventTypes, Counter> getCountersMap() {
171         return countersMap;
172     }
173
174     /**
175      * Give an information if is given counter is enabled
176      * @param counterEventKey
177      * @return true if counter has been Enabled, otherwise false
178      */
179     public boolean isCounterEnabled(CounterEventTypes counterEventKey){
180         if (counterEventKey == null) {
181             return false;
182         }
183         return countersMap.containsKey(counterEventKey);
184     }
185
186     /**
187      * Get counter by CounterEventType
188      * @param counterEventKey key to identify counter (can not be null)
189      * @return - Counter object or null if counter has not been enabled
190      * @exception - IllegalArgumentException if counterEventKey is null
191      */
192     public Counter getCounter(CounterEventTypes counterEventKey) {
193         if (counterEventKey == null) {
194             throw new IllegalArgumentException("counterEventKey can not be null");
195         }
196         return countersMap.get(counterEventKey);
197     }
198
199     /**
200      * Increment value of given counter
201      * @param counterEventKey key to identify counter
202      */
203     public void incrementCounter(CounterEventTypes counterEventKey) {
204         if(runCounting){
205             if (isCounterEnabled(counterEventKey)){
206                 countersMap.get(counterEventKey).incrementCounter();
207             }
208         }
209     }
210
211     @Override
212     public void resetCounters() {
213         for(CounterEventTypes cet : enabledCounters){
214             countersMap.get(cet).reset();
215         }
216         LOGGER.debug("StaticsCounters has been reset");
217     }
218
219     @Override
220     public String printStatistics() {
221         StringBuilder strBuilder = new StringBuilder();
222         for(CounterEventTypes cet : getEnabledCounters()){
223             strBuilder.append(cet.name() + ": " + getCountersMap().get(cet).getStat() + "\n");
224         }
225         return strBuilder.toString();
226     }
227
228     /**
229      * internal class to process logReporter
230      * @author madamjak
231      *
232      */
233     private static class LogReporterTask extends TimerTask {
234         private static final Logger LOG = LoggerFactory.getLogger(LogReporterTask.class);
235
236         private StatisticsCounters sc;
237         public LogReporterTask(StatisticsCounters sc) {
238             this.sc = sc;
239         }
240
241         @Override
242         public void run() {
243             for(CounterEventTypes cet : sc.getEnabledCounters()){
244                 LOG.debug(cet.name() + ": " + sc.getCountersMap().get(cet).getStat());
245             }
246         }
247     }
248 }