diff --git a/receiver/nginxreceiver/integration_test.go b/receiver/nginxreceiver/integration_test.go index a99c0a77153c..dfdc94c1cf13 100644 --- a/receiver/nginxreceiver/integration_test.go +++ b/receiver/nginxreceiver/integration_test.go @@ -28,9 +28,10 @@ import ( "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" "go.opentelemetry.io/collector/config/confighttp" - "go.opentelemetry.io/collector/consumer/pdata" "go.opentelemetry.io/collector/receiver/scraperhelper" "go.uber.org/zap" + + "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nginxreceiver/internal/metadata" ) type NginxIntegrationSuite struct { @@ -92,24 +93,46 @@ func (suite *NginxIntegrationSuite) TestNginxScraperHappyPath() { ilm := ilms.At(0) ms := ilm.Metrics() - require.Equal(t, 7, ms.Len()) - - metricValues := make(map[string]int64, 7) + require.Equal(t, 4, ms.Len()) for i := 0; i < ms.Len(); i++ { m := ms.At(i) - var dps pdata.IntDataPointSlice - - switch m.DataType() { - case pdata.MetricDataTypeIntGauge: - dps = m.IntGauge().DataPoints() - case pdata.MetricDataTypeIntSum: - dps = m.IntSum().DataPoints() + switch m.Name() { + case metadata.M.NginxRequests.Name(): + require.Equal(t, 1, m.IntSum().DataPoints().Len()) + require.True(t, m.IntSum().IsMonotonic()) + case metadata.M.NginxConnectionsAccepted.Name(): + require.Equal(t, 1, m.IntSum().DataPoints().Len()) + require.True(t, m.IntSum().IsMonotonic()) + case metadata.M.NginxConnectionsHandled.Name(): + require.Equal(t, 1, m.IntSum().DataPoints().Len()) + require.True(t, m.IntSum().IsMonotonic()) + case metadata.M.NginxConnectionsCurrent.Name(): + dps := m.IntGauge().DataPoints() + require.Equal(t, 4, dps.Len()) + present := map[string]bool{} + for j := 0; j < dps.Len(); j++ { + dp := dps.At(j) + state, _ := dp.LabelsMap().Get("state") + switch state { + case metadata.LabelState.Active: + present[state] = true + case metadata.LabelState.Reading: + present[state] = true + case metadata.LabelState.Writing: + present[state] = true + case metadata.LabelState.Waiting: + present[state] = true + default: + require.Nil(t, state, fmt.Sprintf("connections with state %s not expected", state)) + } + } + // Ensure all 4 expected states were present + require.Equal(t, 4, len(present)) + default: + require.Nil(t, m.Name(), fmt.Sprintf("metric %s not expected", m.Name())) } - require.Equal(t, 1, dps.Len()) - - metricValues[m.Name()] = dps.At(0).Value() } } diff --git a/receiver/nginxreceiver/internal/metadata/generated_metrics.go b/receiver/nginxreceiver/internal/metadata/generated_metrics.go index eb5145d1114d..08a1b0185821 100644 --- a/receiver/nginxreceiver/internal/metadata/generated_metrics.go +++ b/receiver/nginxreceiver/internal/metadata/generated_metrics.go @@ -56,11 +56,8 @@ func (m *metricImpl) Init(metric pdata.Metric) { type metricStruct struct { NginxConnectionsAccepted MetricIntf - NginxConnectionsActive MetricIntf + NginxConnectionsCurrent MetricIntf NginxConnectionsHandled MetricIntf - NginxConnectionsReading MetricIntf - NginxConnectionsWaiting MetricIntf - NginxConnectionsWriting MetricIntf NginxRequests MetricIntf } @@ -68,22 +65,16 @@ type metricStruct struct { func (m *metricStruct) Names() []string { return []string{ "nginx.connections_accepted", - "nginx.connections_active", + "nginx.connections_current", "nginx.connections_handled", - "nginx.connections_reading", - "nginx.connections_waiting", - "nginx.connections_writing", "nginx.requests", } } var metricsByName = map[string]MetricIntf{ "nginx.connections_accepted": Metrics.NginxConnectionsAccepted, - "nginx.connections_active": Metrics.NginxConnectionsActive, + "nginx.connections_current": Metrics.NginxConnectionsCurrent, "nginx.connections_handled": Metrics.NginxConnectionsHandled, - "nginx.connections_reading": Metrics.NginxConnectionsReading, - "nginx.connections_waiting": Metrics.NginxConnectionsWaiting, - "nginx.connections_writing": Metrics.NginxConnectionsWriting, "nginx.requests": Metrics.NginxRequests, } @@ -94,11 +85,8 @@ func (m *metricStruct) ByName(n string) MetricIntf { func (m *metricStruct) FactoriesByName() map[string]func(pdata.Metric) { return map[string]func(pdata.Metric){ Metrics.NginxConnectionsAccepted.Name(): Metrics.NginxConnectionsAccepted.Init, - Metrics.NginxConnectionsActive.Name(): Metrics.NginxConnectionsActive.Init, + Metrics.NginxConnectionsCurrent.Name(): Metrics.NginxConnectionsCurrent.Init, Metrics.NginxConnectionsHandled.Name(): Metrics.NginxConnectionsHandled.Init, - Metrics.NginxConnectionsReading.Name(): Metrics.NginxConnectionsReading.Init, - Metrics.NginxConnectionsWaiting.Name(): Metrics.NginxConnectionsWaiting.Init, - Metrics.NginxConnectionsWriting.Name(): Metrics.NginxConnectionsWriting.Init, Metrics.NginxRequests.Name(): Metrics.NginxRequests.Init, } } @@ -118,10 +106,10 @@ var Metrics = &metricStruct{ }, }, &metricImpl{ - "nginx.connections_active", + "nginx.connections_current", func(metric pdata.Metric) { - metric.SetName("nginx.connections_active") - metric.SetDescription("The current number of open connections") + metric.SetName("nginx.connections_current") + metric.SetDescription("The current number of nginx connections by state") metric.SetUnit("connections") metric.SetDataType(pdata.MetricDataTypeIntGauge) }, @@ -137,33 +125,6 @@ var Metrics = &metricStruct{ metric.IntSum().SetAggregationTemporality(pdata.AggregationTemporalityCumulative) }, }, - &metricImpl{ - "nginx.connections_reading", - func(metric pdata.Metric) { - metric.SetName("nginx.connections_reading") - metric.SetDescription("The current number of connections where nginx is reading the request headerhe current number of open connections") - metric.SetUnit("connections") - metric.SetDataType(pdata.MetricDataTypeIntGauge) - }, - }, - &metricImpl{ - "nginx.connections_waiting", - func(metric pdata.Metric) { - metric.SetName("nginx.connections_waiting") - metric.SetDescription("The current number of idle client connections waiting for a request.") - metric.SetUnit("connections") - metric.SetDataType(pdata.MetricDataTypeIntGauge) - }, - }, - &metricImpl{ - "nginx.connections_writing", - func(metric pdata.Metric) { - metric.SetName("nginx.connections_writing") - metric.SetDescription("The current number of connections where nginx is writing the response back to the client.") - metric.SetUnit("connections") - metric.SetDataType(pdata.MetricDataTypeIntGauge) - }, - }, &metricImpl{ "nginx.requests", func(metric pdata.Metric) { @@ -183,8 +144,25 @@ var M = Metrics // Labels contains the possible metric labels that can be used. var Labels = struct { -}{} + // State (The state of a connection) + State string +}{ + "state", +} // L contains the possible metric labels that can be used. L is an alias for // Labels. var L = Labels + +// LabelState are the possible values that the label "state" can have. +var LabelState = struct { + Active string + Reading string + Writing string + Waiting string +}{ + "active", + "reading", + "writing", + "waiting", +} diff --git a/receiver/nginxreceiver/metadata.yaml b/receiver/nginxreceiver/metadata.yaml index 98b5e00c13ef..65388598efea 100644 --- a/receiver/nginxreceiver/metadata.yaml +++ b/receiver/nginxreceiver/metadata.yaml @@ -1,6 +1,13 @@ name: nginxreceiver labels: + state: + description: The state of a connection + enum: + - active + - reading + - writing + - waiting metrics: nginx.requests: @@ -11,12 +18,6 @@ metrics: monotonic: true aggregation: cumulative labels: [] - nginx.connections_active: - description: The current number of open connections - unit: connections - data: - type: int gauge - labels: [] nginx.connections_accepted: description: The total number of accepted client connections unit: connections @@ -33,21 +34,9 @@ metrics: monotonic: true aggregation: cumulative labels: [] - nginx.connections_reading: - description: The current number of connections where nginx is reading the request headerhe current number of open connections + nginx.connections_current: + description: The current number of nginx connections by state unit: connections data: type: int gauge - labels: [] - nginx.connections_writing: - description: The current number of connections where nginx is writing the response back to the client. - unit: connections - data: - type: int gauge - labels: [] - nginx.connections_waiting: - description: The current number of idle client connections waiting for a request. - unit: connections - data: - type: int gauge - labels: [] + labels: [state] diff --git a/receiver/nginxreceiver/scraper.go b/receiver/nginxreceiver/scraper.go index 664561172f61..72292268d6e6 100644 --- a/receiver/nginxreceiver/scraper.go +++ b/receiver/nginxreceiver/scraper.go @@ -73,12 +73,13 @@ func (r *nginxScraper) scrape(ctx context.Context) (pdata.ResourceMetricsSlice, } metrics.AddSumDataPoint(metadata.M.NginxRequests.Name(), stats.Requests) - metrics.AddGaugeDataPoint(metadata.M.NginxConnectionsActive.Name(), stats.Connections.Active) metrics.AddSumDataPoint(metadata.M.NginxConnectionsAccepted.Name(), stats.Connections.Accepted) metrics.AddSumDataPoint(metadata.M.NginxConnectionsHandled.Name(), stats.Connections.Handled) - metrics.AddGaugeDataPoint(metadata.M.NginxConnectionsReading.Name(), stats.Connections.Reading) - metrics.AddGaugeDataPoint(metadata.M.NginxConnectionsWriting.Name(), stats.Connections.Writing) - metrics.AddGaugeDataPoint(metadata.M.NginxConnectionsWaiting.Name(), stats.Connections.Waiting) + + metrics.WithLabels(map[string]string{metadata.L.State: metadata.LabelState.Active}).AddGaugeDataPoint(metadata.M.NginxConnectionsCurrent.Name(), stats.Connections.Active) + metrics.WithLabels(map[string]string{metadata.L.State: metadata.LabelState.Reading}).AddGaugeDataPoint(metadata.M.NginxConnectionsCurrent.Name(), stats.Connections.Reading) + metrics.WithLabels(map[string]string{metadata.L.State: metadata.LabelState.Writing}).AddGaugeDataPoint(metadata.M.NginxConnectionsCurrent.Name(), stats.Connections.Writing) + metrics.WithLabels(map[string]string{metadata.L.State: metadata.LabelState.Waiting}).AddGaugeDataPoint(metadata.M.NginxConnectionsCurrent.Name(), stats.Connections.Waiting) return metrics.Metrics.ResourceMetrics(), nil } diff --git a/receiver/nginxreceiver/scraper_test.go b/receiver/nginxreceiver/scraper_test.go index 7eed1973b0e2..7fc3cea8309a 100644 --- a/receiver/nginxreceiver/scraper_test.go +++ b/receiver/nginxreceiver/scraper_test.go @@ -17,6 +17,7 @@ package nginxreceiver import ( "context" "errors" + "fmt" "net/http" "net/http/httptest" "testing" @@ -25,6 +26,8 @@ import ( "go.opentelemetry.io/collector/config/confighttp" "go.opentelemetry.io/collector/consumer/pdata" "go.uber.org/zap" + + "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/nginxreceiver/internal/metadata" ) func TestScraper(t *testing.T) { @@ -57,7 +60,7 @@ Reading: 6 Writing: 179 Waiting: 106 ilm := ilms.At(0) ms := ilm.Metrics() - require.Equal(t, 7, ms.Len()) + require.Equal(t, 4, ms.Len()) metricValues := make(map[string]int64, 7) @@ -69,23 +72,28 @@ Reading: 6 Writing: 179 Waiting: 106 switch m.DataType() { case pdata.MetricDataTypeIntGauge: dps = m.IntGauge().DataPoints() + require.Equal(t, 4, dps.Len()) + for j := 0; j < dps.Len(); j++ { + dp := dps.At(j) + state, _ := dp.LabelsMap().Get(metadata.L.State) + label := fmt.Sprintf("%s state:%s", m.Name(), state) + metricValues[label] = dp.Value() + } case pdata.MetricDataTypeIntSum: dps = m.IntSum().DataPoints() + require.Equal(t, 1, dps.Len()) + metricValues[m.Name()] = dps.At(0).Value() } - - require.Equal(t, 1, dps.Len()) - - metricValues[m.Name()] = dps.At(0).Value() } require.Equal(t, map[string]int64{ - "nginx.connections_accepted": 16630948, - "nginx.connections_handled": 16630948, - "nginx.requests": 31070465, - "nginx.connections_active": 291, - "nginx.connections_reading": 6, - "nginx.connections_writing": 179, - "nginx.connections_waiting": 106, + "nginx.connections_accepted": 16630948, + "nginx.connections_handled": 16630948, + "nginx.requests": 31070465, + "nginx.connections_current state:active": 291, + "nginx.connections_current state:reading": 6, + "nginx.connections_current state:writing": 179, + "nginx.connections_current state:waiting": 106, }, metricValues) }