diff --git a/internal/collector/nginxplusreceiver/record/cache_metrics.go b/internal/collector/nginxplusreceiver/record/cache_metrics.go new file mode 100644 index 000000000..caac89757 --- /dev/null +++ b/internal/collector/nginxplusreceiver/record/cache_metrics.go @@ -0,0 +1,108 @@ +// Copyright (c) F5, Inc. +// +// This source code is licensed under the Apache License, Version 2.0 license found in the +// LICENSE file in the root directory of this source tree. + +package record + +import ( + "github.com/nginx/agent/v3/internal/collector/nginxplusreceiver/internal/metadata" + plusapi "github.com/nginxinc/nginx-plus-go-client/v2/client" + "go.opentelemetry.io/collector/pdata/pcommon" +) + +func RecordCacheMetrics(mb *metadata.MetricsBuilder, stats *plusapi.Stats, now pcommon.Timestamp) { + for name, cache := range stats.Caches { + // Cache Bytes + mb.RecordNginxCacheBytesReadDataPoint( + now, + int64(cache.Bypass.Bytes), + metadata.AttributeNginxCacheOutcomeBYPASS, + name, + ) + mb.RecordNginxCacheBytesReadDataPoint( + now, + int64(cache.Expired.Bytes), + metadata.AttributeNginxCacheOutcomeEXPIRED, + name, + ) + mb.RecordNginxCacheBytesReadDataPoint( + now, + int64(cache.Hit.Bytes), + metadata.AttributeNginxCacheOutcomeHIT, + name, + ) + mb.RecordNginxCacheBytesReadDataPoint( + now, + int64(cache.Miss.Bytes), + metadata.AttributeNginxCacheOutcomeMISS, + name, + ) + mb.RecordNginxCacheBytesReadDataPoint( + now, + int64(cache.Revalidated.Bytes), + metadata.AttributeNginxCacheOutcomeREVALIDATED, + name, + ) + mb.RecordNginxCacheBytesReadDataPoint( + now, + int64(cache.Stale.Bytes), + metadata.AttributeNginxCacheOutcomeSTALE, + name, + ) + mb.RecordNginxCacheBytesReadDataPoint( + now, + int64(cache.Updating.Bytes), + metadata.AttributeNginxCacheOutcomeUPDATING, + name, + ) + + // Cache Memory + mb.RecordNginxCacheMemoryLimitDataPoint(now, int64(cache.MaxSize), name) + mb.RecordNginxCacheMemoryUsageDataPoint(now, int64(cache.Size), name) + + // Cache Responses + mb.RecordNginxCacheResponsesDataPoint( + now, + int64(cache.Bypass.Responses), + metadata.AttributeNginxCacheOutcomeBYPASS, + name, + ) + mb.RecordNginxCacheResponsesDataPoint( + now, + int64(cache.Expired.Responses), + metadata.AttributeNginxCacheOutcomeEXPIRED, + name, + ) + mb.RecordNginxCacheResponsesDataPoint( + now, + int64(cache.Hit.Responses), + metadata.AttributeNginxCacheOutcomeHIT, + name, + ) + mb.RecordNginxCacheResponsesDataPoint( + now, + int64(cache.Miss.Responses), + metadata.AttributeNginxCacheOutcomeMISS, + name, + ) + mb.RecordNginxCacheResponsesDataPoint( + now, + int64(cache.Revalidated.Responses), + metadata.AttributeNginxCacheOutcomeREVALIDATED, + name, + ) + mb.RecordNginxCacheResponsesDataPoint( + now, + int64(cache.Stale.Responses), + metadata.AttributeNginxCacheOutcomeSTALE, + name, + ) + mb.RecordNginxCacheResponsesDataPoint( + now, + int64(cache.Updating.Responses), + metadata.AttributeNginxCacheOutcomeUPDATING, + name, + ) + } +} diff --git a/internal/collector/nginxplusreceiver/record/http_metrics.go b/internal/collector/nginxplusreceiver/record/http_metrics.go new file mode 100644 index 000000000..b79493586 --- /dev/null +++ b/internal/collector/nginxplusreceiver/record/http_metrics.go @@ -0,0 +1,114 @@ +// Copyright (c) F5, Inc. +// +// This source code is licensed under the Apache License, Version 2.0 license found in the +// LICENSE file in the root directory of this source tree. + +package record + +import ( + "github.com/nginx/agent/v3/internal/collector/nginxplusreceiver/internal/metadata" + plusapi "github.com/nginxinc/nginx-plus-go-client/v2/client" + "go.opentelemetry.io/collector/pdata/pcommon" +) + +type HTTPMetrics struct { + mb *metadata.MetricsBuilder + PreviousHTTPRequestsTotal uint64 +} + +func NewHTTPMetrics(stats *plusapi.Stats, mb *metadata.MetricsBuilder) *HTTPMetrics { + return &HTTPMetrics{ + mb: mb, + PreviousHTTPRequestsTotal: stats.HTTPRequests.Total, + } +} + +func (hm *HTTPMetrics) RecordHTTPMetrics(stats *plusapi.Stats, now pcommon.Timestamp) { + // Requests + hm.mb.RecordNginxHTTPRequestsDataPoint(now, int64(stats.HTTPRequests.Total), "", 0) + + // Request Count + requestsDiff := int64(stats.HTTPRequests.Total) - int64(hm.PreviousHTTPRequestsTotal) + hm.mb.RecordNginxHTTPRequestCountDataPoint(now, requestsDiff, "", 0) + hm.PreviousHTTPRequestsTotal = stats.HTTPRequests.Total + + // Connections + hm.mb.RecordNginxHTTPConnectionsDataPoint( + now, + int64(stats.Connections.Accepted), + metadata.AttributeNginxConnectionsOutcomeACCEPTED, + ) + hm.mb.RecordNginxHTTPConnectionsDataPoint( + now, + int64(stats.Connections.Dropped), + metadata.AttributeNginxConnectionsOutcomeDROPPED, + ) + hm.mb.RecordNginxHTTPConnectionCountDataPoint( + now, + int64(stats.Connections.Active), + metadata.AttributeNginxConnectionsOutcomeACTIVE, + ) + hm.mb.RecordNginxHTTPConnectionCountDataPoint( + now, + int64(stats.Connections.Idle), + metadata.AttributeNginxConnectionsOutcomeIDLE, + ) +} + +func (hm *HTTPMetrics) RecordHTTPLimitMetrics(stats *plusapi.Stats, now pcommon.Timestamp) { + // Limit Connections + for name, limitConnection := range stats.HTTPLimitConnections { + hm.mb.RecordNginxHTTPLimitConnRequestsDataPoint( + now, + int64(limitConnection.Passed), + metadata.AttributeNginxLimitConnOutcomePASSED, + name, + ) + hm.mb.RecordNginxHTTPLimitConnRequestsDataPoint( + now, + int64(limitConnection.Rejected), + metadata.AttributeNginxLimitConnOutcomeREJECTED, + name, + ) + hm.mb.RecordNginxHTTPLimitConnRequestsDataPoint( + now, + int64(limitConnection.RejectedDryRun), + metadata.AttributeNginxLimitConnOutcomeREJECTEDDRYRUN, + name, + ) + } + + // Limit Requests + for name, limitRequest := range stats.HTTPLimitRequests { + hm.mb.RecordNginxHTTPLimitReqRequestsDataPoint( + now, + int64(limitRequest.Passed), + metadata.AttributeNginxLimitReqOutcomePASSED, + name, + ) + hm.mb.RecordNginxHTTPLimitReqRequestsDataPoint( + now, + int64(limitRequest.Rejected), + metadata.AttributeNginxLimitReqOutcomeREJECTED, + name, + ) + hm.mb.RecordNginxHTTPLimitReqRequestsDataPoint( + now, + int64(limitRequest.RejectedDryRun), + metadata.AttributeNginxLimitReqOutcomeREJECTEDDRYRUN, + name, + ) + hm.mb.RecordNginxHTTPLimitReqRequestsDataPoint( + now, + int64(limitRequest.Delayed), + metadata.AttributeNginxLimitReqOutcomeDELAYED, + name, + ) + hm.mb.RecordNginxHTTPLimitReqRequestsDataPoint( + now, + int64(limitRequest.DelayedDryRun), + metadata.AttributeNginxLimitReqOutcomeDELAYEDDRYRUN, + name, + ) + } +} diff --git a/internal/collector/nginxplusreceiver/record/location_zone_metrics.go b/internal/collector/nginxplusreceiver/record/location_zone_metrics.go new file mode 100644 index 000000000..e4d1013ad --- /dev/null +++ b/internal/collector/nginxplusreceiver/record/location_zone_metrics.go @@ -0,0 +1,178 @@ +// Copyright (c) F5, Inc. +// +// This source code is licensed under the Apache License, Version 2.0 license found in the +// LICENSE file in the root directory of this source tree. + +package record + +import ( + "github.com/nginx/agent/v3/internal/collector/nginxplusreceiver/internal/metadata" + plusapi "github.com/nginxinc/nginx-plus-go-client/v2/client" + "go.opentelemetry.io/collector/pdata/pcommon" +) + +type LocationZoneMetrics struct { + PreviousLocationZoneResponses map[string]ResponseStatuses + PreviousLocationZoneRequests map[string]int64 + mb *metadata.MetricsBuilder +} + +type ResponseStatuses struct { + OneHundredStatusRange int64 + TwoHundredStatusRange int64 + ThreeHundredStatusRange int64 + FourHundredStatusRange int64 + FiveHundredStatusRange int64 +} + +func NewLocationZoneMetrics(stats *plusapi.Stats, mb *metadata.MetricsBuilder) *LocationZoneMetrics { + return &LocationZoneMetrics{ + mb: mb, + PreviousLocationZoneResponses: createPreviousLocationZoneResponses(stats), + PreviousLocationZoneRequests: createPreviousLocationZoneRequests(stats), + } +} + +func (lzm *LocationZoneMetrics) RecordLocationZoneMetrics(stats *plusapi.Stats, now pcommon.Timestamp) { + for lzName, lz := range stats.LocationZones { + // Requests + lzm.mb.RecordNginxHTTPRequestIoDataPoint( + now, + lz.Received, + metadata.AttributeNginxIoDirectionReceive, + lzName, + metadata.AttributeNginxZoneTypeLOCATION, + ) + lzm.mb.RecordNginxHTTPRequestIoDataPoint( + now, + lz.Sent, + metadata.AttributeNginxIoDirectionTransmit, + lzName, + metadata.AttributeNginxZoneTypeLOCATION, + ) + + lzm.mb.RecordNginxHTTPRequestsDataPoint( + now, + lz.Requests, + lzName, + metadata.AttributeNginxZoneTypeLOCATION, + ) + + lzm.mb.RecordNginxHTTPRequestCountDataPoint(now, + lz.Requests-lzm.PreviousLocationZoneRequests[lzName], + lzName, + metadata.AttributeNginxZoneTypeLOCATION, + ) + + lzm.mb.RecordNginxHTTPRequestDiscardedDataPoint(now, lz.Discarded, + lzName, + metadata.AttributeNginxZoneTypeLOCATION, + ) + + lzm.PreviousLocationZoneRequests[lzName] = lz.Requests + + lzm.recordLocationZoneHTTPMetrics(lz, lzName, now) + } +} + +//nolint:dupl // Duplicate of recordServerZoneHTTPMetrics but same function can not be used due to plusapi.LocationZone +func (lzm *LocationZoneMetrics) recordLocationZoneHTTPMetrics(lz plusapi.LocationZone, + lzName string, now pcommon.Timestamp, +) { + // Response Status + lzm.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(lz.Responses.Responses1xx), + metadata.AttributeNginxStatusRange1xx, + lzName, + metadata.AttributeNginxZoneTypeLOCATION, + ) + lzm.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(lz.Responses.Responses2xx), + metadata.AttributeNginxStatusRange2xx, + lzName, + metadata.AttributeNginxZoneTypeLOCATION, + ) + lzm.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(lz.Responses.Responses3xx), + metadata.AttributeNginxStatusRange3xx, + lzName, + metadata.AttributeNginxZoneTypeLOCATION, + ) + + lzm.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(lz.Responses.Responses4xx), + metadata.AttributeNginxStatusRange4xx, + lzName, + metadata.AttributeNginxZoneTypeLOCATION, + ) + + lzm.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(lz.Responses.Responses5xx), + metadata.AttributeNginxStatusRange5xx, + lzName, + metadata.AttributeNginxZoneTypeLOCATION, + ) + + // Requests + lzm.mb.RecordNginxHTTPResponseCountDataPoint(now, + int64(lz.Responses.Responses1xx)-lzm.PreviousLocationZoneResponses[lzName].OneHundredStatusRange, + metadata.AttributeNginxStatusRange1xx, + lzName, + metadata.AttributeNginxZoneTypeLOCATION) + + // Response Count Status + lzm.mb.RecordNginxHTTPResponseCountDataPoint(now, + int64(lz.Responses.Responses2xx)-lzm.PreviousLocationZoneResponses[lzName].TwoHundredStatusRange, + metadata.AttributeNginxStatusRange2xx, + lzName, + metadata.AttributeNginxZoneTypeLOCATION) + + lzm.mb.RecordNginxHTTPResponseCountDataPoint(now, + int64(lz.Responses.Responses3xx)-lzm.PreviousLocationZoneResponses[lzName].ThreeHundredStatusRange, + metadata.AttributeNginxStatusRange3xx, + lzName, + metadata.AttributeNginxZoneTypeLOCATION) + + lzm.mb.RecordNginxHTTPResponseCountDataPoint(now, + int64(lz.Responses.Responses4xx)-lzm.PreviousLocationZoneResponses[lzName].FourHundredStatusRange, + metadata.AttributeNginxStatusRange4xx, + lzName, + metadata.AttributeNginxZoneTypeLOCATION) + + lzm.mb.RecordNginxHTTPResponseCountDataPoint(now, + int64(lz.Responses.Responses5xx)-lzm.PreviousLocationZoneResponses[lzName].FiveHundredStatusRange, + metadata.AttributeNginxStatusRange5xx, + lzName, + metadata.AttributeNginxZoneTypeLOCATION) + + respStatus := ResponseStatuses{ + OneHundredStatusRange: int64(lz.Responses.Responses1xx), + TwoHundredStatusRange: int64(lz.Responses.Responses2xx), + ThreeHundredStatusRange: int64(lz.Responses.Responses3xx), + FourHundredStatusRange: int64(lz.Responses.Responses4xx), + FiveHundredStatusRange: int64(lz.Responses.Responses5xx), + } + + lzm.PreviousLocationZoneResponses[lzName] = respStatus +} + +func createPreviousLocationZoneResponses(stats *plusapi.Stats) map[string]ResponseStatuses { + previousLocationZoneResponses := make(map[string]ResponseStatuses) + for lzName, lz := range stats.LocationZones { + respStatus := ResponseStatuses{ + OneHundredStatusRange: int64(lz.Responses.Responses1xx), + TwoHundredStatusRange: int64(lz.Responses.Responses2xx), + ThreeHundredStatusRange: int64(lz.Responses.Responses3xx), + FourHundredStatusRange: int64(lz.Responses.Responses4xx), + FiveHundredStatusRange: int64(lz.Responses.Responses5xx), + } + + previousLocationZoneResponses[lzName] = respStatus + } + + return previousLocationZoneResponses +} + +func createPreviousLocationZoneRequests(stats *plusapi.Stats) map[string]int64 { + previousLocationZoneRequests := make(map[string]int64) + for lzName, lz := range stats.LocationZones { + previousLocationZoneRequests[lzName] = lz.Requests + } + + return previousLocationZoneRequests +} diff --git a/internal/collector/nginxplusreceiver/record/server_zone_metrics.go b/internal/collector/nginxplusreceiver/record/server_zone_metrics.go new file mode 100644 index 000000000..939542d37 --- /dev/null +++ b/internal/collector/nginxplusreceiver/record/server_zone_metrics.go @@ -0,0 +1,165 @@ +// Copyright (c) F5, Inc. +// +// This source code is licensed under the Apache License, Version 2.0 license found in the +// LICENSE file in the root directory of this source tree. + +package record + +import ( + "github.com/nginx/agent/v3/internal/collector/nginxplusreceiver/internal/metadata" + plusapi "github.com/nginxinc/nginx-plus-go-client/v2/client" + "go.opentelemetry.io/collector/pdata/pcommon" +) + +type ServerZoneMetrics struct { + PreviousServerZoneResponses map[string]ResponseStatuses + PreviousServerZoneRequests map[string]int64 + mb *metadata.MetricsBuilder +} + +func NewServerZoneMetrics(stats *plusapi.Stats, mb *metadata.MetricsBuilder) *ServerZoneMetrics { + return &ServerZoneMetrics{ + mb: mb, + PreviousServerZoneResponses: createPreviousServerZoneResponses(stats), + PreviousServerZoneRequests: createPreviousServerZoneRequests(stats), + } +} + +func (szm *ServerZoneMetrics) RecordServerZoneMetrics(stats *plusapi.Stats, now pcommon.Timestamp) { + for szName, sz := range stats.ServerZones { + szm.mb.RecordNginxHTTPRequestIoDataPoint( + now, + int64(sz.Received), + metadata.AttributeNginxIoDirectionReceive, + szName, + metadata.AttributeNginxZoneTypeSERVER, + ) + szm.mb.RecordNginxHTTPRequestIoDataPoint( + now, + int64(sz.Sent), + metadata.AttributeNginxIoDirectionTransmit, + szName, + metadata.AttributeNginxZoneTypeSERVER, + ) + + szm.mb.RecordNginxHTTPRequestsDataPoint(now, int64(sz.Requests), szName, metadata.AttributeNginxZoneTypeSERVER) + + szm.mb.RecordNginxHTTPRequestCountDataPoint(now, + int64(sz.Requests)-szm.PreviousServerZoneRequests[szName], + szName, + metadata.AttributeNginxZoneTypeSERVER, + ) + szm.PreviousServerZoneRequests[szName] = int64(sz.Requests) + + szm.mb.RecordNginxHTTPRequestDiscardedDataPoint(now, int64(sz.Discarded), + szName, + metadata.AttributeNginxZoneTypeSERVER, + ) + + szm.mb.RecordNginxHTTPRequestProcessingCountDataPoint(now, int64(sz.Processing), + szName, + metadata.AttributeNginxZoneTypeSERVER, + ) + + szm.recordServerZoneHTTPMetrics(sz, szName, now) + } +} + +//nolint:dupl // Duplicate of recordLocationZoneHTTPMetrics but same function can not be used due to plusapi.ServerZone +func (szm *ServerZoneMetrics) recordServerZoneHTTPMetrics(sz plusapi.ServerZone, szName string, now pcommon.Timestamp) { + // Response Status + szm.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(sz.Responses.Responses1xx), + metadata.AttributeNginxStatusRange1xx, + szName, + metadata.AttributeNginxZoneTypeSERVER, + ) + szm.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(sz.Responses.Responses2xx), + metadata.AttributeNginxStatusRange2xx, + szName, + metadata.AttributeNginxZoneTypeSERVER, + ) + szm.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(sz.Responses.Responses3xx), + metadata.AttributeNginxStatusRange3xx, + szName, + metadata.AttributeNginxZoneTypeSERVER, + ) + + szm.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(sz.Responses.Responses4xx), + metadata.AttributeNginxStatusRange4xx, + szName, + metadata.AttributeNginxZoneTypeSERVER, + ) + + szm.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(sz.Responses.Responses5xx), + metadata.AttributeNginxStatusRange5xx, + szName, + metadata.AttributeNginxZoneTypeSERVER, + ) + + // Response Count Status + szm.mb.RecordNginxHTTPResponseCountDataPoint(now, + int64(sz.Responses.Responses1xx)-szm.PreviousServerZoneResponses[szName].OneHundredStatusRange, + metadata.AttributeNginxStatusRange1xx, + szName, + metadata.AttributeNginxZoneTypeSERVER) + + szm.mb.RecordNginxHTTPResponseCountDataPoint(now, + int64(sz.Responses.Responses2xx)-szm.PreviousServerZoneResponses[szName].TwoHundredStatusRange, + metadata.AttributeNginxStatusRange2xx, + szName, + metadata.AttributeNginxZoneTypeSERVER) + + szm.mb.RecordNginxHTTPResponseCountDataPoint(now, + int64(sz.Responses.Responses3xx)-szm.PreviousServerZoneResponses[szName].ThreeHundredStatusRange, + metadata.AttributeNginxStatusRange3xx, + szName, + metadata.AttributeNginxZoneTypeSERVER) + + szm.mb.RecordNginxHTTPResponseCountDataPoint(now, + int64(sz.Responses.Responses4xx)-szm.PreviousServerZoneResponses[szName].FourHundredStatusRange, + metadata.AttributeNginxStatusRange4xx, + szName, + metadata.AttributeNginxZoneTypeSERVER) + + szm.mb.RecordNginxHTTPResponseCountDataPoint(now, + int64(sz.Responses.Responses5xx)-szm.PreviousServerZoneResponses[szName].FiveHundredStatusRange, + metadata.AttributeNginxStatusRange5xx, + szName, + metadata.AttributeNginxZoneTypeSERVER) + + respStatus := ResponseStatuses{ + OneHundredStatusRange: int64(sz.Responses.Responses1xx), + TwoHundredStatusRange: int64(sz.Responses.Responses2xx), + ThreeHundredStatusRange: int64(sz.Responses.Responses3xx), + FourHundredStatusRange: int64(sz.Responses.Responses4xx), + FiveHundredStatusRange: int64(sz.Responses.Responses5xx), + } + + szm.PreviousServerZoneResponses[szName] = respStatus +} + +func createPreviousServerZoneRequests(stats *plusapi.Stats) map[string]int64 { + previousServerZoneRequests := make(map[string]int64) + for szName, sz := range stats.ServerZones { + previousServerZoneRequests[szName] = int64(sz.Requests) + } + + return previousServerZoneRequests +} + +func createPreviousServerZoneResponses(stats *plusapi.Stats) map[string]ResponseStatuses { + previousServerZoneResponses := make(map[string]ResponseStatuses) + for szName, sz := range stats.ServerZones { + respStatus := ResponseStatuses{ + OneHundredStatusRange: int64(sz.Responses.Responses1xx), + TwoHundredStatusRange: int64(sz.Responses.Responses2xx), + ThreeHundredStatusRange: int64(sz.Responses.Responses3xx), + FourHundredStatusRange: int64(sz.Responses.Responses4xx), + FiveHundredStatusRange: int64(sz.Responses.Responses5xx), + } + + previousServerZoneResponses[szName] = respStatus + } + + return previousServerZoneResponses +} diff --git a/internal/collector/nginxplusreceiver/record/slab_metrics.go b/internal/collector/nginxplusreceiver/record/slab_metrics.go new file mode 100644 index 000000000..5ca0eb76f --- /dev/null +++ b/internal/collector/nginxplusreceiver/record/slab_metrics.go @@ -0,0 +1,48 @@ +// Copyright (c) F5, Inc. +// +// This source code is licensed under the Apache License, Version 2.0 license found in the +// LICENSE file in the root directory of this source tree. + +package record + +import ( + "strconv" + + "github.com/nginx/agent/v3/internal/collector/nginxplusreceiver/internal/metadata" + plusapi "github.com/nginxinc/nginx-plus-go-client/v2/client" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.uber.org/zap" +) + +func RecordSlabPageMetrics(mb *metadata.MetricsBuilder, stats *plusapi.Stats, now pcommon.Timestamp, + logger *zap.Logger, +) { + for name, slab := range stats.Slabs { + mb.RecordNginxSlabPageFreeDataPoint(now, int64(slab.Pages.Free), name) + mb.RecordNginxSlabPageUsageDataPoint(now, int64(slab.Pages.Used), name) + + for slotName, slot := range slab.Slots { + slotNumber, err := strconv.ParseInt(slotName, 10, 64) + if err != nil { + logger.Warn("Invalid slot name for NGINX Plus slab metrics", zap.Error(err)) + } + + mb.RecordNginxSlabSlotUsageDataPoint(now, int64(slot.Used), slotNumber, name) + mb.RecordNginxSlabSlotFreeDataPoint(now, int64(slot.Free), slotNumber, name) + mb.RecordNginxSlabSlotAllocationsDataPoint( + now, + int64(slot.Fails), + slotNumber, + metadata.AttributeNginxSlabSlotAllocationResultFAILURE, + name, + ) + mb.RecordNginxSlabSlotAllocationsDataPoint( + now, + int64(slot.Reqs), + slotNumber, + metadata.AttributeNginxSlabSlotAllocationResultSUCCESS, + name, + ) + } + } +} diff --git a/internal/collector/nginxplusreceiver/record/ssl_metrics.go b/internal/collector/nginxplusreceiver/record/ssl_metrics.go new file mode 100644 index 000000000..e8360dd80 --- /dev/null +++ b/internal/collector/nginxplusreceiver/record/ssl_metrics.go @@ -0,0 +1,80 @@ +// Copyright (c) F5, Inc. +// +// This source code is licensed under the Apache License, Version 2.0 license found in the +// LICENSE file in the root directory of this source tree. + +package record + +import ( + "github.com/nginx/agent/v3/internal/collector/nginxplusreceiver/internal/metadata" + plusapi "github.com/nginxinc/nginx-plus-go-client/v2/client" + "go.opentelemetry.io/collector/pdata/pcommon" +) + +func RecordSSLMetrics(mb *metadata.MetricsBuilder, now pcommon.Timestamp, stats *plusapi.Stats) { + // SSL Handshake + mb.RecordNginxSslHandshakesDataPoint( + now, + int64(stats.SSL.HandshakesFailed), + metadata.AttributeNginxSslStatusFAILED, + 0, + ) + mb.RecordNginxSslHandshakesDataPoint(now, int64(stats.SSL.Handshakes), 0, 0) + mb.RecordNginxSslHandshakesDataPoint( + now, + int64(stats.SSL.SessionReuses), + metadata.AttributeNginxSslStatusREUSE, + 0, + ) + mb.RecordNginxSslHandshakesDataPoint( + now, + int64(stats.SSL.NoCommonProtocol), + metadata.AttributeNginxSslStatusFAILED, + metadata.AttributeNginxSslHandshakeReasonNOCOMMONPROTOCOL, + ) + mb.RecordNginxSslHandshakesDataPoint( + now, + int64(stats.SSL.NoCommonCipher), + metadata.AttributeNginxSslStatusFAILED, + metadata.AttributeNginxSslHandshakeReasonNOCOMMONCIPHER, + ) + mb.RecordNginxSslHandshakesDataPoint( + now, + int64(stats.SSL.HandshakeTimeout), + metadata.AttributeNginxSslStatusFAILED, + metadata.AttributeNginxSslHandshakeReasonTIMEOUT, + ) + mb.RecordNginxSslHandshakesDataPoint( + now, + int64(stats.SSL.PeerRejectedCert), + metadata.AttributeNginxSslStatusFAILED, + metadata.AttributeNginxSslHandshakeReasonCERTREJECTED, + ) + + // SSL Certificate + mb.RecordNginxSslCertificateVerifyFailuresDataPoint( + now, + int64(stats.SSL.VerifyFailures.NoCert), + metadata.AttributeNginxSslVerifyFailureReasonNOCERT, + ) + mb.RecordNginxSslCertificateVerifyFailuresDataPoint( + now, + int64(stats.SSL.VerifyFailures.ExpiredCert), + metadata.AttributeNginxSslVerifyFailureReasonEXPIREDCERT, + ) + mb.RecordNginxSslCertificateVerifyFailuresDataPoint( + now, + int64(stats.SSL.VerifyFailures.RevokedCert), + metadata.AttributeNginxSslVerifyFailureReasonREVOKEDCERT, + ) + mb.RecordNginxSslCertificateVerifyFailuresDataPoint( + now, + int64(stats.SSL.VerifyFailures.HostnameMismatch), + metadata.AttributeNginxSslVerifyFailureReasonHOSTNAMEMISMATCH, + ) + mb.RecordNginxSslCertificateVerifyFailuresDataPoint( + now, + int64(stats.SSL.VerifyFailures.Other), + metadata.AttributeNginxSslVerifyFailureReasonOTHER, + ) +} diff --git a/internal/collector/nginxplusreceiver/record/stream_metrics.go b/internal/collector/nginxplusreceiver/record/stream_metrics.go new file mode 100644 index 000000000..d7aa97bb4 --- /dev/null +++ b/internal/collector/nginxplusreceiver/record/stream_metrics.go @@ -0,0 +1,265 @@ +// Copyright (c) F5, Inc. +// +// This source code is licensed under the Apache License, Version 2.0 license found in the +// LICENSE file in the root directory of this source tree. + +package record + +import ( + "github.com/nginx/agent/v3/internal/collector/nginxplusreceiver/internal/metadata" + plusapi "github.com/nginxinc/nginx-plus-go-client/v2/client" + "go.opentelemetry.io/collector/pdata/pcommon" +) + +func RecordStreamMetrics(mb *metadata.MetricsBuilder, stats *plusapi.Stats, now pcommon.Timestamp) { + for name, streamServerZone := range stats.StreamServerZones { + mb.RecordNginxStreamIoDataPoint( + now, + int64(streamServerZone.Received), + metadata.AttributeNginxIoDirectionReceive, + name, + ) + mb.RecordNginxStreamIoDataPoint( + now, + int64(streamServerZone.Sent), + metadata.AttributeNginxIoDirectionTransmit, + name, + ) + // Connection + mb.RecordNginxStreamConnectionAcceptedDataPoint(now, int64(streamServerZone.Connections), name) + mb.RecordNginxStreamConnectionDiscardedDataPoint(now, int64(streamServerZone.Discarded), name) + mb.RecordNginxStreamConnectionProcessingCountDataPoint(now, int64(streamServerZone.Processing), name) + + // Stream + mb.RecordNginxStreamSessionStatusDataPoint( + now, + int64(streamServerZone.Sessions.Sessions2xx), + metadata.AttributeNginxStatusRange2xx, + name, + ) + mb.RecordNginxStreamSessionStatusDataPoint( + now, + int64(streamServerZone.Sessions.Sessions4xx), + metadata.AttributeNginxStatusRange4xx, + name, + ) + mb.RecordNginxStreamSessionStatusDataPoint( + now, + int64(streamServerZone.Sessions.Sessions5xx), + metadata.AttributeNginxStatusRange5xx, + name, + ) + mb.RecordNginxStreamSessionStatusDataPoint(now, int64(streamServerZone.Sessions.Total), 0, name) + } + + // Stream Upstreams + for upstreamName, upstream := range stats.StreamUpstreams { + peerStates := make(map[string]int) + + for _, peer := range upstream.Peers { + mb.RecordNginxStreamUpstreamPeerIoDataPoint( + now, + int64(peer.Received), + metadata.AttributeNginxIoDirectionReceive, + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + mb.RecordNginxStreamUpstreamPeerIoDataPoint( + now, + int64(peer.Sent), + metadata.AttributeNginxIoDirectionTransmit, + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + // Connection + mb.RecordNginxStreamUpstreamPeerConnectionCountDataPoint( + now, + int64(peer.Active), + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + mb.RecordNginxStreamUpstreamPeerConnectionTimeDataPoint( + now, + int64(peer.ConnectTime), + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + + mb.RecordNginxStreamUpstreamPeerConnectionsDataPoint( + now, + int64(peer.Connections), + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + + // Health + mb.RecordNginxStreamUpstreamPeerHealthChecksDataPoint( + now, + int64(peer.HealthChecks.Checks), + 0, + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + mb.RecordNginxStreamUpstreamPeerHealthChecksDataPoint( + now, + int64(peer.HealthChecks.Fails), + metadata.AttributeNginxHealthCheckFAIL, + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + mb.RecordNginxStreamUpstreamPeerHealthChecksDataPoint( + now, + int64(peer.HealthChecks.Unhealthy), + metadata.AttributeNginxHealthCheckUNHEALTHY, + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + + // Response + mb.RecordNginxStreamUpstreamPeerResponseTimeDataPoint( + now, + int64(peer.ResponseTime), + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + mb.RecordNginxStreamUpstreamPeerTtfbTimeDataPoint( + now, + int64(peer.FirstByteTime), + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + mb.RecordNginxStreamUpstreamPeerUnavailablesDataPoint( + now, + int64(peer.Unavail), + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + + // State + mb.RecordNginxStreamUpstreamPeerStateDataPoint( + now, + boolToInt64(peer.State == peerStateChecking), + metadata.AttributeNginxPeerStateCHECKING, + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + mb.RecordNginxStreamUpstreamPeerStateDataPoint( + now, + boolToInt64(peer.State == peerStateDown), + metadata.AttributeNginxPeerStateDOWN, + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + mb.RecordNginxStreamUpstreamPeerStateDataPoint( + now, + boolToInt64(peer.State == peerStateDraining), + metadata.AttributeNginxPeerStateDRAINING, + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + mb.RecordNginxStreamUpstreamPeerStateDataPoint( + now, + boolToInt64(peer.State == peerStateUnavail), + metadata.AttributeNginxPeerStateUNAVAILABLE, + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + mb.RecordNginxStreamUpstreamPeerStateDataPoint( + now, + boolToInt64(peer.State == peerStateUnhealthy), + metadata.AttributeNginxPeerStateUNHEALTHY, + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + mb.RecordNginxStreamUpstreamPeerStateDataPoint( + now, + boolToInt64(peer.State == peerStateUp), + metadata.AttributeNginxPeerStateUP, + upstream.Zone, + upstreamName, + peer.Server, + peer.Name, + ) + + peerStates[peer.State]++ + } + + // Peer Count + mb.RecordNginxStreamUpstreamPeerCountDataPoint( + now, + int64(peerStates[peerStateChecking]), + metadata.AttributeNginxPeerStateCHECKING, + upstream.Zone, + upstreamName, + ) + mb.RecordNginxStreamUpstreamPeerCountDataPoint( + now, + int64(peerStates[peerStateDown]), + metadata.AttributeNginxPeerStateDOWN, + upstream.Zone, + upstreamName, + ) + mb.RecordNginxStreamUpstreamPeerCountDataPoint( + now, + int64(peerStates[peerStateDraining]), + metadata.AttributeNginxPeerStateDRAINING, + upstream.Zone, + upstreamName, + ) + mb.RecordNginxStreamUpstreamPeerCountDataPoint( + now, + int64(peerStates[peerStateUnavail]), + metadata.AttributeNginxPeerStateUNAVAILABLE, + upstream.Zone, + upstreamName, + ) + mb.RecordNginxStreamUpstreamPeerCountDataPoint( + now, + int64(peerStates[peerStateUnhealthy]), + metadata.AttributeNginxPeerStateUNHEALTHY, + upstream.Zone, + upstreamName, + ) + mb.RecordNginxStreamUpstreamPeerCountDataPoint( + now, + int64(peerStates[peerStateUp]), + metadata.AttributeNginxPeerStateUP, + upstream.Zone, + upstreamName, + ) + + mb.RecordNginxStreamUpstreamZombieCountDataPoint(now, int64(upstream.Zombies), upstream.Zone, upstreamName) + } +} diff --git a/internal/collector/nginxplusreceiver/record/upstream_metrics.go b/internal/collector/nginxplusreceiver/record/upstream_metrics.go new file mode 100644 index 000000000..0c06ca515 --- /dev/null +++ b/internal/collector/nginxplusreceiver/record/upstream_metrics.go @@ -0,0 +1,302 @@ +// Copyright (c) F5, Inc. +// +// This source code is licensed under the Apache License, Version 2.0 license found in the +// LICENSE file in the root directory of this source tree. + +package record + +import ( + "github.com/nginx/agent/v3/internal/collector/nginxplusreceiver/internal/metadata" + plusapi "github.com/nginxinc/nginx-plus-go-client/v2/client" + "go.opentelemetry.io/collector/pdata/pcommon" +) + +const ( + // Peer state is one of “up”, “draining”, “down”, “unavail”, “checking”, and “unhealthy”. + peerStateUp = "up" + peerStateDraining = "draining" + peerStateDown = "down" + peerStateUnavail = "unavail" + peerStateChecking = "checking" + peerStateUnhealthy = "unhealthy" +) + +func RecordHTTPUpstreamPeerMetrics(mb *metadata.MetricsBuilder, stats *plusapi.Stats, now pcommon.Timestamp) { + for name, upstream := range stats.Upstreams { + mb.RecordNginxHTTPUpstreamKeepaliveCountDataPoint(now, int64(upstream.Keepalive), upstream.Zone, name) + + peerStates := make(map[string]int) + + for _, peer := range upstream.Peers { + mb.RecordNginxHTTPUpstreamPeerIoDataPoint( + now, + int64(peer.Received), + metadata.AttributeNginxIoDirectionReceive, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerIoDataPoint( + now, + int64(peer.Sent), + metadata.AttributeNginxIoDirectionTransmit, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + + mb.RecordNginxHTTPUpstreamPeerConnectionCountDataPoint( + now, + int64(peer.Active), + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + + mb.RecordNginxHTTPUpstreamPeerFailsDataPoint( + now, + int64(peer.Fails), + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerHeaderTimeDataPoint( + now, + int64(peer.HeaderTime), + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + + mb.RecordNginxHTTPUpstreamPeerHealthChecksDataPoint( + now, + int64(peer.HealthChecks.Checks), + 0, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerHealthChecksDataPoint( + now, + int64(peer.HealthChecks.Fails), + metadata.AttributeNginxHealthCheckFAIL, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerHealthChecksDataPoint( + now, + int64(peer.HealthChecks.Unhealthy), + metadata.AttributeNginxHealthCheckUNHEALTHY, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + + mb.RecordNginxHTTPUpstreamPeerRequestsDataPoint( + now, + int64(peer.Requests), + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerResponseTimeDataPoint( + now, + int64(peer.ResponseTime), + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerResponsesDataPoint( + now, + int64(peer.Responses.Total), + 0, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + + mb.RecordNginxHTTPUpstreamPeerResponsesDataPoint( + now, + int64(peer.Responses.Responses1xx), + metadata.AttributeNginxStatusRange1xx, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerResponsesDataPoint( + now, + int64(peer.Responses.Responses2xx), + metadata.AttributeNginxStatusRange2xx, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerResponsesDataPoint( + now, + int64(peer.Responses.Responses3xx), + metadata.AttributeNginxStatusRange3xx, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerResponsesDataPoint( + now, + int64(peer.Responses.Responses4xx), + metadata.AttributeNginxStatusRange4xx, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerResponsesDataPoint( + now, + int64(peer.Responses.Responses5xx), + metadata.AttributeNginxStatusRange5xx, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + + mb.RecordNginxHTTPUpstreamPeerUnavailablesDataPoint( + now, + int64(peer.Unavail), + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + + mb.RecordNginxHTTPUpstreamPeerStateDataPoint( + now, + boolToInt64(peer.State == peerStateChecking), + metadata.AttributeNginxPeerStateCHECKING, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerStateDataPoint( + now, + boolToInt64(peer.State == peerStateDown), + metadata.AttributeNginxPeerStateDOWN, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerStateDataPoint( + now, + boolToInt64(peer.State == peerStateDraining), + metadata.AttributeNginxPeerStateDRAINING, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerStateDataPoint( + now, + boolToInt64(peer.State == peerStateUnavail), + metadata.AttributeNginxPeerStateUNAVAILABLE, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerStateDataPoint( + now, + boolToInt64(peer.State == peerStateUnhealthy), + metadata.AttributeNginxPeerStateUNHEALTHY, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + mb.RecordNginxHTTPUpstreamPeerStateDataPoint( + now, + boolToInt64(peer.State == peerStateUp), + metadata.AttributeNginxPeerStateUP, + upstream.Zone, + name, + peer.Server, + peer.Name, + ) + + peerStates[peer.State]++ + } + + // Peer Count + mb.RecordNginxHTTPUpstreamPeerCountDataPoint( + now, + int64(peerStates[peerStateChecking]), + metadata.AttributeNginxPeerStateCHECKING, + upstream.Zone, + name, + ) + mb.RecordNginxHTTPUpstreamPeerCountDataPoint( + now, + int64(peerStates[peerStateDown]), + metadata.AttributeNginxPeerStateDOWN, + upstream.Zone, + name, + ) + mb.RecordNginxHTTPUpstreamPeerCountDataPoint( + now, + int64(peerStates[peerStateDraining]), + metadata.AttributeNginxPeerStateDRAINING, + upstream.Zone, + name, + ) + mb.RecordNginxHTTPUpstreamPeerCountDataPoint( + now, + int64(peerStates[peerStateUnavail]), + metadata.AttributeNginxPeerStateUNAVAILABLE, + upstream.Zone, + name, + ) + mb.RecordNginxHTTPUpstreamPeerCountDataPoint( + now, + int64(peerStates[peerStateUnhealthy]), + metadata.AttributeNginxPeerStateUNHEALTHY, + upstream.Zone, + name, + ) + mb.RecordNginxHTTPUpstreamPeerCountDataPoint( + now, + int64(peerStates[peerStateUp]), + metadata.AttributeNginxPeerStateUP, + upstream.Zone, + name, + ) + + // Upstream Queue + mb.RecordNginxHTTPUpstreamQueueLimitDataPoint(now, int64(upstream.Queue.MaxSize), upstream.Zone, name) + mb.RecordNginxHTTPUpstreamQueueOverflowsDataPoint(now, int64(upstream.Queue.Overflows), upstream.Zone, name) + mb.RecordNginxHTTPUpstreamQueueUsageDataPoint(now, int64(upstream.Queue.Size), upstream.Zone, name) + mb.RecordNginxHTTPUpstreamZombieCountDataPoint(now, int64(upstream.Zombies), upstream.Zone, name) + } +} + +//nolint:revive // booleanValue flag is mandatory +func boolToInt64(booleanValue bool) int64 { + if booleanValue { + return 1 + } + + return 0 +} diff --git a/internal/collector/nginxplusreceiver/scraper.go b/internal/collector/nginxplusreceiver/scraper.go index e677e2451..165545e26 100644 --- a/internal/collector/nginxplusreceiver/scraper.go +++ b/internal/collector/nginxplusreceiver/scraper.go @@ -2,6 +2,7 @@ // // This source code is licensed under the Apache License, Version 2.0 license found in the // LICENSE file in the root directory of this source tree. + package nginxplusreceiver import ( @@ -12,11 +13,11 @@ import ( "net" "net/http" "os" - "strconv" "strings" "sync" "time" + "github.com/nginx/agent/v3/internal/collector/nginxplusreceiver/record" "go.opentelemetry.io/collector/component" "go.uber.org/zap" @@ -29,37 +30,17 @@ import ( plusapi "github.com/nginxinc/nginx-plus-go-client/v2/client" ) -const ( - // Peer state is one of “up”, “draining”, “down”, “unavail”, “checking”, and “unhealthy”. - peerStateUp = "up" - peerStateDraining = "draining" - peerStateDown = "down" - peerStateUnavail = "unavail" - peerStateChecking = "checking" - peerStateUnhealthy = "unhealthy" -) - type NginxPlusScraper struct { - previousServerZoneResponses map[string]ResponseStatuses - previousLocationZoneResponses map[string]ResponseStatuses - previousServerZoneRequests map[string]int64 - previousLocationZoneRequests map[string]int64 - plusClient *plusapi.NginxClient - cfg *Config - mb *metadata.MetricsBuilder - rb *metadata.ResourceBuilder - logger *zap.Logger - settings receiver.Settings - init sync.Once - previousHTTPRequestsTotal uint64 -} - -type ResponseStatuses struct { - oneHundredStatusRange int64 - twoHundredStatusRange int64 - threeHundredStatusRange int64 - fourHundredStatusRange int64 - fiveHundredStatusRange int64 + locationZoneMetrics *record.LocationZoneMetrics + serverZoneMetrics *record.ServerZoneMetrics + httpMetrics *record.HTTPMetrics + plusClient *plusapi.NginxClient + cfg *Config + mb *metadata.MetricsBuilder + rb *metadata.ResourceBuilder + logger *zap.Logger + settings receiver.Settings + init sync.Once } func newNginxPlusScraper( @@ -136,11 +117,9 @@ func (nps *NginxPlusScraper) Scrape(ctx context.Context) (pmetric.Metrics, error return } - nps.previousHTTPRequestsTotal = stats.HTTPRequests.Total - nps.createPreviousServerZoneResponses(stats) - nps.createPreviousLocationZoneResponses(stats) - nps.createPreviousServerZoneRequests(stats) - nps.createPreviousLocationZoneRequests(stats) + nps.httpMetrics = record.NewHTTPMetrics(stats, nps.mb) + nps.locationZoneMetrics = record.NewLocationZoneMetrics(stats, nps.mb) + nps.serverZoneMetrics = record.NewServerZoneMetrics(stats, nps.mb) }) stats, err := nps.plusClient.GetStats(ctx) @@ -162,1083 +141,25 @@ func (nps *NginxPlusScraper) Shutdown(ctx context.Context) error { return nil } -func (nps *NginxPlusScraper) createPreviousLocationZoneResponses(stats *plusapi.Stats) { - previousLocationZoneResponses := make(map[string]ResponseStatuses) - for lzName, lz := range stats.LocationZones { - respStatus := ResponseStatuses{ - oneHundredStatusRange: int64(lz.Responses.Responses1xx), - twoHundredStatusRange: int64(lz.Responses.Responses2xx), - threeHundredStatusRange: int64(lz.Responses.Responses3xx), - fourHundredStatusRange: int64(lz.Responses.Responses4xx), - fiveHundredStatusRange: int64(lz.Responses.Responses5xx), - } - - previousLocationZoneResponses[lzName] = respStatus - } - - nps.previousLocationZoneResponses = previousLocationZoneResponses -} - -func (nps *NginxPlusScraper) createPreviousServerZoneRequests(stats *plusapi.Stats) { - previousServerZoneRequests := make(map[string]int64) - for szName, sz := range stats.ServerZones { - previousServerZoneRequests[szName] = int64(sz.Requests) - } - nps.previousServerZoneRequests = previousServerZoneRequests -} - -func (nps *NginxPlusScraper) createPreviousLocationZoneRequests(stats *plusapi.Stats) { - previousLocationZoneRequests := make(map[string]int64) - for lzName, lz := range stats.LocationZones { - previousLocationZoneRequests[lzName] = lz.Requests - } - nps.previousLocationZoneRequests = previousLocationZoneRequests -} - -func (nps *NginxPlusScraper) createPreviousServerZoneResponses(stats *plusapi.Stats) { - previousServerZoneResponses := make(map[string]ResponseStatuses) - for szName, sz := range stats.ServerZones { - respStatus := ResponseStatuses{ - oneHundredStatusRange: int64(sz.Responses.Responses1xx), - twoHundredStatusRange: int64(sz.Responses.Responses2xx), - threeHundredStatusRange: int64(sz.Responses.Responses3xx), - fourHundredStatusRange: int64(sz.Responses.Responses4xx), - fiveHundredStatusRange: int64(sz.Responses.Responses5xx), - } - - previousServerZoneResponses[szName] = respStatus - } - - nps.previousServerZoneResponses = previousServerZoneResponses -} - func (nps *NginxPlusScraper) recordMetrics(stats *plusapi.Stats) { now := pcommon.NewTimestampFromTime(time.Now()) // NGINX config reloads nps.mb.RecordNginxConfigReloadsDataPoint(now, int64(stats.NginxInfo.Generation)) - // Connections - nps.mb.RecordNginxHTTPConnectionsDataPoint( - now, - int64(stats.Connections.Accepted), - metadata.AttributeNginxConnectionsOutcomeACCEPTED, - ) - nps.mb.RecordNginxHTTPConnectionsDataPoint( - now, - int64(stats.Connections.Dropped), - metadata.AttributeNginxConnectionsOutcomeDROPPED, - ) - nps.mb.RecordNginxHTTPConnectionCountDataPoint( - now, - int64(stats.Connections.Active), - metadata.AttributeNginxConnectionsOutcomeACTIVE, - ) - nps.mb.RecordNginxHTTPConnectionCountDataPoint( - now, - int64(stats.Connections.Idle), - metadata.AttributeNginxConnectionsOutcomeIDLE, - ) - - // HTTP Requests - nps.mb.RecordNginxHTTPRequestsDataPoint(now, int64(stats.HTTPRequests.Total), "", 0) - - requestsDiff := int64(stats.HTTPRequests.Total) - int64(nps.previousHTTPRequestsTotal) - nps.mb.RecordNginxHTTPRequestCountDataPoint(now, requestsDiff, "", 0) - nps.previousHTTPRequestsTotal = stats.HTTPRequests.Total - - nps.recordCacheMetrics(stats, now) - nps.recordHTTPLimitMetrics(stats, now) - nps.recordLocationZoneMetrics(stats, now) - nps.recordServerZoneMetrics(stats, now) - nps.recordHTTPUpstreamPeerMetrics(stats, now) - nps.recordSlabPageMetrics(stats, now) - nps.recordSSLMetrics(now, stats) - nps.recordStreamMetrics(stats, now) -} - -func (nps *NginxPlusScraper) recordStreamMetrics(stats *plusapi.Stats, now pcommon.Timestamp) { - for name, streamServerZone := range stats.StreamServerZones { - nps.mb.RecordNginxStreamIoDataPoint( - now, - int64(streamServerZone.Received), - metadata.AttributeNginxIoDirectionReceive, - name, - ) - nps.mb.RecordNginxStreamIoDataPoint( - now, - int64(streamServerZone.Sent), - metadata.AttributeNginxIoDirectionTransmit, - name, - ) - nps.mb.RecordNginxStreamConnectionAcceptedDataPoint(now, int64(streamServerZone.Connections), name) - nps.mb.RecordNginxStreamConnectionDiscardedDataPoint(now, int64(streamServerZone.Discarded), name) - nps.mb.RecordNginxStreamConnectionProcessingCountDataPoint(now, int64(streamServerZone.Processing), name) - nps.mb.RecordNginxStreamSessionStatusDataPoint( - now, - int64(streamServerZone.Sessions.Sessions2xx), - metadata.AttributeNginxStatusRange2xx, - name, - ) - nps.mb.RecordNginxStreamSessionStatusDataPoint( - now, - int64(streamServerZone.Sessions.Sessions4xx), - metadata.AttributeNginxStatusRange4xx, - name, - ) - nps.mb.RecordNginxStreamSessionStatusDataPoint( - now, - int64(streamServerZone.Sessions.Sessions5xx), - metadata.AttributeNginxStatusRange5xx, - name, - ) - nps.mb.RecordNginxStreamSessionStatusDataPoint(now, int64(streamServerZone.Sessions.Total), 0, name) - } - - for upstreamName, upstream := range stats.StreamUpstreams { - peerStates := make(map[string]int) - - for _, peer := range upstream.Peers { - nps.mb.RecordNginxStreamUpstreamPeerIoDataPoint( - now, - int64(peer.Received), - metadata.AttributeNginxIoDirectionReceive, - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxStreamUpstreamPeerIoDataPoint( - now, - int64(peer.Sent), - metadata.AttributeNginxIoDirectionTransmit, - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxStreamUpstreamPeerConnectionCountDataPoint( - now, - int64(peer.Active), - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxStreamUpstreamPeerConnectionTimeDataPoint( - now, - int64(peer.ConnectTime), - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - - nps.mb.RecordNginxStreamUpstreamPeerConnectionsDataPoint( - now, - int64(peer.Connections), - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - - nps.mb.RecordNginxStreamUpstreamPeerHealthChecksDataPoint( - now, - int64(peer.HealthChecks.Checks), - 0, - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxStreamUpstreamPeerHealthChecksDataPoint( - now, - int64(peer.HealthChecks.Fails), - metadata.AttributeNginxHealthCheckFAIL, - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxStreamUpstreamPeerHealthChecksDataPoint( - now, - int64(peer.HealthChecks.Unhealthy), - metadata.AttributeNginxHealthCheckUNHEALTHY, - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - - nps.mb.RecordNginxStreamUpstreamPeerResponseTimeDataPoint( - now, - int64(peer.ResponseTime), - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxStreamUpstreamPeerTtfbTimeDataPoint( - now, - int64(peer.FirstByteTime), - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxStreamUpstreamPeerUnavailablesDataPoint( - now, - int64(peer.Unavail), - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - - nps.mb.RecordNginxStreamUpstreamPeerStateDataPoint( - now, - boolToInt64(peer.State == peerStateChecking), - metadata.AttributeNginxPeerStateCHECKING, - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxStreamUpstreamPeerStateDataPoint( - now, - boolToInt64(peer.State == peerStateDown), - metadata.AttributeNginxPeerStateDOWN, - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxStreamUpstreamPeerStateDataPoint( - now, - boolToInt64(peer.State == peerStateDraining), - metadata.AttributeNginxPeerStateDRAINING, - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxStreamUpstreamPeerStateDataPoint( - now, - boolToInt64(peer.State == peerStateUnavail), - metadata.AttributeNginxPeerStateUNAVAILABLE, - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxStreamUpstreamPeerStateDataPoint( - now, - boolToInt64(peer.State == peerStateUnhealthy), - metadata.AttributeNginxPeerStateUNHEALTHY, - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxStreamUpstreamPeerStateDataPoint( - now, - boolToInt64(peer.State == peerStateUp), - metadata.AttributeNginxPeerStateUP, - upstream.Zone, - upstreamName, - peer.Server, - peer.Name, - ) - - peerStates[peer.State]++ - } - - nps.mb.RecordNginxStreamUpstreamPeerCountDataPoint( - now, - int64(peerStates[peerStateChecking]), - metadata.AttributeNginxPeerStateCHECKING, - upstream.Zone, - upstreamName, - ) - nps.mb.RecordNginxStreamUpstreamPeerCountDataPoint( - now, - int64(peerStates[peerStateDown]), - metadata.AttributeNginxPeerStateDOWN, - upstream.Zone, - upstreamName, - ) - nps.mb.RecordNginxStreamUpstreamPeerCountDataPoint( - now, - int64(peerStates[peerStateDraining]), - metadata.AttributeNginxPeerStateDRAINING, - upstream.Zone, - upstreamName, - ) - nps.mb.RecordNginxStreamUpstreamPeerCountDataPoint( - now, - int64(peerStates[peerStateUnavail]), - metadata.AttributeNginxPeerStateUNAVAILABLE, - upstream.Zone, - upstreamName, - ) - nps.mb.RecordNginxStreamUpstreamPeerCountDataPoint( - now, - int64(peerStates[peerStateUnhealthy]), - metadata.AttributeNginxPeerStateUNHEALTHY, - upstream.Zone, - upstreamName, - ) - nps.mb.RecordNginxStreamUpstreamPeerCountDataPoint( - now, - int64(peerStates[peerStateUp]), - metadata.AttributeNginxPeerStateUP, - upstream.Zone, - upstreamName, - ) - - nps.mb.RecordNginxStreamUpstreamZombieCountDataPoint(now, int64(upstream.Zombies), upstream.Zone, upstreamName) - } -} - -func (nps *NginxPlusScraper) recordSSLMetrics(now pcommon.Timestamp, stats *plusapi.Stats) { - nps.mb.RecordNginxSslHandshakesDataPoint( - now, - int64(stats.SSL.HandshakesFailed), - metadata.AttributeNginxSslStatusFAILED, - 0, - ) - nps.mb.RecordNginxSslHandshakesDataPoint(now, int64(stats.SSL.Handshakes), 0, 0) - nps.mb.RecordNginxSslHandshakesDataPoint( - now, - int64(stats.SSL.SessionReuses), - metadata.AttributeNginxSslStatusREUSE, - 0, - ) - nps.mb.RecordNginxSslHandshakesDataPoint( - now, - int64(stats.SSL.NoCommonProtocol), - metadata.AttributeNginxSslStatusFAILED, - metadata.AttributeNginxSslHandshakeReasonNOCOMMONPROTOCOL, - ) - nps.mb.RecordNginxSslHandshakesDataPoint( - now, - int64(stats.SSL.NoCommonCipher), - metadata.AttributeNginxSslStatusFAILED, - metadata.AttributeNginxSslHandshakeReasonNOCOMMONCIPHER, - ) - nps.mb.RecordNginxSslHandshakesDataPoint( - now, - int64(stats.SSL.HandshakeTimeout), - metadata.AttributeNginxSslStatusFAILED, - metadata.AttributeNginxSslHandshakeReasonTIMEOUT, - ) - nps.mb.RecordNginxSslHandshakesDataPoint( - now, - int64(stats.SSL.PeerRejectedCert), - metadata.AttributeNginxSslStatusFAILED, - metadata.AttributeNginxSslHandshakeReasonCERTREJECTED, - ) - - nps.mb.RecordNginxSslCertificateVerifyFailuresDataPoint( - now, - int64(stats.SSL.VerifyFailures.NoCert), - metadata.AttributeNginxSslVerifyFailureReasonNOCERT, - ) - nps.mb.RecordNginxSslCertificateVerifyFailuresDataPoint( - now, - int64(stats.SSL.VerifyFailures.ExpiredCert), - metadata.AttributeNginxSslVerifyFailureReasonEXPIREDCERT, - ) - nps.mb.RecordNginxSslCertificateVerifyFailuresDataPoint( - now, - int64(stats.SSL.VerifyFailures.RevokedCert), - metadata.AttributeNginxSslVerifyFailureReasonREVOKEDCERT, - ) - nps.mb.RecordNginxSslCertificateVerifyFailuresDataPoint( - now, - int64(stats.SSL.VerifyFailures.HostnameMismatch), - metadata.AttributeNginxSslVerifyFailureReasonHOSTNAMEMISMATCH, - ) - nps.mb.RecordNginxSslCertificateVerifyFailuresDataPoint( - now, - int64(stats.SSL.VerifyFailures.Other), - metadata.AttributeNginxSslVerifyFailureReasonOTHER, - ) -} - -func (nps *NginxPlusScraper) recordSlabPageMetrics(stats *plusapi.Stats, now pcommon.Timestamp) { - for name, slab := range stats.Slabs { - nps.mb.RecordNginxSlabPageFreeDataPoint(now, int64(slab.Pages.Free), name) - nps.mb.RecordNginxSlabPageUsageDataPoint(now, int64(slab.Pages.Used), name) - - for slotName, slot := range slab.Slots { - slotNumber, err := strconv.ParseInt(slotName, 10, 64) - if err != nil { - nps.logger.Warn("Invalid slot name for NGINX Plus slab metrics", zap.Error(err)) - } - - nps.mb.RecordNginxSlabSlotUsageDataPoint(now, int64(slot.Used), slotNumber, name) - nps.mb.RecordNginxSlabSlotFreeDataPoint(now, int64(slot.Free), slotNumber, name) - nps.mb.RecordNginxSlabSlotAllocationsDataPoint( - now, - int64(slot.Fails), - slotNumber, - metadata.AttributeNginxSlabSlotAllocationResultFAILURE, - name, - ) - nps.mb.RecordNginxSlabSlotAllocationsDataPoint( - now, - int64(slot.Reqs), - slotNumber, - metadata.AttributeNginxSlabSlotAllocationResultSUCCESS, - name, - ) - } - } -} - -func (nps *NginxPlusScraper) recordHTTPUpstreamPeerMetrics(stats *plusapi.Stats, now pcommon.Timestamp) { - for name, upstream := range stats.Upstreams { - nps.mb.RecordNginxHTTPUpstreamKeepaliveCountDataPoint(now, int64(upstream.Keepalive), upstream.Zone, name) - - peerStates := make(map[string]int) - - for _, peer := range upstream.Peers { - nps.mb.RecordNginxHTTPUpstreamPeerIoDataPoint( - now, - int64(peer.Received), - metadata.AttributeNginxIoDirectionReceive, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerIoDataPoint( - now, - int64(peer.Sent), - metadata.AttributeNginxIoDirectionTransmit, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - - nps.mb.RecordNginxHTTPUpstreamPeerConnectionCountDataPoint( - now, - int64(peer.Active), - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - - nps.mb.RecordNginxHTTPUpstreamPeerFailsDataPoint( - now, - int64(peer.Fails), - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerHeaderTimeDataPoint( - now, - int64(peer.HeaderTime), - upstream.Zone, - name, - peer.Server, - peer.Name, - ) + nps.httpMetrics.RecordHTTPMetrics(stats, now) + nps.httpMetrics.RecordHTTPLimitMetrics(stats, now) - nps.mb.RecordNginxHTTPUpstreamPeerHealthChecksDataPoint( - now, - int64(peer.HealthChecks.Checks), - 0, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerHealthChecksDataPoint( - now, - int64(peer.HealthChecks.Fails), - metadata.AttributeNginxHealthCheckFAIL, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerHealthChecksDataPoint( - now, - int64(peer.HealthChecks.Unhealthy), - metadata.AttributeNginxHealthCheckUNHEALTHY, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) + nps.locationZoneMetrics.RecordLocationZoneMetrics(stats, now) + nps.serverZoneMetrics.RecordServerZoneMetrics(stats, now) - nps.mb.RecordNginxHTTPUpstreamPeerRequestsDataPoint( - now, - int64(peer.Requests), - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerResponseTimeDataPoint( - now, - int64(peer.ResponseTime), - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerResponsesDataPoint( - now, - int64(peer.Responses.Total), - 0, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) + record.RecordCacheMetrics(nps.mb, stats, now) - nps.mb.RecordNginxHTTPUpstreamPeerResponsesDataPoint( - now, - int64(peer.Responses.Responses1xx), - metadata.AttributeNginxStatusRange1xx, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerResponsesDataPoint( - now, - int64(peer.Responses.Responses2xx), - metadata.AttributeNginxStatusRange2xx, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerResponsesDataPoint( - now, - int64(peer.Responses.Responses3xx), - metadata.AttributeNginxStatusRange3xx, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerResponsesDataPoint( - now, - int64(peer.Responses.Responses4xx), - metadata.AttributeNginxStatusRange4xx, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerResponsesDataPoint( - now, - int64(peer.Responses.Responses5xx), - metadata.AttributeNginxStatusRange5xx, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) + record.RecordHTTPUpstreamPeerMetrics(nps.mb, stats, now) + record.RecordStreamMetrics(nps.mb, stats, now) - nps.mb.RecordNginxHTTPUpstreamPeerUnavailablesDataPoint( - now, - int64(peer.Unavail), - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - - nps.mb.RecordNginxHTTPUpstreamPeerStateDataPoint( - now, - boolToInt64(peer.State == peerStateChecking), - metadata.AttributeNginxPeerStateCHECKING, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerStateDataPoint( - now, - boolToInt64(peer.State == peerStateDown), - metadata.AttributeNginxPeerStateDOWN, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerStateDataPoint( - now, - boolToInt64(peer.State == peerStateDraining), - metadata.AttributeNginxPeerStateDRAINING, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerStateDataPoint( - now, - boolToInt64(peer.State == peerStateUnavail), - metadata.AttributeNginxPeerStateUNAVAILABLE, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerStateDataPoint( - now, - boolToInt64(peer.State == peerStateUnhealthy), - metadata.AttributeNginxPeerStateUNHEALTHY, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerStateDataPoint( - now, - boolToInt64(peer.State == peerStateUp), - metadata.AttributeNginxPeerStateUP, - upstream.Zone, - name, - peer.Server, - peer.Name, - ) - - peerStates[peer.State]++ - } - - nps.mb.RecordNginxHTTPUpstreamPeerCountDataPoint( - now, - int64(peerStates[peerStateChecking]), - metadata.AttributeNginxPeerStateCHECKING, - upstream.Zone, - name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerCountDataPoint( - now, - int64(peerStates[peerStateDown]), - metadata.AttributeNginxPeerStateDOWN, - upstream.Zone, - name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerCountDataPoint( - now, - int64(peerStates[peerStateDraining]), - metadata.AttributeNginxPeerStateDRAINING, - upstream.Zone, - name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerCountDataPoint( - now, - int64(peerStates[peerStateUnavail]), - metadata.AttributeNginxPeerStateUNAVAILABLE, - upstream.Zone, - name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerCountDataPoint( - now, - int64(peerStates[peerStateUnhealthy]), - metadata.AttributeNginxPeerStateUNHEALTHY, - upstream.Zone, - name, - ) - nps.mb.RecordNginxHTTPUpstreamPeerCountDataPoint( - now, - int64(peerStates[peerStateUp]), - metadata.AttributeNginxPeerStateUP, - upstream.Zone, - name, - ) - - nps.mb.RecordNginxHTTPUpstreamQueueLimitDataPoint(now, int64(upstream.Queue.MaxSize), upstream.Zone, name) - nps.mb.RecordNginxHTTPUpstreamQueueOverflowsDataPoint(now, int64(upstream.Queue.Overflows), upstream.Zone, name) - nps.mb.RecordNginxHTTPUpstreamQueueUsageDataPoint(now, int64(upstream.Queue.Size), upstream.Zone, name) - nps.mb.RecordNginxHTTPUpstreamZombieCountDataPoint(now, int64(upstream.Zombies), upstream.Zone, name) - } -} - -func (nps *NginxPlusScraper) recordServerZoneMetrics(stats *plusapi.Stats, now pcommon.Timestamp) { - for szName, sz := range stats.ServerZones { - nps.mb.RecordNginxHTTPRequestIoDataPoint( - now, - int64(sz.Received), - metadata.AttributeNginxIoDirectionReceive, - szName, - metadata.AttributeNginxZoneTypeSERVER, - ) - nps.mb.RecordNginxHTTPRequestIoDataPoint( - now, - int64(sz.Sent), - metadata.AttributeNginxIoDirectionTransmit, - szName, - metadata.AttributeNginxZoneTypeSERVER, - ) - - nps.mb.RecordNginxHTTPRequestsDataPoint(now, int64(sz.Requests), szName, metadata.AttributeNginxZoneTypeSERVER) - - nps.mb.RecordNginxHTTPRequestCountDataPoint(now, - int64(sz.Requests)-nps.previousServerZoneRequests[szName], - szName, - metadata.AttributeNginxZoneTypeSERVER, - ) - nps.previousServerZoneRequests[szName] = int64(sz.Requests) - - nps.recordServerZoneHTTPMetrics(sz, szName, now) - - nps.mb.RecordNginxHTTPRequestDiscardedDataPoint(now, int64(sz.Discarded), - szName, - metadata.AttributeNginxZoneTypeSERVER, - ) - - nps.mb.RecordNginxHTTPRequestProcessingCountDataPoint(now, int64(sz.Processing), - szName, - metadata.AttributeNginxZoneTypeSERVER, - ) - } -} - -//nolint:dupl // Duplicate of recordLocationZoneHTTPMetrics but same function can not be used due to plusapi.ServerZone -func (nps *NginxPlusScraper) recordServerZoneHTTPMetrics(sz plusapi.ServerZone, szName string, now pcommon.Timestamp) { - nps.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(sz.Responses.Responses1xx), - metadata.AttributeNginxStatusRange1xx, - szName, - metadata.AttributeNginxZoneTypeSERVER, - ) - nps.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(sz.Responses.Responses2xx), - metadata.AttributeNginxStatusRange2xx, - szName, - metadata.AttributeNginxZoneTypeSERVER, - ) - nps.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(sz.Responses.Responses3xx), - metadata.AttributeNginxStatusRange3xx, - szName, - metadata.AttributeNginxZoneTypeSERVER, - ) - - nps.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(sz.Responses.Responses4xx), - metadata.AttributeNginxStatusRange4xx, - szName, - metadata.AttributeNginxZoneTypeSERVER, - ) - - nps.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(sz.Responses.Responses5xx), - metadata.AttributeNginxStatusRange5xx, - szName, - metadata.AttributeNginxZoneTypeSERVER, - ) - - nps.mb.RecordNginxHTTPResponseCountDataPoint(now, - int64(sz.Responses.Responses1xx)-nps.previousServerZoneResponses[szName].oneHundredStatusRange, - metadata.AttributeNginxStatusRange1xx, - szName, - metadata.AttributeNginxZoneTypeSERVER) - - nps.mb.RecordNginxHTTPResponseCountDataPoint(now, - int64(sz.Responses.Responses2xx)-nps.previousServerZoneResponses[szName].twoHundredStatusRange, - metadata.AttributeNginxStatusRange2xx, - szName, - metadata.AttributeNginxZoneTypeSERVER) - - nps.mb.RecordNginxHTTPResponseCountDataPoint(now, - int64(sz.Responses.Responses3xx)-nps.previousServerZoneResponses[szName].threeHundredStatusRange, - metadata.AttributeNginxStatusRange3xx, - szName, - metadata.AttributeNginxZoneTypeSERVER) - - nps.mb.RecordNginxHTTPResponseCountDataPoint(now, - int64(sz.Responses.Responses4xx)-nps.previousServerZoneResponses[szName].fourHundredStatusRange, - metadata.AttributeNginxStatusRange4xx, - szName, - metadata.AttributeNginxZoneTypeSERVER) - - nps.mb.RecordNginxHTTPResponseCountDataPoint(now, - int64(sz.Responses.Responses5xx)-nps.previousServerZoneResponses[szName].fiveHundredStatusRange, - metadata.AttributeNginxStatusRange5xx, - szName, - metadata.AttributeNginxZoneTypeSERVER) - - respStatus := ResponseStatuses{ - oneHundredStatusRange: int64(sz.Responses.Responses1xx), - twoHundredStatusRange: int64(sz.Responses.Responses2xx), - threeHundredStatusRange: int64(sz.Responses.Responses3xx), - fourHundredStatusRange: int64(sz.Responses.Responses4xx), - fiveHundredStatusRange: int64(sz.Responses.Responses5xx), - } - - nps.previousServerZoneResponses[szName] = respStatus -} - -func (nps *NginxPlusScraper) recordLocationZoneMetrics(stats *plusapi.Stats, now pcommon.Timestamp) { - for lzName, lz := range stats.LocationZones { - nps.mb.RecordNginxHTTPRequestIoDataPoint( - now, - lz.Received, - metadata.AttributeNginxIoDirectionReceive, - lzName, - metadata.AttributeNginxZoneTypeLOCATION, - ) - nps.mb.RecordNginxHTTPRequestIoDataPoint( - now, - lz.Sent, - metadata.AttributeNginxIoDirectionTransmit, - lzName, - metadata.AttributeNginxZoneTypeLOCATION, - ) - - nps.mb.RecordNginxHTTPRequestsDataPoint( - now, - lz.Requests, - lzName, - metadata.AttributeNginxZoneTypeLOCATION, - ) - - nps.mb.RecordNginxHTTPRequestCountDataPoint(now, - lz.Requests-nps.previousLocationZoneRequests[lzName], - lzName, - metadata.AttributeNginxZoneTypeLOCATION, - ) - - nps.previousLocationZoneRequests[lzName] = lz.Requests - - nps.recordLocationZoneHTTPMetrics(lz, lzName, now) - - nps.mb.RecordNginxHTTPRequestDiscardedDataPoint(now, lz.Discarded, - lzName, - metadata.AttributeNginxZoneTypeLOCATION, - ) - } -} - -//nolint:dupl // Duplicate of recordServerZoneHTTPMetrics but same function can not be used due to plusapi.LocationZone -func (nps *NginxPlusScraper) recordLocationZoneHTTPMetrics(lz plusapi.LocationZone, - lzName string, now pcommon.Timestamp, -) { - nps.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(lz.Responses.Responses1xx), - metadata.AttributeNginxStatusRange1xx, - lzName, - metadata.AttributeNginxZoneTypeLOCATION, - ) - nps.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(lz.Responses.Responses2xx), - metadata.AttributeNginxStatusRange2xx, - lzName, - metadata.AttributeNginxZoneTypeLOCATION, - ) - nps.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(lz.Responses.Responses3xx), - metadata.AttributeNginxStatusRange3xx, - lzName, - metadata.AttributeNginxZoneTypeLOCATION, - ) - - nps.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(lz.Responses.Responses4xx), - metadata.AttributeNginxStatusRange4xx, - lzName, - metadata.AttributeNginxZoneTypeLOCATION, - ) - - nps.mb.RecordNginxHTTPResponseStatusDataPoint(now, int64(lz.Responses.Responses5xx), - metadata.AttributeNginxStatusRange5xx, - lzName, - metadata.AttributeNginxZoneTypeLOCATION, - ) - - nps.mb.RecordNginxHTTPResponseCountDataPoint(now, - int64(lz.Responses.Responses1xx)-nps.previousLocationZoneResponses[lzName].oneHundredStatusRange, - metadata.AttributeNginxStatusRange1xx, - lzName, - metadata.AttributeNginxZoneTypeLOCATION) - - nps.mb.RecordNginxHTTPResponseCountDataPoint(now, - int64(lz.Responses.Responses2xx)-nps.previousLocationZoneResponses[lzName].twoHundredStatusRange, - metadata.AttributeNginxStatusRange2xx, - lzName, - metadata.AttributeNginxZoneTypeLOCATION) - - nps.mb.RecordNginxHTTPResponseCountDataPoint(now, - int64(lz.Responses.Responses3xx)-nps.previousLocationZoneResponses[lzName].threeHundredStatusRange, - metadata.AttributeNginxStatusRange3xx, - lzName, - metadata.AttributeNginxZoneTypeLOCATION) - - nps.mb.RecordNginxHTTPResponseCountDataPoint(now, - int64(lz.Responses.Responses4xx)-nps.previousLocationZoneResponses[lzName].fourHundredStatusRange, - metadata.AttributeNginxStatusRange4xx, - lzName, - metadata.AttributeNginxZoneTypeLOCATION) - - nps.mb.RecordNginxHTTPResponseCountDataPoint(now, - int64(lz.Responses.Responses5xx)-nps.previousLocationZoneResponses[lzName].fiveHundredStatusRange, - metadata.AttributeNginxStatusRange5xx, - lzName, - metadata.AttributeNginxZoneTypeLOCATION) - - respStatus := ResponseStatuses{ - oneHundredStatusRange: int64(lz.Responses.Responses1xx), - twoHundredStatusRange: int64(lz.Responses.Responses2xx), - threeHundredStatusRange: int64(lz.Responses.Responses3xx), - fourHundredStatusRange: int64(lz.Responses.Responses4xx), - fiveHundredStatusRange: int64(lz.Responses.Responses5xx), - } - - nps.previousLocationZoneResponses[lzName] = respStatus -} - -func (nps *NginxPlusScraper) recordHTTPLimitMetrics(stats *plusapi.Stats, now pcommon.Timestamp) { - for name, limitConnection := range stats.HTTPLimitConnections { - nps.mb.RecordNginxHTTPLimitConnRequestsDataPoint( - now, - int64(limitConnection.Passed), - metadata.AttributeNginxLimitConnOutcomePASSED, - name, - ) - nps.mb.RecordNginxHTTPLimitConnRequestsDataPoint( - now, - int64(limitConnection.Rejected), - metadata.AttributeNginxLimitConnOutcomeREJECTED, - name, - ) - nps.mb.RecordNginxHTTPLimitConnRequestsDataPoint( - now, - int64(limitConnection.RejectedDryRun), - metadata.AttributeNginxLimitConnOutcomeREJECTEDDRYRUN, - name, - ) - } - - for name, limitRequest := range stats.HTTPLimitRequests { - nps.mb.RecordNginxHTTPLimitReqRequestsDataPoint( - now, - int64(limitRequest.Passed), - metadata.AttributeNginxLimitReqOutcomePASSED, - name, - ) - nps.mb.RecordNginxHTTPLimitReqRequestsDataPoint( - now, - int64(limitRequest.Rejected), - metadata.AttributeNginxLimitReqOutcomeREJECTED, - name, - ) - nps.mb.RecordNginxHTTPLimitReqRequestsDataPoint( - now, - int64(limitRequest.RejectedDryRun), - metadata.AttributeNginxLimitReqOutcomeREJECTEDDRYRUN, - name, - ) - nps.mb.RecordNginxHTTPLimitReqRequestsDataPoint( - now, - int64(limitRequest.Delayed), - metadata.AttributeNginxLimitReqOutcomeDELAYED, - name, - ) - nps.mb.RecordNginxHTTPLimitReqRequestsDataPoint( - now, - int64(limitRequest.DelayedDryRun), - metadata.AttributeNginxLimitReqOutcomeDELAYEDDRYRUN, - name, - ) - } -} - -func (nps *NginxPlusScraper) recordCacheMetrics(stats *plusapi.Stats, now pcommon.Timestamp) { - for name, cache := range stats.Caches { - nps.mb.RecordNginxCacheBytesReadDataPoint( - now, - int64(cache.Bypass.Bytes), - metadata.AttributeNginxCacheOutcomeBYPASS, - name, - ) - nps.mb.RecordNginxCacheBytesReadDataPoint( - now, - int64(cache.Expired.Bytes), - metadata.AttributeNginxCacheOutcomeEXPIRED, - name, - ) - nps.mb.RecordNginxCacheBytesReadDataPoint( - now, - int64(cache.Hit.Bytes), - metadata.AttributeNginxCacheOutcomeHIT, - name, - ) - nps.mb.RecordNginxCacheBytesReadDataPoint( - now, - int64(cache.Miss.Bytes), - metadata.AttributeNginxCacheOutcomeMISS, - name, - ) - nps.mb.RecordNginxCacheBytesReadDataPoint( - now, - int64(cache.Revalidated.Bytes), - metadata.AttributeNginxCacheOutcomeREVALIDATED, - name, - ) - nps.mb.RecordNginxCacheBytesReadDataPoint( - now, - int64(cache.Stale.Bytes), - metadata.AttributeNginxCacheOutcomeSTALE, - name, - ) - nps.mb.RecordNginxCacheBytesReadDataPoint( - now, - int64(cache.Updating.Bytes), - metadata.AttributeNginxCacheOutcomeUPDATING, - name, - ) - - nps.mb.RecordNginxCacheMemoryLimitDataPoint(now, int64(cache.MaxSize), name) - nps.mb.RecordNginxCacheMemoryUsageDataPoint(now, int64(cache.Size), name) - - nps.mb.RecordNginxCacheResponsesDataPoint( - now, - int64(cache.Bypass.Responses), - metadata.AttributeNginxCacheOutcomeBYPASS, - name, - ) - nps.mb.RecordNginxCacheResponsesDataPoint( - now, - int64(cache.Expired.Responses), - metadata.AttributeNginxCacheOutcomeEXPIRED, - name, - ) - nps.mb.RecordNginxCacheResponsesDataPoint( - now, - int64(cache.Hit.Responses), - metadata.AttributeNginxCacheOutcomeHIT, - name, - ) - nps.mb.RecordNginxCacheResponsesDataPoint( - now, - int64(cache.Miss.Responses), - metadata.AttributeNginxCacheOutcomeMISS, - name, - ) - nps.mb.RecordNginxCacheResponsesDataPoint( - now, - int64(cache.Revalidated.Responses), - metadata.AttributeNginxCacheOutcomeREVALIDATED, - name, - ) - nps.mb.RecordNginxCacheResponsesDataPoint( - now, - int64(cache.Stale.Responses), - metadata.AttributeNginxCacheOutcomeSTALE, - name, - ) - nps.mb.RecordNginxCacheResponsesDataPoint( - now, - int64(cache.Updating.Responses), - metadata.AttributeNginxCacheOutcomeUPDATING, - name, - ) - } + record.RecordSlabPageMetrics(nps.mb, stats, now, nps.logger) + record.RecordSSLMetrics(nps.mb, now, stats) } func socketClient(ctx context.Context, socketPath string) *http.Client { @@ -1251,12 +172,3 @@ func socketClient(ctx context.Context, socketPath string) *http.Client { }, } } - -//nolint:revive // booleanValue flag is mandatory -func boolToInt64(booleanValue bool) int64 { - if booleanValue { - return 1 - } - - return 0 -} diff --git a/internal/collector/nginxplusreceiver/scraper_test.go b/internal/collector/nginxplusreceiver/scraper_test.go index 954a0ad8e..d55a5e160 100644 --- a/internal/collector/nginxplusreceiver/scraper_test.go +++ b/internal/collector/nginxplusreceiver/scraper_test.go @@ -9,6 +9,7 @@ import ( "path/filepath" "testing" + "github.com/nginx/agent/v3/internal/collector/nginxplusreceiver/record" "go.opentelemetry.io/collector/component/componenttest" "github.com/nginx/agent/v3/test/helpers" @@ -28,6 +29,15 @@ func TestScraper(t *testing.T) { assert.True(t, ok) cfg.APIDetails.URL = nginxPlusMock.URL + "/api" + tmpDir := t.TempDir() + _, cert := helpers.GenerateSelfSignedCert(t) + + caContents := helpers.Cert{Name: "ca.pem", Type: "CERTIFICATE", Contents: cert} + caFile := helpers.WriteCertFiles(t, tmpDir, caContents) + t.Logf("Ca File: %s", caFile) + + cfg.APIDetails.Ca = caFile + scraper := newNginxPlusScraper(receivertest.NewNopSettings(component.Type{}), cfg) err := scraper.Start(context.Background(), componenttest.NewNopHost()) require.NoError(t, err) @@ -38,35 +48,35 @@ func TestScraper(t *testing.T) { // To test the nginx.http.response.count metric calculation we need to set the previousLocationZoneResponses & // previousSeverZoneResponses then call scrape a second time as the first time it is called the previous responses // are set using the API - scraper.previousLocationZoneResponses = map[string]ResponseStatuses{ + scraper.locationZoneMetrics.PreviousLocationZoneResponses = map[string]record.ResponseStatuses{ "location_test": { - oneHundredStatusRange: 3, // 4 - twoHundredStatusRange: 29, // 2 - threeHundredStatusRange: 0, - fourHundredStatusRange: 1, // 2 - fiveHundredStatusRange: 0, + OneHundredStatusRange: 3, // 4 + TwoHundredStatusRange: 29, // 2 + ThreeHundredStatusRange: 0, + FourHundredStatusRange: 1, // 2 + FiveHundredStatusRange: 0, }, } - scraper.previousServerZoneResponses = map[string]ResponseStatuses{ + scraper.serverZoneMetrics.PreviousServerZoneResponses = map[string]record.ResponseStatuses{ "test": { - oneHundredStatusRange: 3, // 2 - twoHundredStatusRange: 0, // 29 - threeHundredStatusRange: 0, - fourHundredStatusRange: 1, // 1 - fiveHundredStatusRange: 0, + OneHundredStatusRange: 3, // 2 + TwoHundredStatusRange: 0, // 29 + ThreeHundredStatusRange: 0, + FourHundredStatusRange: 1, // 1 + FiveHundredStatusRange: 0, }, } - scraper.previousLocationZoneRequests = map[string]int64{ + scraper.locationZoneMetrics.PreviousLocationZoneRequests = map[string]int64{ "location_test": 30, // 5 } - scraper.previousServerZoneRequests = map[string]int64{ + scraper.serverZoneMetrics.PreviousServerZoneRequests = map[string]int64{ "test": 29, // 3 } - scraper.previousHTTPRequestsTotal = 3 + scraper.httpMetrics.PreviousHTTPRequestsTotal = 3 actualMetrics, err := scraper.Scrape(context.Background()) require.NoError(t, err)