From: Mohamed Abukar Date: Thu, 22 Oct 2020 16:31:01 +0000 (+0300) Subject: Additions to measurements X-Git-Tag: 0.7.4~17 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=070b3653202d9db994834cbdc175044a80e8278a;p=ric-plt%2Fvespamgr.git Additions to measurements Change-Id: Idba0234209e57ed02c93b8aa027f90c6c6d5ddfb Signed-off-by: Mohamed Abukar --- diff --git a/cmd/vesmgr/config.go b/cmd/vesmgr/config.go index e6e48d9..b79d19b 100755 --- a/cmd/vesmgr/config.go +++ b/cmd/vesmgr/config.go @@ -23,6 +23,7 @@ package main import ( "encoding/json" + "fmt" "io" "io/ioutil" "os" @@ -71,9 +72,9 @@ func basicVespaConf() VESAgentConfiguration { ReportingEntityID: readSystemUUID(), MaxSize: 2000000, NfNamingCode: getNFNamingCode(), - NfcNamingCodes: []NfcNamingCode{}, - RetryInterval: time.Second * 5, - MaxMissed: 2, + NfcNamingCodes: []NfcNamingCode{}, + RetryInterval: time.Second * 5, + MaxMissed: 2, }, Measurement: MeasurementConfiguration{ // Domain abbreviation has to be set to “Mvfs” for VES 5.3, @@ -96,10 +97,13 @@ func basicVespaConf() VESAgentConfiguration { // AppMetricsStruct contains xapplication metrics definition type AppMetricsStruct struct { + MoId string + MeasType string + MeasId string + MeasInterval string ObjectName string ObjectInstance string - MeasId string - MeasObject string + CounterId string } // AppMetrics contains metrics definitions for all Xapps @@ -138,14 +142,18 @@ func parseMetricsFromXAppDescriptor(descriptor []byte, appMetrics AppMetrics) Ap } for _, m := range measurements.([]interface{}) { + moId, moIdOk := m.(map[string]interface{})["moId"].(string) + measType, measTypeOk := m.(map[string]interface{})["measType"].(string) measId, measIdOk := m.(map[string]interface{})["measId"].(string) - measObject, objectOk := m.(map[string]interface{})["object"].(string) + measInterval, measIntervalOk := m.(map[string]interface{})["measInterval"].(string) metrics, metricsOk := m.(map[string]interface{})["metrics"] - if !metricsOk || !measIdOk || !objectOk { - logger.Info("No metrics found for measId=%s Object=%s", measId, measObject) + if !metricsOk || !measTypeOk || !measIdOk || !moIdOk || !measIntervalOk { + logger.Info("No metrics found for moId=%s measType=%s measId=%s measInterval=%s", moId, measId, measType, measInterval) continue } - parseMetricsRules(metrics.([]interface{}), appMetrics, measId, measObject) + logger.Info("Parsed measurement: moId=%s type=%s id=%s interval=%s", moId, measType, measId, measInterval) + + parseMetricsRules(metrics.([]interface{}), appMetrics, moId, measType, measId, measInterval) } } return appMetrics @@ -155,16 +163,17 @@ func parseMetricsFromXAppDescriptor(descriptor []byte, appMetrics AppMetrics) Ap // of the following format: // { "name": xxx, "objectName": yyy, "objectInstance": zzz } // Entries, which do not have all the necessary fields, are ignored. -func parseMetricsRules(metricsMap []interface{}, appMetrics AppMetrics, measId, measObject string) AppMetrics { +func parseMetricsRules(metricsMap []interface{}, appMetrics AppMetrics, moId, measType, measId, measInterval string) AppMetrics { for _, element := range metricsMap { name, nameOk := element.(map[string]interface{})["name"].(string) if nameOk { _, alreadyFound := appMetrics[name] objectName, objectNameOk := element.(map[string]interface{})["objectName"].(string) objectInstance, objectInstanceOk := element.(map[string]interface{})["objectInstance"].(string) - if !alreadyFound && objectNameOk && objectInstanceOk { - appMetrics[name] = AppMetricsStruct{objectName, objectInstance, measId, measObject} - logger.Info("parsed counter %s %s %s", name, objectName, objectInstance) + counterId, counterIdOk := element.(map[string]interface{})["counterId"].(string) + if !alreadyFound && objectNameOk && objectInstanceOk && counterIdOk { + appMetrics[name] = AppMetricsStruct{moId, measType, measId, measInterval, objectName, objectInstance, counterId} + logger.Info("Parsed counter name=%s %s/%s M%sC%s", name, objectName, objectInstance, measId, counterId) } if alreadyFound { logger.Info("skipped duplicate counter %s", name) @@ -174,26 +183,19 @@ func parseMetricsRules(metricsMap []interface{}, appMetrics AppMetrics, measId, return appMetrics } -func getRules(vespaconf *VESAgentConfiguration, xAppConfig []byte) { +func getRules(vespaconf *VESAgentConfiguration, xAppConfig []byte) bool { makeRule := func(expr string, value AppMetricsStruct) MetricRule { return MetricRule{ Target: "AdditionalObjects", Expr: expr, - ObjectInstance: value.ObjectInstance, + ObjectInstance: fmt.Sprintf("%s:%s", value.ObjectInstance, value.CounterId), ObjectName: value.ObjectName, ObjectKeys: []Label{ - Label{ - Name: "ricComponentName", - Expr: "'{{.labels.kubernetes_name}}'", - }, - Label{ - Name: "measObject", - Expr: value.MeasObject, - }, - Label{ - Name: "measId", - Expr: value.MeasId, - }, + {Name: "ricComponentName", Expr: "'{{.labels.kubernetes_name}}'"}, + {Name: "moId", Expr: value.MoId}, + {Name: "measType", Expr: value.MeasType}, + {Name: "measId", Expr: value.MeasId}, + {Name: "measInterval", Expr: value.MeasInterval}, }, } } @@ -207,6 +209,8 @@ func getRules(vespaconf *VESAgentConfiguration, xAppConfig []byte) { if len(vespaconf.Measurement.Prometheus.Rules.Metrics) == 0 { logger.Info("vespa config with empty metrics") } + + return len(vespaconf.Measurement.Prometheus.Rules.Metrics) > 0 } func getCollectorConfiguration(vespaconf *VESAgentConfiguration) { @@ -217,12 +221,14 @@ func getCollectorConfiguration(vespaconf *VESAgentConfiguration) { vespaconf.PrimaryCollector.ServerRoot = os.Getenv("VESMGR_PRICOLLECTOR_SERVERROOT") vespaconf.PrimaryCollector.Topic = os.Getenv("VESMGR_PRICOLLECTOR_TOPIC") portStr := os.Getenv("VESMGR_PRICOLLECTOR_PORT") + if portStr == "" { vespaconf.PrimaryCollector.Port = 8443 } else { port, _ := strconv.Atoi(portStr) vespaconf.PrimaryCollector.Port = port } + secureStr := os.Getenv("VESMGR_PRICOLLECTOR_SECURE") if secureStr == "true" { vespaconf.PrimaryCollector.Secure = true @@ -233,8 +239,11 @@ func getCollectorConfiguration(vespaconf *VESAgentConfiguration) { func createVespaConfig(writer io.Writer, xAppStatus []byte) { vespaconf := basicVespaConf() + getRules(&vespaconf, xAppStatus) + getCollectorConfiguration(&vespaconf) + err := yaml.NewEncoder(writer).Encode(vespaconf) if err != nil { logger.Error("Cannot write vespa conf file: %s", err.Error()) diff --git a/cmd/vesmgr/config_test.go b/cmd/vesmgr/config_test.go index ac1b7d6..da135b4 100755 --- a/cmd/vesmgr/config_test.go +++ b/cmd/vesmgr/config_test.go @@ -157,15 +157,15 @@ func metricsStringToInterfaceArray(metrics string) []interface{} { func TestParseMetricsRules(t *testing.T) { metricsJSON := `{"metrics": [ - { "name": "ricxapp_RMR_Received", "objectName": "ricxappRMRreceivedCounter", "objectInstance": "ricxappRMRReceived" }, - { "name": "ricxapp_RMR_ReceiveError", "objectName": "ricxappRMRReceiveErrorCounter", "objectInstance": "ricxappRMRReceiveError" }, - { "name": "ricxapp_RMR_Transmitted", "objectName": "ricxappRMRTransmittedCounter", "objectInstance": "ricxappRMRTransmitted" }, - { "name": "ricxapp_RMR_TransmitError", "objectName": "ricxappRMRTransmitErrorCounter", "objectInstance": "ricxappRMRTransmitError" }, - { "name": "ricxapp_SDL_Stored", "objectName": "ricxappSDLStoredCounter", "objectInstance": "ricxappSDLStored" }, - { "name": "ricxapp_SDL_StoreError", "objectName": "ricxappSDLStoreErrorCounter", "objectInstance": "ricxappSDLStoreError" } ]}` + { "name": "ricxapp_RMR_Received", "objectName": "ricxappRMRreceivedCounter", "objectInstance": "ricxappRMRReceived", "counterId": "0011" }, + { "name": "ricxapp_RMR_ReceiveError", "objectName": "ricxappRMRReceiveErrorCounter", "objectInstance": "ricxappRMRReceiveError", "counterId": "0011" }, + { "name": "ricxapp_RMR_Transmitted", "objectName": "ricxappRMRTransmittedCounter", "objectInstance": "ricxappRMRTransmitted", "counterId": "0011" }, + { "name": "ricxapp_RMR_TransmitError", "objectName": "ricxappRMRTransmitErrorCounter", "objectInstance": "ricxappRMRTransmitError", "counterId": "0011" }, + { "name": "ricxapp_SDL_Stored", "objectName": "ricxappSDLStoredCounter", "objectInstance": "ricxappSDLStored", "counterId": "0011" }, + { "name": "ricxapp_SDL_StoreError", "objectName": "ricxappSDLStoreErrorCounter", "objectInstance": "ricxappSDLStoreError", "counterId": "0011" } ]}` appMetrics := make(AppMetrics) m := metricsStringToInterfaceArray(metricsJSON) - appMetrics = parseMetricsRules(m, appMetrics, "M1234", "App-1") + appMetrics = parseMetricsRules(m, appMetrics, "SEP/XAPP", "X2", "1234", "60") assert.Len(t, appMetrics, 6) assert.Equal(t, "ricxappRMRreceivedCounter", appMetrics["ricxapp_RMR_Received"].ObjectName) assert.Equal(t, "ricxappRMRTransmitErrorCounter", appMetrics["ricxapp_RMR_TransmitError"].ObjectName) @@ -176,16 +176,16 @@ func TestParseMetricsRulesNoMetrics(t *testing.T) { appMetrics := make(AppMetrics) metricsJSON := `{"metrics": []` m := metricsStringToInterfaceArray(metricsJSON) - appMetrics = parseMetricsRules(m, appMetrics, "M1234", "App-1") + appMetrics = parseMetricsRules(m, appMetrics, "SEP/XAPP", "X2", "1234", "60") assert.Empty(t, appMetrics) } func TestParseMetricsRulesAdditionalFields(t *testing.T) { appMetrics := make(AppMetrics) metricsJSON := `{"metrics": [ - { "additionalField": "valueIgnored", "name": "ricxapp_RMR_Received", "objectName": "ricxappRMRreceivedCounter", "objectInstance": "ricxappRMRReceived" }]}` + { "additionalField": "valueIgnored", "name": "ricxapp_RMR_Received", "objectName": "ricxappRMRreceivedCounter", "objectInstance": "ricxappRMRReceived", "counterId": "0011" }]}` m := metricsStringToInterfaceArray(metricsJSON) - appMetrics = parseMetricsRules(m, appMetrics, "M1234", "App-1") + appMetrics = parseMetricsRules(m, appMetrics, "SEP/XAPP", "X2", "1234", "60") assert.Len(t, appMetrics, 1) assert.Equal(t, "ricxappRMRreceivedCounter", appMetrics["ricxapp_RMR_Received"].ObjectName) assert.Equal(t, "ricxappRMRReceived", appMetrics["ricxapp_RMR_Received"].ObjectInstance) @@ -194,11 +194,11 @@ func TestParseMetricsRulesAdditionalFields(t *testing.T) { func TestParseMetricsRulesMissingFields(t *testing.T) { appMetrics := make(AppMetrics) metricsJSON := `{"metrics": [ - { "name": "ricxapp_RMR_Received", "objectName": "ricxappRMRreceivedCounter", "objectInstance": "ricxappRMRReceived" }, + { "name": "ricxapp_RMR_Received", "objectName": "ricxappRMRreceivedCounter", "objectInstance": "ricxappRMRReceived", "counterId": "0011" }, { "name": "ricxapp_RMR_ReceiveError", "objectInstance": "ricxappRMRReceiveError" }, - { "name": "ricxapp_RMR_Transmitted", "objectName": "ricxappRMRTransmittedCounter", "objectInstance": "ricxappRMRTransmitted" }]}` + { "name": "ricxapp_RMR_Transmitted", "objectName": "ricxappRMRTransmittedCounter", "objectInstance": "ricxappRMRTransmitted", "counterId": "0011" }]}` m := metricsStringToInterfaceArray(metricsJSON) - appMetrics = parseMetricsRules(m, appMetrics, "M1234", "App-1") + appMetrics = parseMetricsRules(m, appMetrics, "SEP/XAPP", "X2", "1234", "60") assert.Len(t, appMetrics, 2) assert.Equal(t, "ricxappRMRreceivedCounter", appMetrics["ricxapp_RMR_Received"].ObjectName) assert.Equal(t, "ricxappRMRTransmittedCounter", appMetrics["ricxapp_RMR_Transmitted"].ObjectName) @@ -209,11 +209,11 @@ func TestParseMetricsRulesMissingFields(t *testing.T) { func TestParseMetricsRulesDuplicateDefinitionIsIgnored(t *testing.T) { appMetrics := make(AppMetrics) metricsJSON := `{"metrics": [ - { "name": "ricxapp_RMR_Received", "objectName": "ricxappRMRreceivedCounter", "objectInstance": "ricxappRMRReceived" }, - { "name": "ricxapp_RMR_Received", "objectName": "ricxappRMRreceivedCounterXXX", "objectInstance": "ricxappRMRReceivedXXX" }, - { "name": "ricxapp_RMR_Transmitted", "objectName": "ricxappRMRTransmittedCounter", "objectInstance": "ricxappRMRTransmitted" }]}` + { "name": "ricxapp_RMR_Received", "objectName": "ricxappRMRreceivedCounter", "objectInstance": "ricxappRMRReceived", "counterId": "0011" }, + { "name": "ricxapp_RMR_Received", "objectName": "ricxappRMRreceivedCounterXXX", "objectInstance": "ricxappRMRReceivedXXX", "counterId": "0011" }, + { "name": "ricxapp_RMR_Transmitted", "objectName": "ricxappRMRTransmittedCounter", "objectInstance": "ricxappRMRTransmitted", "counterId": "0011" }]}` m := metricsStringToInterfaceArray(metricsJSON) - appMetrics = parseMetricsRules(m, appMetrics, "M1234", "App-1") + appMetrics = parseMetricsRules(m, appMetrics, "SEP/XAPP", "X2", "1234", "60") assert.Len(t, appMetrics, 2) assert.Equal(t, "ricxappRMRreceivedCounter", appMetrics["ricxapp_RMR_Received"].ObjectName) assert.Equal(t, "ricxappRMRReceived", appMetrics["ricxapp_RMR_Received"].ObjectInstance) @@ -222,13 +222,13 @@ func TestParseMetricsRulesDuplicateDefinitionIsIgnored(t *testing.T) { func TestParseMetricsRulesIncrementalFillOfAppMetrics(t *testing.T) { appMetrics := make(AppMetrics) metricsJSON1 := `{"metrics": [ - { "name": "ricxapp_RMR_Received", "objectName": "ricxappRMRreceivedCounter", "objectInstance": "ricxappRMRReceived" }]}` + { "name": "ricxapp_RMR_Received", "objectName": "ricxappRMRreceivedCounter", "objectInstance": "ricxappRMRReceived", "counterId": "0011" }]}` metricsJSON2 := `{"metrics": [ - { "name": "ricxapp_RMR_Transmitted", "objectName": "ricxappRMRTransmittedCounter", "objectInstance": "ricxappRMRTransmitted" }]}` + { "name": "ricxapp_RMR_Transmitted", "objectName": "ricxappRMRTransmittedCounter", "objectInstance": "ricxappRMRTransmitted", "counterId": "0011" }]}` m1 := metricsStringToInterfaceArray(metricsJSON1) m2 := metricsStringToInterfaceArray(metricsJSON2) - appMetrics = parseMetricsRules(m1, appMetrics, "M1234", "App-1") - appMetrics = parseMetricsRules(m2, appMetrics, "M1234", "App-1") + appMetrics = parseMetricsRules(m1, appMetrics, "SEP/XAPP", "X2", "1234", "60") + appMetrics = parseMetricsRules(m2, appMetrics, "SEP/XAPP", "X2", "1234", "60") assert.Len(t, appMetrics, 2) assert.Equal(t, "ricxappRMRreceivedCounter", appMetrics["ricxapp_RMR_Received"].ObjectName) assert.Equal(t, "ricxappRMRReceived", appMetrics["ricxapp_RMR_Received"].ObjectInstance) diff --git a/cmd/vesmgr/vesmgr.go b/cmd/vesmgr/vesmgr.go index e292307..c093359 100755 --- a/cmd/vesmgr/vesmgr.go +++ b/cmd/vesmgr/vesmgr.go @@ -187,9 +187,15 @@ func queryXAppsConfig(appmgrURL string, timeout time.Duration) ([]byte, error) { return emptyConfig, errors.New(resp.Status) } -func queryConf() ([]byte, error) { - return queryXAppsConfig("http://"+appmgrDomain+":"+appmgrPort+appmgrXAppConfigPath, - 10*time.Second) +func queryConf() (appConfig []byte, err error) { + for i := 0; i < 10; i++ { + appConfig, err = queryXAppsConfig("http://"+appmgrDomain+":"+appmgrPort+appmgrXAppConfigPath, 10*time.Second) + if len(appConfig) > 0 { + break + } + time.Sleep(5 * time.Second) + } + return appConfig, err } func (vesmgr *VesMgr) emptyNotificationsChannel() { @@ -250,11 +256,17 @@ func (vesmgr *VesMgr) waitSubscriptionLoop() { // Run the vesmgr process main loop func (vesmgr *VesMgr) Run() { logger.Info("vesmgr main loop ready") + vesmgr.httpServer.start(vesmgrXappNotifPath, vesmgr.chXAppNotifications, vesmgr.chSupervision) + vesmgr.subscribeXAppNotifications() + vesmgr.waitSubscriptionLoop() + xappConfig, _ := queryConf() + createConf(vespaConfigFile, xappConfig) + vesmgr.startVesagent() for { vesmgr.servRequest() diff --git a/container-tag.yaml b/container-tag.yaml index c28c94d..b7c6ac8 100644 --- a/container-tag.yaml +++ b/container-tag.yaml @@ -1,4 +1,4 @@ # The Jenkins job uses this string for the tag in the image name # for example nexus3.o-ran-sc.org:10004/my-image-name:0.0.1 --- -tag: 0.5.0 +tag: 0.5.1 diff --git a/test/xApp_config_test_output.json b/test/xApp_config_test_output.json index c74bac9..204398b 100755 --- a/test/xApp_config_test_output.json +++ b/test/xApp_config_test_output.json @@ -126,24 +126,26 @@ }, "measurements": [ { - "measId": "M9001", - "object": "XAPP-xApp1", + "moId": "SEP-12/XAPP-1", + "measType": "X2", + "measId": "9001", + "measInterval": "60", "metrics": [ { - "description": "Example counter 1", - "enabled": true, "name": "App1ExampleCounterOne", - "type": "counter", "objectName": "App1ExampleCounterOneObject", - "objectInstance": "App1ExampleCounterOneObjectInstance" + "objectInstance": "App1ExampleCounterOneObjectInstance", + "counterId": "0011", + "type": "counter", + "description": "Example counter 1" }, { - "description": "Example counter 2", - "enabled": true, "name": "App1ExampleCounterTwo", - "type": "counter", "objectName": "App1ExampleCounterTwoObject", - "objectInstance": "App1ExampleCounterTwoObjectInstance" + "objectInstance": "App1ExampleCounterTwoObjectInstance", + "counterId": "0012", + "type": "counter", + "description": "Example counter 2" } ] } @@ -277,24 +279,26 @@ }, "measurements": [ { - "measId": "M9001", - "object": "XAPP-xApp2", + "moId": "SEP-12/XAPP-2", + "measType": "X2", + "measId": "9002", + "measInterval": "60", "metrics": [ { - "description": "Example counter", - "enabled": true, "name": "App2ExampleCounterOne", - "type": "counter", "objectName": "App2ExampleCounterOneObject", - "objectInstance": "App2ExampleCounterOneObjectInstance" + "objectInstance": "App2ExampleCounterOneObjectInstance", + "counterId": "0021", + "type": "counter", + "description": "Example counter 1" }, { - "description": "Another example counter", - "enabled": true, "name": "App2ExampleCounterTwo", - "type": "counter", "objectName": "App2ExampleCounterTwoObject", - "objectInstance": "App2ExampleCounterTwoObjectInstance" + "objectInstance": "App2ExampleCounterTwoObjectInstance", + "counterId": "0022", + "type": "counter", + "description": "Example counter 2" } ] }