Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[k8sclusterreceiver] switch k8s.hpa metrics to use pdata #18250

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .chloggen/switchk8shpa.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: k8sclusterreceiver

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Switch k8s.hpa metrics to use pdata.

# One or more tracking issues related to the change
issues: [18250]
19 changes: 10 additions & 9 deletions receiver/k8sclusterreceiver/internal/collection/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
agentmetricspb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/metrics/v1"
quotav1 "github.com/openshift/api/quota/v1"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/receiver"
"go.uber.org/zap"
appsv1 "k8s.io/api/apps/v1"
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
Expand Down Expand Up @@ -58,17 +59,17 @@ import (
// an interface to interact with refactored code from SignalFx Agent which is
// confined to the collection package.
type DataCollector struct {
logger *zap.Logger
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you share a little context around why we're moving from using the zap logger here to the CreateSettings object? I'm wondering how this change is connected with using the pdata format for metrics instead of opencensus.

settings receiver.CreateSettings
metricsStore *metricsStore
metadataStore *metadata.Store
nodeConditionsToReport []string
allocatableTypesToReport []string
}

// NewDataCollector returns a DataCollector.
func NewDataCollector(logger *zap.Logger, nodeConditionsToReport, allocatableTypesToReport []string) *DataCollector {
func NewDataCollector(set receiver.CreateSettings, nodeConditionsToReport, allocatableTypesToReport []string) *DataCollector {
return &DataCollector{
logger: logger,
settings: set,
metricsStore: &metricsStore{
metricsCache: make(map[types.UID]pmetric.Metrics),
},
Expand All @@ -85,7 +86,7 @@ func (dc *DataCollector) SetupMetadataStore(gvk schema.GroupVersionKind, store c

func (dc *DataCollector) RemoveFromMetricsStore(obj interface{}) {
if err := dc.metricsStore.remove(obj.(runtime.Object)); err != nil {
dc.logger.Error(
dc.settings.TelemetrySettings.Logger.Error(
"failed to remove from metric cache",
zap.String("obj", reflect.TypeOf(obj).String()),
zap.Error(err),
Expand All @@ -95,7 +96,7 @@ func (dc *DataCollector) RemoveFromMetricsStore(obj interface{}) {

func (dc *DataCollector) UpdateMetricsStore(obj interface{}, md pmetric.Metrics) {
if err := dc.metricsStore.update(obj.(runtime.Object), md); err != nil {
dc.logger.Error(
dc.settings.TelemetrySettings.Logger.Error(
"failed to update metric cache",
zap.String("obj", reflect.TypeOf(obj).String()),
zap.Error(err),
Expand All @@ -113,9 +114,9 @@ func (dc *DataCollector) SyncMetrics(obj interface{}) {

switch o := obj.(type) {
case *corev1.Pod:
md = ocsToMetrics(pod.GetMetrics(o, dc.logger))
md = ocsToMetrics(pod.GetMetrics(o, dc.settings.TelemetrySettings.Logger))
case *corev1.Node:
md = ocsToMetrics(node.GetMetrics(o, dc.nodeConditionsToReport, dc.allocatableTypesToReport, dc.logger))
md = ocsToMetrics(node.GetMetrics(o, dc.nodeConditionsToReport, dc.allocatableTypesToReport, dc.settings.TelemetrySettings.Logger))
case *corev1.Namespace:
md = ocsToMetrics(namespace.GetMetrics(o))
case *corev1.ReplicationController:
Expand All @@ -137,7 +138,7 @@ func (dc *DataCollector) SyncMetrics(obj interface{}) {
case *batchv1beta1.CronJob:
md = ocsToMetrics(cronjob.GetMetricsBeta(o))
case *autoscalingv2beta2.HorizontalPodAutoscaler:
md = ocsToMetrics(hpa.GetMetrics(o))
md = hpa.GetMetrics(dc.settings, o)
case *quotav1.ClusterResourceQuota:
md = ocsToMetrics(clusterresourcequota.GetMetrics(o))
default:
Expand All @@ -156,7 +157,7 @@ func (dc *DataCollector) SyncMetadata(obj interface{}) map[experimentalmetricmet
km := map[experimentalmetricmetadata.ResourceID]*metadata.KubernetesMetadata{}
switch o := obj.(type) {
case *corev1.Pod:
km = pod.GetMetadata(o, dc.metadataStore, dc.logger)
km = pod.GetMetadata(o, dc.metadataStore, dc.settings.TelemetrySettings.Logger)
case *corev1.Node:
km = node.GetMetadata(o)
case *corev1.ReplicationController:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"testing"

"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/receiver/receivertest"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"
Expand Down Expand Up @@ -274,10 +275,11 @@ func TestDataCollectorSyncMetadata(t *testing.T) {

for _, tt := range tests {
observedLogger, _ := observer.New(zapcore.WarnLevel)
logger := zap.New(observedLogger)
set := receivertest.NewNopCreateSettings()
set.TelemetrySettings.Logger = zap.New(observedLogger)
t.Run(tt.name, func(t *testing.T) {
dc := &DataCollector{
logger: logger,
settings: set,
metadataStore: tt.metadataStore,
nodeConditionsToReport: []string{},
}
Expand Down
2 changes: 0 additions & 2 deletions receiver/k8sclusterreceiver/internal/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,11 @@ const (
// Resource labels keys for UID.
K8sKeyNamespaceUID = "k8s.namespace.uid"
K8sKeyReplicationControllerUID = "k8s.replicationcontroller.uid"
K8sKeyHPAUID = "k8s.hpa.uid"
K8sKeyResourceQuotaUID = "k8s.resourcequota.uid"
K8sKeyClusterResourceQuotaUID = "openshift.clusterquota.uid"

// Resource labels keys for Name.
K8sKeyReplicationControllerName = "k8s.replicationcontroller.name"
K8sKeyHPAName = "k8s.hpa.name"
K8sKeyResourceQuotaName = "k8s.resourcequota.name"
K8sKeyClusterResourceQuotaName = "openshift.clusterquota.name"

Expand Down
20 changes: 20 additions & 0 deletions receiver/k8sclusterreceiver/internal/hpa/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build !windows
// +build !windows

//go:generate mdatagen metadata.yaml

package hpa // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/hpa"
53 changes: 53 additions & 0 deletions receiver/k8sclusterreceiver/internal/hpa/documentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
[comment]: <> (Code generated by mdatagen. DO NOT EDIT.)

# k8s/hpa

## Default Metrics

The following metrics are emitted by default. Each of them can be disabled by applying the following configuration:

```yaml
metrics:
<metric_name>:
enabled: false
```

### k8s.hpa.current_replicas

Current number of pod replicas managed by this autoscaler.

| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Int |

### k8s.hpa.desired_replicas

Desired number of pod replicas managed by this autoscaler.

| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Int |

### k8s.hpa.max_replicas

Maximum number of replicas to which the autoscaler can scale up.

| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Int |

### k8s.hpa.min_replicas

Minimum number of replicas to which the autoscaler can scale up.

| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Int |

## Resource Attributes

| Name | Description | Values | Enabled |
| ---- | ----------- | ------ | ------- |
| k8s.hpa.name | The k8s hpa name. | Any Str | true |
| k8s.hpa.uid | The k8s hpa uid. | Any Str | true |
| k8s.namespace.name | The name of the namespace that the pod is running in. | Any Str | true |
92 changes: 14 additions & 78 deletions receiver/k8sclusterreceiver/internal/hpa/hpa.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,91 +15,27 @@
package hpa // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/hpa"

import (
agentmetricspb "github.com/census-instrumentation/opencensus-proto/gen-go/agent/metrics/v1"
metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1"
resourcepb "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1"
conventions "go.opentelemetry.io/collector/semconv/v1.6.1"
"time"

"go.opentelemetry.io/collector/pdata/pcommon"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/receiver"
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"

"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/experimentalmetricmetadata"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/constants"
imetadata "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/hpa/internal/metadata"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/metadata"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/utils"
)

var hpaMaxReplicasMetric = &metricspb.MetricDescriptor{
Name: "k8s.hpa.max_replicas",
Description: "Maximum number of replicas to which the autoscaler can scale up",
Unit: "1",
Type: metricspb.MetricDescriptor_GAUGE_INT64,
}

var hpaMinReplicasMetric = &metricspb.MetricDescriptor{
Name: "k8s.hpa.min_replicas",
Description: "Minimum number of replicas to which the autoscaler can scale down",
Unit: "1",
Type: metricspb.MetricDescriptor_GAUGE_INT64,
}

var hpaCurrentReplicasMetric = &metricspb.MetricDescriptor{
Name: "k8s.hpa.current_replicas",
Description: "Current number of pod replicas managed by this autoscaler",
Unit: "1",
Type: metricspb.MetricDescriptor_GAUGE_INT64,
}

var hpaDesiredReplicasMetric = &metricspb.MetricDescriptor{
Name: "k8s.hpa.desired_replicas",
Description: "Desired number of pod replicas managed by this autoscaler",
Unit: "1",
Type: metricspb.MetricDescriptor_GAUGE_INT64,
}

func GetMetrics(hpa *autoscalingv2beta2.HorizontalPodAutoscaler) []*agentmetricspb.ExportMetricsServiceRequest {
metrics := []*metricspb.Metric{
{
MetricDescriptor: hpaMaxReplicasMetric,
Timeseries: []*metricspb.TimeSeries{
utils.GetInt64TimeSeries(int64(hpa.Spec.MaxReplicas)),
},
},
{
MetricDescriptor: hpaMinReplicasMetric,
Timeseries: []*metricspb.TimeSeries{
utils.GetInt64TimeSeries(int64(*hpa.Spec.MinReplicas)),
},
},
{
MetricDescriptor: hpaCurrentReplicasMetric,
Timeseries: []*metricspb.TimeSeries{
utils.GetInt64TimeSeries(int64(hpa.Status.CurrentReplicas)),
},
},
{
MetricDescriptor: hpaDesiredReplicasMetric,
Timeseries: []*metricspb.TimeSeries{
utils.GetInt64TimeSeries(int64(hpa.Status.DesiredReplicas)),
},
},
}
func GetMetrics(set receiver.CreateSettings, hpa *autoscalingv2beta2.HorizontalPodAutoscaler) pmetric.Metrics {
mb := imetadata.NewMetricsBuilder(imetadata.DefaultMetricsSettings(), set)

return []*agentmetricspb.ExportMetricsServiceRequest{
{
Resource: getResourceForHPA(hpa),
Metrics: metrics,
},
}
}

func getResourceForHPA(hpa *autoscalingv2beta2.HorizontalPodAutoscaler) *resourcepb.Resource {
return &resourcepb.Resource{
Type: constants.K8sType,
Labels: map[string]string{
constants.K8sKeyHPAUID: string(hpa.UID),
constants.K8sKeyHPAName: hpa.Name,
conventions.AttributeK8SNamespaceName: hpa.Namespace,
},
}
ts := pcommon.NewTimestampFromTime(time.Now())
mb.RecordK8sHpaMaxReplicasDataPoint(ts, int64(hpa.Spec.MaxReplicas))
mb.RecordK8sHpaMinReplicasDataPoint(ts, int64(*hpa.Spec.MinReplicas))
mb.RecordK8sHpaCurrentReplicasDataPoint(ts, int64(hpa.Status.CurrentReplicas))
mb.RecordK8sHpaDesiredReplicasDataPoint(ts, int64(hpa.Status.DesiredReplicas))
return mb.Emit(imetadata.WithK8sHpaUID(string(hpa.UID)), imetadata.WithK8sHpaName(hpa.Name), imetadata.WithK8sNamespaceName(hpa.Namespace))
}

func GetMetadata(hpa *autoscalingv2beta2.HorizontalPodAutoscaler) map[experimentalmetricmetadata.ResourceID]*metadata.KubernetesMetadata {
Expand Down
42 changes: 20 additions & 22 deletions receiver/k8sclusterreceiver/internal/hpa/hpa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,39 +17,37 @@ package hpa
import (
"testing"

metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/pdata/pmetric"
"go.opentelemetry.io/collector/receiver/receivertest"

"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/constants"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/testutils"
)

func TestHPAMetrics(t *testing.T) {
hpa := testutils.NewHPA("1")

actualResourceMetrics := GetMetrics(hpa)
md := GetMetrics(receivertest.NewNopCreateSettings(), hpa)

require.Equal(t, 1, len(actualResourceMetrics))
require.Equal(t, 4, len(actualResourceMetrics[0].Metrics))

rm := actualResourceMetrics[0]
testutils.AssertResource(t, rm.Resource, constants.K8sType,
map[string]string{
require.Equal(t, 1, md.ResourceMetrics().Len())
rm := md.ResourceMetrics().At(0)
assert.Equal(t,
map[string]any{
"k8s.hpa.uid": "test-hpa-1-uid",
"k8s.hpa.name": "test-hpa-1",
"k8s.namespace.name": "test-namespace",
},
)

testutils.AssertMetricsInt(t, rm.Metrics[0], "k8s.hpa.max_replicas",
metricspb.MetricDescriptor_GAUGE_INT64, 10)

testutils.AssertMetricsInt(t, rm.Metrics[1], "k8s.hpa.min_replicas",
metricspb.MetricDescriptor_GAUGE_INT64, 2)

testutils.AssertMetricsInt(t, rm.Metrics[2], "k8s.hpa.current_replicas",
metricspb.MetricDescriptor_GAUGE_INT64, 5)

testutils.AssertMetricsInt(t, rm.Metrics[3], "k8s.hpa.desired_replicas",
metricspb.MetricDescriptor_GAUGE_INT64, 7)
rm.Resource().Attributes().AsRaw())

require.Equal(t, 1, rm.ScopeMetrics().Len())
sms := rm.ScopeMetrics().At(0)
require.Equal(t, 4, sms.Metrics().Len())
sms.Metrics().Sort(func(a, b pmetric.Metric) bool {
return a.Name() < b.Name()
})
testutils.AssertMetricInt(t, sms.Metrics().At(0), "k8s.hpa.current_replicas", pmetric.MetricTypeGauge, 5)
testutils.AssertMetricInt(t, sms.Metrics().At(1), "k8s.hpa.desired_replicas", pmetric.MetricTypeGauge, 7)
testutils.AssertMetricInt(t, sms.Metrics().At(2), "k8s.hpa.max_replicas", pmetric.MetricTypeGauge, 10)
testutils.AssertMetricInt(t, sms.Metrics().At(3), "k8s.hpa.min_replicas", pmetric.MetricTypeGauge, 2)
}
Loading