From 1e6f46e165f1835f990d26074a751bca039446a8 Mon Sep 17 00:00:00 2001 From: marepally Date: Mon, 29 Aug 2022 13:23:19 -0700 Subject: [PATCH] feat: new NMS ACM dimensions for advanced metrics --- src/plugins/advanced_metrics.go | 15 +++ test/integration/advanced_metrics_test.go | 115 ++++++++++++++++++ test/integration/nginx/conf.go | 9 ++ test/integration/nginx/nginx_templates.go | 2 +- test/integration/validator/metrics.go | 4 + .../agent/v2/src/plugins/advanced_metrics.go | 15 +++ 6 files changed, 159 insertions(+), 1 deletion(-) diff --git a/src/plugins/advanced_metrics.go b/src/plugins/advanced_metrics.go index f206ea8f7..3b978b03c 100644 --- a/src/plugins/advanced_metrics.go +++ b/src/plugins/advanced_metrics.go @@ -21,6 +21,7 @@ const ( advancedMetricsPluginVersion = "v0.8.0" advancedMetricsPluginName = "Advanced Metrics Plugin" + // ordinal positions of data collected by metrics module. httpUriDimension = "http.uri" httpResponseCodeDimension = "http.response_code" httpRequestMethodDimension = "http.request_method" @@ -30,6 +31,13 @@ const ( environmentDimension = "environment" appDimension = "app" componentDimension = "component" + acmInfraWorkspacesNameDimension = "acm_infra_workspaces_name" + acmServiceWorkspacesNameDimension = "acm_service_workspaces_name" + acmEnvironmentsNameDimension = "acm_environments_name" + acmEnvironmentsTypeDimension = "acm_environments_type" + acmApiProxyNameDimension = "acm_api_proxy_name" + acmApiProxyHostnameDimension = "acm_api_proxy_hostname" + acmProxyApiVersionDimension = "acm_api_proxy_version" countryCodeDimension = "country_code" httpVersionSchemaDimension = "http.version_schema" httpUpstreamAddrDimension = "http.upstream_addr" // TODO this should not contain http. prefix probably @@ -103,6 +111,13 @@ func NewAdvancedMetrics(env core.Environment, conf *config.Config) *AdvancedMetr NewDimension(environmentDimension, 32). NewDimension(appDimension, 32). NewDimension(componentDimension, 256). + NewDimension(acmInfraWorkspacesNameDimension, 256). + NewDimension(acmServiceWorkspacesNameDimension, 256). + NewDimension(acmEnvironmentsNameDimension, 256). + NewDimension(acmEnvironmentsTypeDimension, 256). + NewDimension(acmApiProxyNameDimension, 256). + NewDimension(acmApiProxyHostnameDimension, 256). + NewDimension(acmProxyApiVersionDimension, 256). NewDimension(countryCodeDimension, 256). //TODO should be implemented as GeoIP NewDimension(httpVersionSchemaDimension, 16). NewDimension(httpUpstreamAddrDimension, 1024). diff --git a/test/integration/advanced_metrics_test.go b/test/integration/advanced_metrics_test.go index 62a1060c7..9864651e5 100644 --- a/test/integration/advanced_metrics_test.go +++ b/test/integration/advanced_metrics_test.go @@ -33,6 +33,13 @@ func SetupAdvancedMetrics(t *testing.T, socketLocation string) *advanced_metrics NewDimension("environment", 32). NewDimension("app", 32). NewDimension("component", 256). + NewDimension("acm_infra_workspaces_name", 256). + NewDimension("acm_service_workspaces_name", 256). + NewDimension("acm_environments_name", 256). + NewDimension("acm_environments_type", 256). + NewDimension("acm_api_proxy_name", 256). + NewDimension("acm_api_proxy_hostname", 256). + NewDimension("acm_api_proxy_version", 256). NewDimension("country_code", 256). NewDimension("http.version_schema", 16). NewDimension("http.upstream_addr", 1024). @@ -1130,3 +1137,111 @@ func TestStreamUdpMetrics(t *testing.T) { assert.Fail(t, "failed to receive message") } } + +func TestAppCentricACMDimensions(t *testing.T) { + httpServerListenAddress := fmt.Sprintf("%s:8080", httpServerAddress) + + socket := "/tmp/advanced_metrics.sr" + acm := SetupAdvancedMetrics(t, socket) + + httpUpstream := upstream.HttpTestUpstream{ + Name: "returns_200_ok", + Address: fmt.Sprintf("%s:%d", upstreamHost, upstreamPort), + Handlers: map[string]upstream.Handler{ + location1: { + Handler: func(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "OK") + }, + }, + }, + } + httpUpstream.Serve(t) + + var ( + // acm centric + acmInfraWorkspace1 = "acm_infra_1" + acmServicesWorkspace1 = "acm_service_1" + acmEnvName1 = "acm_env_1" + envType1 = "env_type_1" + apiProxyName1 = "api_proxy_name_1" + apiHostname1 = "api_proxy_hostname_1" + apiProxyVersion1 = "api_proxy_version_1" + ) + + // generate config that exercises ACM dimensions using metrics marker directive + cfg := conf.NginxConf{ + HttpBlock: &conf.HttpBlock{ + F5MetricsServer: socket, + Upstreams: map[string]conf.Upstream{ + httpUpstream.Name: httpUpstream.AsUpstream(), + }, + Servers: []conf.Server{ + httpUpstream.AsServer(httpServerListenAddress, + map[string]string{ + conf.MarkerEnvironment: env1, + conf.MarkerGateway: gw1, + conf.AcmInfraWorkspacesNameDimension: acmInfraWorkspace1, + conf.AcmServiceWorkspacesNameDimension: acmServicesWorkspace1, + conf.AcmEnvironmentsNameDimension: acmEnvName1, + conf.AcmEnvironmentsTypeDimension: envType1, + }, + upstream.LocationsMarkers{ + location1: map[string]string{ + conf.MarkerApp: app1, + conf.MarkerComponent: comp1, + conf.AcmApiProxyNameDimension: apiProxyName1, + conf.AcmApiProxyHostnameDimension: apiHostname1, + conf.AcmProxyApiVersionDimension: apiProxyVersion1, + }, + }, + upstream.LocationsDirectives{}, + ), + }, + }, + } + + cmd, err := conf.NewNginxCommand(&cfg) + require.NoError(t, err) + cmd.Start(t) + + location1Url := fmt.Sprintf("http://%s/loc1", httpServerListenAddress) + + _, err = http.Get(location1Url) + assert.NoError(t, err) + _, err = http.Get(location1Url) + assert.NoError(t, err) + + expectedDimensions := []publisher.Dimension{ + {Name: "app", Value: app1}, + {Name: "component", Value: comp1}, + {Name: "gateway", Value: gw1}, + {Name: "environment", Value: env1}, + {Name: "http.uri", Value: location1}, + {Name: "http.request_method", Value: "GET"}, + {Name: "http.response_code", Value: "200"}, + {Name: "country_code", Value: "0100007fffff00000000000000000000"}, + {Name: "http.version_schema", Value: "4"}, + {Name: "http.upstream_addr", Value: fmt.Sprintf("%s:%d", upstreamAddress, upstreamPort)}, + {Name: "http.hostname", Value: httpServerAddress}, + {Name: "family", Value: "web"}, + {Name: "proxied_protocol", Value: "http"}, + {Name: "request_outcome", Value: "PASSED"}, + {Name: "upstream_response_code", Value: "200"}, + {Name: conf.AcmInfraWorkspacesNameDimension, Value: acmInfraWorkspace1}, + {Name: conf.AcmServiceWorkspacesNameDimension, Value: acmServicesWorkspace1}, + {Name: conf.AcmEnvironmentsNameDimension, Value: acmEnvName1}, + {Name: conf.AcmEnvironmentsTypeDimension, Value: envType1}, + {Name: conf.AcmApiProxyHostnameDimension, Value: apiHostname1}, + {Name: conf.AcmProxyApiVersionDimension, Value: apiProxyVersion1}, + {Name: conf.AcmApiProxyNameDimension, Value: apiProxyName1}, + } + + select { + case metrics := <-acm.OutChannel(): + assert.NotEmpty(t, metrics) + assert.Len(t, metrics, 1) + validator.AssertDimensionsEqual(t, expectedDimensions, metrics[0]) + case <-time.After(time.Second * 15): + assert.Fail(t, "failed to receive message") + } +} diff --git a/test/integration/nginx/conf.go b/test/integration/nginx/conf.go index e50ca1902..440c43b4c 100644 --- a/test/integration/nginx/conf.go +++ b/test/integration/nginx/conf.go @@ -11,6 +11,15 @@ const ( MarkerComponent = "component" MarkerGateway = "gateway" MarkerPublishedApi = "published_api" + + // ACM dimensions + AcmInfraWorkspacesNameDimension = "acm_infra_workspaces_name" + AcmServiceWorkspacesNameDimension = "acm_service_workspaces_name" + AcmEnvironmentsNameDimension = "acm_environments_name" + AcmEnvironmentsTypeDimension = "acm_environments_type" + AcmApiProxyNameDimension = "acm_api_proxy_name" + AcmApiProxyHostnameDimension = "acm_api_proxy_hostname" + AcmProxyApiVersionDimension = "acm_api_proxy_version" ) type NginxConf struct { diff --git a/test/integration/nginx/nginx_templates.go b/test/integration/nginx/nginx_templates.go index 974a60dab..ea7d3071f 100644 --- a/test/integration/nginx/nginx_templates.go +++ b/test/integration/nginx/nginx_templates.go @@ -5,7 +5,7 @@ const ( master_process on; worker_processes auto; -error_log /dev/stderr; +error_log /var/log/nginx/error.log warn; load_module modules/ngx_http_f5_metrics_module.so; load_module modules/ngx_stream_f5_metrics_module.so; diff --git a/test/integration/validator/metrics.go b/test/integration/validator/metrics.go index 9f712a85c..dba4dc677 100644 --- a/test/integration/validator/metrics.go +++ b/test/integration/validator/metrics.go @@ -26,6 +26,10 @@ func AssertMetricSetEqual(t *testing.T, expectedMetrics []ExpectedMetric, expect assertMetricsEqual(t, expectedMetrics, actuallMetrics.Metrics) } +func AssertDimensionsEqual(t *testing.T, expectedDimensions []publisher.Dimension, actualMetrics *publisher.MetricSet) { + assertDimensionsEqual(t, expectedDimensions, actualMetrics) +} + func assertMetricsEqual(t *testing.T, expectedMetrics []ExpectedMetric, actualMetrics []publisher.Metric) { diff --git a/test/performance/vendor/github.com/nginx/agent/v2/src/plugins/advanced_metrics.go b/test/performance/vendor/github.com/nginx/agent/v2/src/plugins/advanced_metrics.go index f206ea8f7..3b978b03c 100644 --- a/test/performance/vendor/github.com/nginx/agent/v2/src/plugins/advanced_metrics.go +++ b/test/performance/vendor/github.com/nginx/agent/v2/src/plugins/advanced_metrics.go @@ -21,6 +21,7 @@ const ( advancedMetricsPluginVersion = "v0.8.0" advancedMetricsPluginName = "Advanced Metrics Plugin" + // ordinal positions of data collected by metrics module. httpUriDimension = "http.uri" httpResponseCodeDimension = "http.response_code" httpRequestMethodDimension = "http.request_method" @@ -30,6 +31,13 @@ const ( environmentDimension = "environment" appDimension = "app" componentDimension = "component" + acmInfraWorkspacesNameDimension = "acm_infra_workspaces_name" + acmServiceWorkspacesNameDimension = "acm_service_workspaces_name" + acmEnvironmentsNameDimension = "acm_environments_name" + acmEnvironmentsTypeDimension = "acm_environments_type" + acmApiProxyNameDimension = "acm_api_proxy_name" + acmApiProxyHostnameDimension = "acm_api_proxy_hostname" + acmProxyApiVersionDimension = "acm_api_proxy_version" countryCodeDimension = "country_code" httpVersionSchemaDimension = "http.version_schema" httpUpstreamAddrDimension = "http.upstream_addr" // TODO this should not contain http. prefix probably @@ -103,6 +111,13 @@ func NewAdvancedMetrics(env core.Environment, conf *config.Config) *AdvancedMetr NewDimension(environmentDimension, 32). NewDimension(appDimension, 32). NewDimension(componentDimension, 256). + NewDimension(acmInfraWorkspacesNameDimension, 256). + NewDimension(acmServiceWorkspacesNameDimension, 256). + NewDimension(acmEnvironmentsNameDimension, 256). + NewDimension(acmEnvironmentsTypeDimension, 256). + NewDimension(acmApiProxyNameDimension, 256). + NewDimension(acmApiProxyHostnameDimension, 256). + NewDimension(acmProxyApiVersionDimension, 256). NewDimension(countryCodeDimension, 256). //TODO should be implemented as GeoIP NewDimension(httpVersionSchemaDimension, 16). NewDimension(httpUpstreamAddrDimension, 1024).