blob: 8d1df1004bf0754a8dff708868f95e3ad2252684 [file] [log] [blame]
Boyoung Jeong1cca5e82018-08-01 21:00:08 +09001/*
2 * Copyright 2018-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.openstacktelemetry.gui;
17
18import com.fasterxml.jackson.databind.node.ArrayNode;
19import com.fasterxml.jackson.databind.node.ObjectNode;
20import com.google.common.base.Strings;
21import com.google.common.collect.ImmutableMap;
22import com.google.common.collect.ImmutableSet;
23import com.google.common.collect.Maps;
24import org.onosproject.openstacktelemetry.api.FlowInfo;
25import org.onosproject.openstacktelemetry.api.StatsFlowRuleAdminService;
26import org.onosproject.ui.RequestHandler;
27import org.onosproject.ui.UiMessageHandler;
28import org.onosproject.ui.chart.ChartModel;
29import org.onosproject.ui.chart.ChartRequestHandler;
30import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
33import java.text.SimpleDateFormat;
34import java.util.Collection;
35import java.util.Date;
36import java.util.Map;
37import java.util.Queue;
38
39/**
40 * Message handler for Openstack Telemetry view related messages.
41 */
42public class OpensteckTelemetryViewMessageHandler extends UiMessageHandler {
43 private final Logger log = LoggerFactory.getLogger(getClass());
44
45 private static final String OST_DATA_REQ = "openstacktelemetryDataRequest";
46 private static final String OST_DATA_RESP = "openstacktelemetryDataResponse";
47 private static final String OSTS = "openstacktelemetrys";
48 private static final String ANNOT_FLOW_IDS = "flowIds";
49 private static final String ANNOT_PERIOD_OPTIONS = "periodOptions";
50
51 private static final String STAT_CURR_ACC_PACKET = "curr_acc_packet";
52 private static final String STAT_PREV_ACC_PACKET = "prev_acc_packet";
53 private static final String STAT_CURR_ACC_BYTE = "curr_acc_byte";
54 private static final String STAT_PREV_ACC_BYTE = "prev_acc_byte";
55 private static final String STAT_ERROR_PACKET = "error_packet";
56 private static final String STAT_DROP_PACKET = "drop_packet";
57
58 private static final String CHART_TIME_FORMAT = "HH:mm:ss";
59
60 // JSON node name
61 private static final String JSON_NODE_FLOW = "flowOpt";
62 private static final String JSON_NODE_PERIOD = "periodOpt";
63
64 private static final String DEFAULT_PERIOD_OPTION_1MIN = "1 MIN";
65
66 // Statistics period of statistics chart
67 private static final Map<String, Integer> PERIOD_OPTION_MAP =
68 ImmutableMap.<String, Integer>builder()
69 .put(DEFAULT_PERIOD_OPTION_1MIN, 12)
70 .put("3 MIN", 36)
71 .put("5 MIN", 60)
72 .put("30 MIN", 360)
73 .put("1 HOUR", 720)
74 .put("2 HOUR", 1440)
75 .put("6 HOUR", 4320)
76 .put("24 HOUR", 17280)
77 .build();
78
79 @Override
80 protected Collection<RequestHandler> createRequestHandlers() {
81 return ImmutableSet.of(
82 new ControlMessageRequest()
83 );
84 }
85
86 private final class ControlMessageRequest extends ChartRequestHandler {
87 private StatsFlowRuleAdminService statsFlowRuleService = null;
88 private Map<String, Queue<FlowInfo>> flowInfoMap = null;
89 private String currentFlowKey = null;
90 private String currentPeriod = DEFAULT_PERIOD_OPTION_1MIN;
91
92 private ControlMessageRequest() {
93 super(OST_DATA_REQ, OST_DATA_RESP, OSTS);
94 }
95
96 @Override
97 protected String[] getSeries() {
98 String[] series = {STAT_CURR_ACC_PACKET, STAT_PREV_ACC_PACKET,
99 STAT_CURR_ACC_BYTE, STAT_PREV_ACC_BYTE, STAT_ERROR_PACKET, STAT_DROP_PACKET};
100 return series;
101 }
102
103 @Override
104 protected void populateChart(ChartModel cm, ObjectNode payload) {
105 if (statsFlowRuleService == null) {
106 statsFlowRuleService = get(StatsFlowRuleAdminService.class);
107 }
108 if (flowInfoMap == null) {
109 flowInfoMap = statsFlowRuleService.getFlowInfoMap();
110 }
111
112 String flowKey = string(payload, JSON_NODE_FLOW);
113 String period = string(payload, JSON_NODE_PERIOD);
114
115 if (!Strings.isNullOrEmpty(flowKey) || !Strings.isNullOrEmpty(period)) {
116 if (!Strings.isNullOrEmpty(flowKey)) {
117 currentFlowKey = flowKey;
118 }
119 if (!Strings.isNullOrEmpty(period)) {
120 currentPeriod = period;
121 }
122
123 Queue<FlowInfo> flowInfoQ = flowInfoMap.get(currentFlowKey);
124
125 if (flowInfoQ == null) {
126 log.warn("No such flow key {}", currentFlowKey);
127 return;
128 } else {
129 populateMetrics(cm, flowInfoQ);
130 attachFlowList(cm);
131 attachPeriodList(cm);
132 }
133 } else {
134 flowInfoMap.keySet().forEach(key -> {
135 Queue<FlowInfo> flowInfoQ = flowInfoMap.get(key);
136 if (flowInfoQ == null) {
137 log.warn("Key {} is not found in FlowInfoMap", key);
138 return;
139 }
140 FlowInfo flowInfo = getLatestFlowInfo(flowInfoQ);
141
142 Map<String, Object> local = Maps.newHashMap();
143 local.put(LABEL, key);
144 local.put(STAT_CURR_ACC_PACKET, flowInfo.statsInfo().currAccPkts());
145 local.put(STAT_PREV_ACC_PACKET, flowInfo.statsInfo().prevAccPkts());
146 local.put(STAT_CURR_ACC_BYTE, flowInfo.statsInfo().currAccBytes());
147 local.put(STAT_PREV_ACC_BYTE, flowInfo.statsInfo().prevAccBytes());
148 local.put(STAT_ERROR_PACKET, flowInfo.statsInfo().errorPkts());
149 local.put(STAT_DROP_PACKET, flowInfo.statsInfo().dropPkts());
150
151 populateMetric(cm.addDataPoint(key), local);
152 });
153 }
154 }
155
156 private void populateMetrics(ChartModel cm, Queue<FlowInfo> flowInfoQ) {
157 FlowInfo[] flowInfos = flowInfoQ.toArray(new FlowInfo[flowInfoQ.size()]);
158 SimpleDateFormat form = new SimpleDateFormat(CHART_TIME_FORMAT);
159 int timeOffset = 0;
160 Integer dataPointCount = PERIOD_OPTION_MAP.get(currentPeriod);
161 if (dataPointCount != null) {
162 timeOffset = flowInfos.length - (int) dataPointCount;
163 if (timeOffset < 0) {
164 timeOffset = 0;
165 }
166 }
167
168 for (int idx = timeOffset; idx < flowInfos.length; idx++) {
169 Map<String, Object> local = Maps.newHashMap();
170 local.put(LABEL, form.format(new Date(flowInfos[idx].statsInfo().fstPktArrTime())));
171 local.put(STAT_CURR_ACC_PACKET, flowInfos[idx].statsInfo().currAccPkts());
172 local.put(STAT_PREV_ACC_PACKET, flowInfos[idx].statsInfo().prevAccPkts());
173 local.put(STAT_CURR_ACC_BYTE, flowInfos[idx].statsInfo().currAccBytes());
174 local.put(STAT_PREV_ACC_BYTE, flowInfos[idx].statsInfo().prevAccBytes());
175 local.put(STAT_ERROR_PACKET, flowInfos[idx].statsInfo().errorPkts());
176 local.put(STAT_DROP_PACKET, flowInfos[idx].statsInfo().dropPkts());
177 populateMetric(cm.addDataPoint(flowInfos[idx].uniqueFlowInfoKey()), local);
178 }
179 }
180
181 private void populateMetric(ChartModel.DataPoint dataPoint,
182 Map<String, Object> data) {
183 data.forEach(dataPoint::data);
184 }
185
186 private void attachFlowList(ChartModel cm) {
187 ArrayNode array = arrayNode();
188 flowInfoMap.keySet().forEach(key -> {
189 array.add(key);
190 });
191 cm.addAnnotation(ANNOT_FLOW_IDS, array);
192 }
193
194 private void attachPeriodList(ChartModel cm) {
195 ArrayNode array = arrayNode();
196 PERIOD_OPTION_MAP.keySet().forEach(period -> {
197 array.add(period);
198 });
199 cm.addAnnotation(ANNOT_PERIOD_OPTIONS, array);
200 }
201
202 private FlowInfo getLatestFlowInfo(Queue<FlowInfo> flowInfoQ) {
203 FlowInfo[] flowInfos = flowInfoQ.toArray(new FlowInfo[flowInfoQ.size()]);
204 return flowInfos[flowInfos.length - 1];
205 }
206 }
207}