Skip to content

Commit

Permalink
[receiver/k8scluster] Change k8s.daemonset metrics to use mdatagen (#…
Browse files Browse the repository at this point in the history
…24269)

**Description:** <Describe what has changed.>
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue.
Ex. Adding a feature - Explain what this achieves.-->
Change k8s.daemonset metrics to use mdatagen.

The migration has the following side effects, we add scope and schema to
metrics:
```
    schemaUrl: "https://opentelemetry.io/schemas/1.18.0"
...
        scope:
          name: otelcol/k8sclusterreceiver
          version: latest
```

**Link to tracking Issue:** #4367

---------

Co-authored-by: Curtis Robert <92119472+crobert-1@users.noreply.github.com>
  • Loading branch information
povilasv and crobert-1 committed Jul 20, 2023
1 parent 6285644 commit 0bbc5dd
Show file tree
Hide file tree
Showing 14 changed files with 995 additions and 105 deletions.
21 changes: 21 additions & 0 deletions .chloggen/k8s-cluster-receiver-daemonset-2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Use this changelog template to create an entry for release notes.
# If your change doesn't affect end users, such as a test fix or a tooling change,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.

# 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: Change k8s.daemonset metrics to use mdatagen


# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [10553]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func (dc *DataCollector) SyncMetrics(obj interface{}) {
case *appsv1.ReplicaSet:
md = replicaset.GetMetrics(dc.settings, o)
case *appsv1.DaemonSet:
md = ocsToMetrics(demonset.GetMetrics(o))
md = demonset.GetMetrics(dc.settings, o)
case *appsv1.StatefulSet:
md = statefulset.GetMetrics(dc.settings, o)
case *batchv1.Job:
Expand Down
95 changes: 19 additions & 76 deletions receiver/k8sclusterreceiver/internal/demonset/daemonsets.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,19 @@
package demonset // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/demonset"

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"
appsv1 "k8s.io/api/apps/v1"

"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/experimentalmetricmetadata"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/constants"
imetadataphase "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/demonset/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 daemonSetCurrentScheduledMetric = &metricspb.MetricDescriptor{
Name: "k8s.daemonset.current_scheduled_nodes",
Description: "Number of nodes that are running at least 1 daemon pod and are supposed to run the daemon pod",
Unit: "1",
Type: metricspb.MetricDescriptor_GAUGE_INT64,
}

var daemonSetDesiredScheduledMetric = &metricspb.MetricDescriptor{
Name: "k8s.daemonset.desired_scheduled_nodes",
Description: "Number of nodes that should be running the daemon pod (including nodes currently running the daemon pod)",
Unit: "1",
Type: metricspb.MetricDescriptor_GAUGE_INT64,
}

var daemonSetMisScheduledMetric = &metricspb.MetricDescriptor{
Name: "k8s.daemonset.misscheduled_nodes",
Description: "Number of nodes that are running the daemon pod, but are not supposed to run the daemon pod",
Unit: "1",
Type: metricspb.MetricDescriptor_GAUGE_INT64,
}

var daemonSetReadyMetric = &metricspb.MetricDescriptor{
Name: "k8s.daemonset.ready_nodes",
Description: "Number of nodes that should be running the daemon pod and have one or more of the daemon pod running and ready",
Unit: "1",
Type: metricspb.MetricDescriptor_GAUGE_INT64,
}

// Transform transforms the pod to remove the fields that we don't use to reduce RAM utilization.
// IMPORTANT: Make sure to update this function before using new daemonset fields.
func Transform(ds *appsv1.DaemonSet) *appsv1.DaemonSet {
Expand All @@ -58,51 +31,21 @@ func Transform(ds *appsv1.DaemonSet) *appsv1.DaemonSet {
}
}

func GetMetrics(ds *appsv1.DaemonSet) []*agentmetricspb.ExportMetricsServiceRequest {
metrics := []*metricspb.Metric{
{
MetricDescriptor: daemonSetCurrentScheduledMetric,
Timeseries: []*metricspb.TimeSeries{
utils.GetInt64TimeSeries(int64(ds.Status.CurrentNumberScheduled)),
},
},
{
MetricDescriptor: daemonSetDesiredScheduledMetric,
Timeseries: []*metricspb.TimeSeries{
utils.GetInt64TimeSeries(int64(ds.Status.DesiredNumberScheduled)),
},
},
{
MetricDescriptor: daemonSetMisScheduledMetric,
Timeseries: []*metricspb.TimeSeries{
utils.GetInt64TimeSeries(int64(ds.Status.NumberMisscheduled)),
},
},
{
MetricDescriptor: daemonSetReadyMetric,
Timeseries: []*metricspb.TimeSeries{
utils.GetInt64TimeSeries(int64(ds.Status.NumberReady)),
},
},
}
func GetMetrics(set receiver.CreateSettings, ds *appsv1.DaemonSet) pmetric.Metrics {
mbphase := imetadataphase.NewMetricsBuilder(imetadataphase.DefaultMetricsBuilderConfig(), set)
ts := pcommon.NewTimestampFromTime(time.Now())
mbphase.RecordK8sDaemonsetCurrentScheduledNodesDataPoint(ts, int64(ds.Status.CurrentNumberScheduled))
mbphase.RecordK8sDaemonsetDesiredScheduledNodesDataPoint(ts, int64(ds.Status.DesiredNumberScheduled))
mbphase.RecordK8sDaemonsetMisscheduledNodesDataPoint(ts, int64(ds.Status.NumberMisscheduled))
mbphase.RecordK8sDaemonsetReadyNodesDataPoint(ts, int64(ds.Status.NumberReady))

return []*agentmetricspb.ExportMetricsServiceRequest{
{
Resource: getResource(ds),
Metrics: metrics,
},
}
}
return mbphase.Emit(
imetadataphase.WithK8sNamespaceName(ds.Namespace),
imetadataphase.WithK8sDaemonsetName(ds.Name),
imetadataphase.WithK8sDaemonsetUID(string(ds.UID)),
imetadataphase.WithOpencensusResourcetype("k8s"),
)

func getResource(ds *appsv1.DaemonSet) *resourcepb.Resource {
return &resourcepb.Resource{
Type: constants.K8sType,
Labels: map[string]string{
conventions.AttributeK8SDaemonSetUID: string(ds.UID),
conventions.AttributeK8SDaemonSetName: ds.Name,
conventions.AttributeK8SNamespaceName: ds.Namespace,
},
}
}

func GetMetadata(ds *appsv1.DaemonSet) map[experimentalmetricmetadata.ResourceID]*metadata.KubernetesMetadata {
Expand Down
40 changes: 14 additions & 26 deletions receiver/k8sclusterreceiver/internal/demonset/daemonsets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,35 @@
package demonset

import (
"path/filepath"
"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/receiver/receivertest"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/constants"
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal/golden"
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest/pmetrictest"
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/k8sclusterreceiver/internal/testutils"
)

func TestDaemonsetMetrics(t *testing.T) {
ds := testutils.NewDaemonset("1")

actualResourceMetrics := GetMetrics(ds)

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{
"k8s.daemonset.uid": "test-daemonset-1-uid",
"k8s.daemonset.name": "test-daemonset-1",
"k8s.namespace.name": "test-namespace",
},
m := GetMetrics(receivertest.NewNopCreateSettings(), ds)
expected, err := golden.ReadMetrics(filepath.Join("testdata", "expected.yaml"))
require.NoError(t, err)
require.NoError(t, pmetrictest.CompareMetrics(expected, m,
pmetrictest.IgnoreTimestamp(),
pmetrictest.IgnoreStartTimestamp(),
pmetrictest.IgnoreResourceMetricsOrder(),
pmetrictest.IgnoreMetricsOrder(),
pmetrictest.IgnoreScopeMetricsOrder(),
),
)

testutils.AssertMetricsInt(t, rm.Metrics[0], "k8s.daemonset.current_scheduled_nodes",
metricspb.MetricDescriptor_GAUGE_INT64, 3)

testutils.AssertMetricsInt(t, rm.Metrics[1], "k8s.daemonset.desired_scheduled_nodes",
metricspb.MetricDescriptor_GAUGE_INT64, 5)

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

testutils.AssertMetricsInt(t, rm.Metrics[3], "k8s.daemonset.ready_nodes",
metricspb.MetricDescriptor_GAUGE_INT64, 2)
}

func TestTransform(t *testing.T) {
Expand Down
6 changes: 6 additions & 0 deletions receiver/k8sclusterreceiver/internal/demonset/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

//go:generate mdatagen metadata.yaml

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

# k8s/daemonset

**Parent Component:** k8s_cluster

## 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.daemonset.current_scheduled_nodes
Number of nodes that are running at least 1 daemon pod and are supposed to run the daemon pod
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Int |
### k8s.daemonset.desired_scheduled_nodes
Number of nodes that should be running the daemon pod (including nodes currently running the daemon pod)
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Int |
### k8s.daemonset.misscheduled_nodes
Number of nodes that are running the daemon pod, but are not supposed to run the daemon pod
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Int |
### k8s.daemonset.ready_nodes
Number of nodes that should be running the daemon pod and have one or more of the daemon pod running and ready
| Unit | Metric Type | Value Type |
| ---- | ----------- | ---------- |
| 1 | Gauge | Int |
## Resource Attributes
| Name | Description | Values | Enabled |
| ---- | ----------- | ------ | ------- |
| k8s.daemonset.name | The k8s daemonset name. | Any Str | true |
| k8s.daemonset.uid | The k8s daemonset uid. | Any Str | true |
| k8s.namespace.name | The k8s namespace name. | Any Str | true |
| opencensus.resourcetype | The OpenCensus resource type. | Any Str | true |

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 0bbc5dd

Please sign in to comment.