blob: 69423ca534d50e1b9005b818b6c0dcab3c4da5ae [file] [log] [blame]
boyoung21c5f5f42018-09-27 20:29:41 +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.impl;
17
boyoung2a8549d22018-11-23 20:42:37 +090018import io.prometheus.client.Gauge;
19import org.onlab.packet.TpPort;
boyoung21c5f5f42018-09-27 20:29:41 +090020import org.onosproject.openstacktelemetry.api.FlowInfo;
21import org.onosproject.openstacktelemetry.api.OpenstackTelemetryService;
22import org.onosproject.openstacktelemetry.api.PrometheusTelemetryAdminService;
23import org.onosproject.openstacktelemetry.api.config.PrometheusTelemetryConfig;
24import org.onosproject.openstacktelemetry.api.config.TelemetryConfig;
Ray Milkeydf521292018-10-04 15:13:33 -070025import org.osgi.service.component.annotations.Activate;
26import org.osgi.service.component.annotations.Component;
27import org.osgi.service.component.annotations.Deactivate;
28import org.osgi.service.component.annotations.Reference;
29import org.osgi.service.component.annotations.ReferenceCardinality;
boyoung21c5f5f42018-09-27 20:29:41 +090030import org.slf4j.Logger;
31import org.slf4j.LoggerFactory;
32
33import io.prometheus.client.Counter;
34import io.prometheus.client.exporter.MetricsServlet;
35import org.eclipse.jetty.server.Server;
36import org.eclipse.jetty.servlet.ServletContextHandler;
37import org.eclipse.jetty.servlet.ServletHolder;
boyoung2a8549d22018-11-23 20:42:37 +090038
39import java.util.Arrays;
boyoung21c5f5f42018-09-27 20:29:41 +090040import java.util.Set;
41
42/**
43 * Prometheus telemetry manager.
44 */
boyoung2a8549d22018-11-23 20:42:37 +090045@Component(immediate = true, service = PrometheusTelemetryAdminService.class)
boyoung21c5f5f42018-09-27 20:29:41 +090046public class PrometheusTelemetryManager implements PrometheusTelemetryAdminService {
47
48 private final Logger log = LoggerFactory.getLogger(getClass());
49
50 private Server prometheusExporter;
51
boyoung2a8549d22018-11-23 20:42:37 +090052 private static final String FLOW_TYPE = "flowType";
53 private static final String DEVICE_ID = "deviceId";
54 private static final String INPUT_INTERFACE_ID = "inputInterfaceId";
55 private static final String OUTPUT_INTERFACE_ID = "outputInterfaceId";
56 private static final String VLAN_ID = "vlanId";
57 private static final String VXLAN_ID = "vxlanId";
58 private static final String SRC_IP = "srcIp";
59 private static final String DST_IP = "dstIp";
60 private static final String SRC_PORT = "srcPort";
61 private static final String DST_PORT = "dstPort";
62 private static final String PROTOCOL = "protocol";
boyoung21c5f5f42018-09-27 20:29:41 +090063
boyoung2a8549d22018-11-23 20:42:37 +090064 private static final String[] LABEL_TAGS = {
65 FLOW_TYPE, DEVICE_ID, INPUT_INTERFACE_ID, OUTPUT_INTERFACE_ID,
66 VLAN_ID, VXLAN_ID, SRC_IP, DST_IP, SRC_PORT, DST_PORT, PROTOCOL
67 };
boyoung21c5f5f42018-09-27 20:29:41 +090068
boyoung2a8549d22018-11-23 20:42:37 +090069 private static final String STAT_NAME_VM2VM_BYTE = "vm2vm_byte";
70 private static final String STAT_NAME_VM2VM_BYTE_PREV = "vm2vm_byte_prev";
71 private static final String STAT_NAME_VM2VM_BYTE_CURR = "vm2vm_byte_curr";
72 private static final String STAT_NAME_VM2VM_PKT = "vm2vm_pkt";
73 private static final String STAT_NAME_VM2VM_PKT_PREV = "vm2vm_pkt_prev";
74 private static final String STAT_NAME_VM2VM_PKT_CURR = "vm2vm_pkt_curr";
75 private static final String STAT_NAME_ERROR_PKT = "error_pkt";
76 private static final String STAT_NAME_DROP_PKT = "drop_pkt";
boyoung21c5f5f42018-09-27 20:29:41 +090077
boyoung2a8549d22018-11-23 20:42:37 +090078 private static final String HELP_MSG_VM2VM_BYTE =
79 "SONA flow bytes statistics for VM to VM";
80 private static final String HELP_MSG_VM2VM_BYTE_PREV =
81 HELP_MSG_VM2VM_BYTE + " [Accumulated previous byte]";
82 private static final String HELP_MSG_VM2VM_BYTE_CURR =
83 HELP_MSG_VM2VM_BYTE + " [Accumulated current byte]";
84 private static final String HELP_MSG_VM2VM_PKT =
85 "SONA flow packets statistics for VM to VM";
86 private static final String HELP_MSG_VM2VM_PKT_PREV =
87 HELP_MSG_VM2VM_PKT + " [Accumulated previous pkt]";
88 private static final String HELP_MSG_VM2VM_PKT_CURR =
89 HELP_MSG_VM2VM_PKT + " [Accumulated current pkt]";
90 private static final String HELP_MSG_ERROR = "SONA error statistics";
91 private static final String HELP_MSG_DROP = "SONA drop statistics";
boyoung21c5f5f42018-09-27 20:29:41 +090092
boyoung2a8549d22018-11-23 20:42:37 +090093 private static Gauge byteVM2VM = Gauge.build()
94 .name(STAT_NAME_VM2VM_BYTE)
95 .help(HELP_MSG_VM2VM_BYTE)
96 .labelNames(LABEL_TAGS)
97 .register();
98 private static Gauge byteVM2VMPrev = Gauge.build()
99 .name(STAT_NAME_VM2VM_BYTE_PREV)
100 .help(HELP_MSG_VM2VM_BYTE_PREV)
101 .labelNames(LABEL_TAGS)
102 .register();
103 private static Gauge byteVM2VMCurr = Gauge.build()
104 .name(STAT_NAME_VM2VM_BYTE_CURR)
105 .help(HELP_MSG_VM2VM_BYTE_CURR)
106 .labelNames(LABEL_TAGS)
107 .register();
108 private static Gauge pktVM2VM = Gauge.build()
109 .name(STAT_NAME_VM2VM_PKT)
110 .help(HELP_MSG_VM2VM_PKT)
111 .labelNames(LABEL_TAGS)
112 .register();
113 private static Gauge pktVM2VMPrev = Gauge.build()
114 .name(STAT_NAME_VM2VM_PKT_PREV)
115 .help(HELP_MSG_VM2VM_PKT_PREV)
116 .labelNames(LABEL_TAGS)
117 .register();
118 private static Gauge pktVM2VMCurr = Gauge.build()
119 .name(STAT_NAME_VM2VM_PKT_CURR)
120 .help(HELP_MSG_VM2VM_PKT_CURR)
121 .labelNames(LABEL_TAGS)
122 .register();
123 private static Counter pktError = Counter.build()
124 .name(STAT_NAME_ERROR_PKT)
125 .help(HELP_MSG_ERROR)
126 .labelNames(LABEL_TAGS)
127 .register();
128 private static Counter pktDrop = Counter.build()
129 .name(STAT_NAME_DROP_PKT)
130 .help(HELP_MSG_DROP)
131 .labelNames(LABEL_TAGS)
132 .register();
boyoung21c5f5f42018-09-27 20:29:41 +0900133
Ray Milkeydf521292018-10-04 15:13:33 -0700134 @Reference(cardinality = ReferenceCardinality.MANDATORY)
boyoung21c5f5f42018-09-27 20:29:41 +0900135 protected OpenstackTelemetryService openstackTelemetryService;
136
137 @Activate
138 protected void activate() {
139 openstackTelemetryService.addTelemetryService(this);
140 log.info("Started");
141 }
142
143 @Deactivate
144 protected void deactivate() {
145 stop();
146 openstackTelemetryService.removeTelemetryService(this);
147 log.info("Stopped");
148 }
149
150 @Override
151 public void start(TelemetryConfig config) {
152 log.info("Prometheus exporter starts.");
153
154 PrometheusTelemetryConfig prometheusConfig = (PrometheusTelemetryConfig) config;
155
156 try {
boyoung21c5f5f42018-09-27 20:29:41 +0900157 prometheusExporter = new Server(prometheusConfig.port());
158 ServletContextHandler context = new ServletContextHandler();
159 context.setContextPath("/");
160 prometheusExporter.setHandler(context);
161 context.addServlet(new ServletHolder(new MetricsServlet()), "/metrics");
boyoung2a8549d22018-11-23 20:42:37 +0900162 log.info("Prometeus server start (Server port:{})", prometheusConfig.port());
boyoung21c5f5f42018-09-27 20:29:41 +0900163 prometheusExporter.start();
164 } catch (Exception ex) {
165 log.warn("Exception: {}", ex.toString());
166 }
167 }
168
169 @Override
170 public void stop() {
171 try {
172 prometheusExporter.stop();
173 } catch (Exception ex) {
174 log.warn("Exception: {}", ex.toString());
175 }
176 log.info("Prometheus exporter has stopped");
177 }
178
179 @Override
180 public void restart(TelemetryConfig config) {
181 stop();
182 start(config);
183 }
184
185 @Override
186 public void publish(Set<FlowInfo> flowInfos) {
boyoung2a8549d22018-11-23 20:42:37 +0900187 if (flowInfos.isEmpty()) {
188 log.debug("No FlowInfo record to publish");
boyoung21c5f5f42018-09-27 20:29:41 +0900189 return;
190 }
191
192 long flowByte;
193 int flowPkt;
boyoung2a8549d22018-11-23 20:42:37 +0900194 String[] labelValues;
195
boyoung21c5f5f42018-09-27 20:29:41 +0900196 for (FlowInfo flowInfo: flowInfos) {
197 flowByte = flowInfo.statsInfo().currAccBytes() - flowInfo.statsInfo().prevAccBytes();
198 flowPkt = flowInfo.statsInfo().currAccPkts() - flowInfo.statsInfo().prevAccPkts();
boyoung2a8549d22018-11-23 20:42:37 +0900199 labelValues = getLabelValues(flowInfo);
200 byteVM2VM.labels(labelValues).set(flowByte);
201 byteVM2VMPrev.labels(labelValues).set(flowInfo.statsInfo().prevAccBytes());
202 byteVM2VMCurr.labels(labelValues).set(flowInfo.statsInfo().currAccBytes());
203 pktVM2VM.labels(labelValues).set(flowPkt);
204 pktVM2VMPrev.labels(labelValues).set(flowInfo.statsInfo().prevAccPkts());
205 pktVM2VMCurr.labels(labelValues).set(flowInfo.statsInfo().currAccPkts());
206 pktError.labels(labelValues).inc(flowInfo.statsInfo().errorPkts());
207 pktDrop.labels(labelValues).inc(flowInfo.statsInfo().dropPkts());
boyoung21c5f5f42018-09-27 20:29:41 +0900208 }
209 }
210
boyoung2a8549d22018-11-23 20:42:37 +0900211 private String[] getLabelValues(FlowInfo flowInfo) {
212 String[] labelValues = new String[LABEL_TAGS.length];
213
214 labelValues[Arrays.asList(LABEL_TAGS).indexOf(FLOW_TYPE)]
215 = String.valueOf(flowInfo.flowType());
216 labelValues[Arrays.asList(LABEL_TAGS).indexOf(DEVICE_ID)]
217 = flowInfo.deviceId().toString();
218 labelValues[Arrays.asList(LABEL_TAGS).indexOf(INPUT_INTERFACE_ID)]
219 = String.valueOf(flowInfo.inputInterfaceId());
220 labelValues[Arrays.asList(LABEL_TAGS).indexOf(OUTPUT_INTERFACE_ID)]
221 = String.valueOf(flowInfo.outputInterfaceId());
222 labelValues[Arrays.asList(LABEL_TAGS).indexOf(VXLAN_ID)]
223 = String.valueOf(flowInfo.vxlanId());
224 labelValues[Arrays.asList(LABEL_TAGS).indexOf(SRC_IP)]
225 = flowInfo.srcIp().toString();
226 labelValues[Arrays.asList(LABEL_TAGS).indexOf(DST_IP)]
227 = flowInfo.dstIp().toString();
228 labelValues[Arrays.asList(LABEL_TAGS).indexOf(SRC_PORT)]
229 = getTpPort(flowInfo.srcPort());
230 labelValues[Arrays.asList(LABEL_TAGS).indexOf(DST_PORT)]
231 = getTpPort(flowInfo.dstPort());
232 labelValues[Arrays.asList(LABEL_TAGS).indexOf(PROTOCOL)]
233 = String.valueOf(flowInfo.protocol());
234 if (flowInfo.vlanId() != null) {
235 labelValues[Arrays.asList(LABEL_TAGS).indexOf(VLAN_ID)]
236 = flowInfo.vlanId().toString();
237 }
238 return labelValues;
239 }
240
241 private String getTpPort(TpPort tpPort) {
242 if (tpPort == null) {
243 return "";
244 }
245 return tpPort.toString();
246 }
247
boyoung21c5f5f42018-09-27 20:29:41 +0900248 @Override
249 public boolean isRunning() {
boyoung21c5f5f42018-09-27 20:29:41 +0900250 return prometheusExporter.isRunning();
251 }
252}