blob: 8301b0c2b92bdd330ec357e7a00e636d2daba731 [file] [log] [blame]
Katri Turunen4b74f012019-08-15 10:49:36 +03001/*
2 * Copyright (c) 2019 AT&T Intellectual Property.
3 * Copyright (c) 2018-2019 Nokia.
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 */
17
18package main
19
20import (
Katri Turunen412df962019-09-16 08:48:18 +030021 "encoding/json"
Katri Turunen4b74f012019-08-15 10:49:36 +030022 "io"
Katri Turunen66b78132019-09-02 10:28:52 +030023 "os"
24 "strconv"
Katri Turunen412df962019-09-16 08:48:18 +030025 "time"
Roni Riskafc77ebb2019-09-26 08:20:44 +030026
27 "gopkg.in/yaml.v2"
Katri Turunen4b74f012019-08-15 10:49:36 +030028)
29
30func basicVespaConf() VESAgentConfiguration {
Katri Turunen412df962019-09-16 08:48:18 +030031 var vespaconf = VESAgentConfiguration{
Katri Turunen4b74f012019-08-15 10:49:36 +030032 DataDir: "/tmp/data",
33 Debug: false,
Katri Turunen412df962019-09-16 08:48:18 +030034 Event: EventConfiguration{
35 VNFName: "vespa-demo", // XXX
Katri Turunen4b74f012019-08-15 10:49:36 +030036 ReportingEntityID: "1af5bfa9-40b4-4522-b045-40e54f0310f", // XXX
Katri Turunen412df962019-09-16 08:48:18 +030037 MaxSize: 2000000,
38 NfNamingCode: "hsxp",
39 NfcNamingCodes: []NfcNamingCode{
40 NfcNamingCode{
41 Type: "oam",
42 Vnfcs: []string{"lr-ope-0", "lr-ope-1", "lr-ope-2"},
Katri Turunen4b74f012019-08-15 10:49:36 +030043 },
Katri Turunen412df962019-09-16 08:48:18 +030044 NfcNamingCode{
45 Type: "etl",
46 Vnfcs: []string{"lr-pro-0", "lr-pro-1"},
Katri Turunen4b74f012019-08-15 10:49:36 +030047 },
48 },
49 RetryInterval: time.Second * 5,
Katri Turunen412df962019-09-16 08:48:18 +030050 MaxMissed: 2,
Katri Turunen4b74f012019-08-15 10:49:36 +030051 },
Katri Turunen412df962019-09-16 08:48:18 +030052 Measurement: MeasurementConfiguration{
53 DomainAbbreviation: "Mvfs",
Katri Turunen4b74f012019-08-15 10:49:36 +030054 MaxBufferingDuration: time.Hour,
Katri Turunen412df962019-09-16 08:48:18 +030055 Prometheus: PrometheusConfig{
56 Timeout: time.Second * 30,
Katri Turunen4b74f012019-08-15 10:49:36 +030057 KeepAlive: time.Second * 30,
Katri Turunen412df962019-09-16 08:48:18 +030058 Rules: MetricRules{
59 DefaultValues: &MetricRule{
Katri Turunen4b74f012019-08-15 10:49:36 +030060 VMIDLabel: "'{{.labels.instance}}'",
61 },
62 },
63 },
64 },
65 }
66 return vespaconf
67}
68
Roni Riskafc77ebb2019-09-26 08:20:44 +030069// AppMetricsStruct contains xapplication metrics definition
Katri Turunen412df962019-09-16 08:48:18 +030070type AppMetricsStruct struct {
71 ObjectName string
72 ObjectInstance string
Katri Turunen412df962019-09-16 08:48:18 +030073}
74
Roni Riskafc77ebb2019-09-26 08:20:44 +030075// AppMetrics contains metrics definitions for all Xapps
Katri Turunen412df962019-09-16 08:48:18 +030076type AppMetrics map[string]AppMetricsStruct
77
78// Parses the metrics data from an array of bytes, which is expected to contain a JSON
79// array with structs of the following format:
80//
81// { ...
82// "config" : {
83// "metrics": [
84// { "name": "...", "objectName": "...", "objectInstamce": "..." },
85// ...
86// ]
87// }
88// }
89func parseMetricsFromXAppDescriptor(descriptor []byte, appMetrics AppMetrics) AppMetrics {
90 var desc []map[string]interface{}
91 json.Unmarshal(descriptor, &desc)
92
93 for _, app := range desc {
Roni Riskafc77ebb2019-09-26 08:20:44 +030094 config, configOk := app["config"]
95 if configOk {
96 metrics, metricsOk := config.(map[string]interface{})["metrics"]
97 if metricsOk {
Katri Turunen412df962019-09-16 08:48:18 +030098 parseMetricsRules(metrics.([]interface{}), appMetrics)
99 }
100 }
101 }
102 return appMetrics
103}
104
105// Parses the metrics data from an array of interfaces, which are expected to be maps
106// of the following format:
107// { "name": xxx, "objectName": yyy, "objectInstance": zzz }
108// Entries, which do not have all the necessary fields, are ignored.
109func parseMetricsRules(metricsMap []interface{}, appMetrics AppMetrics) AppMetrics {
110 for _, element := range metricsMap {
Roni Riskafc77ebb2019-09-26 08:20:44 +0300111 name, nameOk := element.(map[string]interface{})["name"].(string)
112 if nameOk {
113 _, alreadyFound := appMetrics[name]
114 objectName, objectNameOk := element.(map[string]interface{})["objectName"].(string)
115 objectInstance, objectInstanceOk := element.(map[string]interface{})["objectInstance"].(string)
116 if !alreadyFound && objectNameOk && objectInstanceOk {
Katri Turunen412df962019-09-16 08:48:18 +0300117 appMetrics[name] = AppMetricsStruct{objectName, objectInstance}
118 logger.Info("parsed counter %s %s %s", name, objectName, objectInstance)
119 }
Roni Riskafc77ebb2019-09-26 08:20:44 +0300120 if alreadyFound {
Katri Turunen412df962019-09-16 08:48:18 +0300121 logger.Info("skipped duplicate counter %s", name)
122 }
123 }
124 }
125 return appMetrics
126}
127
128func getRules(vespaconf *VESAgentConfiguration, xAppConfig []byte) {
129 appMetrics := make(AppMetrics)
130 parseMetricsFromXAppDescriptor(xAppConfig, appMetrics)
131
Roni Riskafc77ebb2019-09-26 08:20:44 +0300132 makeRule := func(expr string, objName string, objInstance string) MetricRule {
Katri Turunen412df962019-09-16 08:48:18 +0300133 return MetricRule{
134 Target: "AdditionalObjects",
135 Expr: expr,
Roni Riskafc77ebb2019-09-26 08:20:44 +0300136 ObjectInstance: objInstance,
137 ObjectName: objName,
Katri Turunen412df962019-09-16 08:48:18 +0300138 ObjectKeys: []Label{
139 Label{
Katri Turunen4b74f012019-08-15 10:49:36 +0300140 Name: "ricComponentName",
Katri Turunen412df962019-09-16 08:48:18 +0300141 Expr: "'{{.labels.kubernetes_name}}'",
Katri Turunen4b74f012019-08-15 10:49:36 +0300142 },
143 },
144 }
145 }
Katri Turunen412df962019-09-16 08:48:18 +0300146 var metricsMap map[string][]interface{}
147 json.Unmarshal(xAppConfig, &metricsMap)
148 metrics := parseMetricsRules(metricsMap["metrics"], appMetrics)
Katri Turunen4b74f012019-08-15 10:49:36 +0300149
Katri Turunen412df962019-09-16 08:48:18 +0300150 vespaconf.Measurement.Prometheus.Rules.Metrics = make([]MetricRule, 0, len(metrics))
151 for key, value := range metrics {
152 vespaconf.Measurement.Prometheus.Rules.Metrics = append(vespaconf.Measurement.Prometheus.Rules.Metrics, makeRule(key, value.ObjectName, value.ObjectInstance))
153 }
154 if len(vespaconf.Measurement.Prometheus.Rules.Metrics) == 0 {
155 logger.Info("vespa config with empty metrics")
156 }
Katri Turunen4b74f012019-08-15 10:49:36 +0300157}
158
Katri Turunen66b78132019-09-02 10:28:52 +0300159func getCollectorConfiguration(vespaconf *VESAgentConfiguration) {
160 vespaconf.PrimaryCollector.User = os.Getenv("VESMGR_PRICOLLECTOR_USER")
161 vespaconf.PrimaryCollector.Password = os.Getenv("VESMGR_PRICOLLECTOR_PASSWORD")
162 vespaconf.PrimaryCollector.PassPhrase = os.Getenv("VESMGR_PRICOLLECTOR_PASSPHRASE")
163 vespaconf.PrimaryCollector.FQDN = os.Getenv("VESMGR_PRICOLLECTOR_ADDR")
164 vespaconf.PrimaryCollector.ServerRoot = os.Getenv("VESMGR_PRICOLLECTOR_SERVERROOT")
165 vespaconf.PrimaryCollector.Topic = os.Getenv("VESMGR_PRICOLLECTOR_TOPIC")
Roni Riskafc77ebb2019-09-26 08:20:44 +0300166 portStr := os.Getenv("VESMGR_PRICOLLECTOR_PORT")
167 if portStr == "" {
Katri Turunen66b78132019-09-02 10:28:52 +0300168 vespaconf.PrimaryCollector.Port = 8443
169 } else {
Roni Riskafc77ebb2019-09-26 08:20:44 +0300170 port, _ := strconv.Atoi(portStr)
Katri Turunen66b78132019-09-02 10:28:52 +0300171 vespaconf.PrimaryCollector.Port = port
172 }
Roni Riskafc77ebb2019-09-26 08:20:44 +0300173 secureStr := os.Getenv("VESMGR_PRICOLLECTOR_SECURE")
174 if secureStr == "true" {
Katri Turunen66b78132019-09-02 10:28:52 +0300175 vespaconf.PrimaryCollector.Secure = true
176 } else {
177 vespaconf.PrimaryCollector.Secure = false
178 }
179}
180
Katri Turunen412df962019-09-16 08:48:18 +0300181func createVespaConfig(writer io.Writer, xAppStatus []byte) {
Katri Turunen4b74f012019-08-15 10:49:36 +0300182 vespaconf := basicVespaConf()
Katri Turunen412df962019-09-16 08:48:18 +0300183 getRules(&vespaconf, xAppStatus)
Katri Turunen66b78132019-09-02 10:28:52 +0300184 getCollectorConfiguration(&vespaconf)
Katri Turunen4b74f012019-08-15 10:49:36 +0300185 err := yaml.NewEncoder(writer).Encode(vespaconf)
186 if err != nil {
187 logger.Error("Cannot write vespa conf file: %s", err.Error())
188 return
189 }
Katri Turunen66b78132019-09-02 10:28:52 +0300190}