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

[Metricbeat][Kubernetes] Extend state_node with more conditions #23905

Merged
merged 3 commits into from
Feb 16, 2021
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- kubernetes.container.cpu.limit.cores and kubernetes.container.cpu.requests.cores are now floats. {issue}11975[11975]
- Change types of numeric metrics from Kubelet summary api to double so as to cover big numbers. {pull}23335[23335]
- Add container.image.name and containe.name ECS fields for state_container. {pull}23802[23802]
- Add support for the MemoryPressure, DiskPressure, OutOfDisk and PIDPressure status conditions in state_node. {pull}[23905]

*Packetbeat*

Expand Down
40 changes: 40 additions & 0 deletions metricbeat/docs/fields.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -29807,6 +29807,46 @@ type: keyword
Node unschedulable status


type: boolean

--

*`kubernetes.node.status.memory_pressure`*::
+
--
Node MemoryPressure status


type: boolean

--

*`kubernetes.node.status.disk_pressure`*::
+
--
Node DiskPressure status


type: boolean

--

*`kubernetes.node.status.out_of_disk`*::
+
--
Node OutOfDisk status


type: boolean

--

*`kubernetes.node.status.pid_pressure`*::
+
--
Node PIDPressure status


type: boolean

--
Expand Down
29 changes: 17 additions & 12 deletions metricbeat/helper/prometheus/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@ type MetricOption interface {
Process(field string, value interface{}, labels common.MapStr) (string, interface{}, common.MapStr)
}

// OpFilter only processes metrics matching the given filter
func OpFilter(filter map[string]string) MetricOption {
return opFilter{
labels: filter,
// OpFilterMap only processes metrics matching the given filter
func OpFilterMap(label string, filterMap map[string]string) MetricOption {
return opFilterMap{
label: label,
filterMap: filterMap,
}
}

Expand Down Expand Up @@ -331,18 +332,22 @@ func (m *infoMetric) GetField() string {
return ""
}

type opFilter struct {
labels map[string]string
type opFilterMap struct {
label string
filterMap map[string]string
}

// Process will return nil if labels don't match the filter
func (o opFilter) Process(field string, value interface{}, labels common.MapStr) (string, interface{}, common.MapStr) {
for k, v := range o.labels {
if labels[k] != v {
return "", nil, nil
// Called by the Prometheus helper to apply extra options on retrieved metrics
// Check whether the value of the specified label is allowed and, if yes, return the metric via the specified mapped field
// Else, if the specified label does not match the filter, return nil
// This is useful in cases where multiple Metricbeat fields need to be defined per Prometheus metric, based on label values
func (o opFilterMap) Process(field string, value interface{}, labels common.MapStr) (string, interface{}, common.MapStr) {
for k, v := range o.filterMap {
if labels[o.label] == k {
return fmt.Sprintf("%v.%v", field, v), value, labels
}
}
return field, value, labels
return "", nil, nil
}

type opLowercaseValue struct{}
Expand Down
33 changes: 30 additions & 3 deletions metricbeat/helper/prometheus/prometheus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,36 @@ func TestPrometheus(t *testing.T) {
msg: "Label metrics, filter",
mapping: &MetricsMapping{
Metrics: map[string]MetricMap{
"first_metric": LabelMetric("first.metric", "label4", OpLowercaseValue(), OpFilter(map[string]string{
"foo": "filtered",
})),
"first_metric": LabelMetric("first.metric", "label4", OpFilterMap(
"label1",
map[string]string{"value1": "foo"},
)),
},
Labels: map[string]LabelMap{
"label1": Label("labels.label1"),
},
},
expected: []common.MapStr{
common.MapStr{
"first": common.MapStr{
"metric": common.MapStr{
"foo": "FOO",
},
},
"labels": common.MapStr{
"label1": "value1",
},
},
},
},
{
msg: "Label metrics, filter",
mapping: &MetricsMapping{
Metrics: map[string]MetricMap{
"first_metric": LabelMetric("first.metric", "label4", OpLowercaseValue(), OpFilterMap(
"foo",
map[string]string{"Filtered": "filtered"},
)),
},
Labels: map[string]LabelMap{
"label1": Label("labels.label1"),
Expand Down
2 changes: 1 addition & 1 deletion metricbeat/module/kubernetes/fields.go

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

16 changes: 16 additions & 0 deletions metricbeat/module/kubernetes/state_node/_meta/fields.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,22 @@
type: boolean
description: >
Node unschedulable status
- name: memory_pressure
type: boolean
description: >
Node MemoryPressure status
- name: disk_pressure
type: boolean
description: >
Node DiskPressure status
- name: out_of_disk
type: boolean
description: >
Node OutOfDisk status
- name: pid_pressure
type: boolean
description: >
Node PIDPressure status
- name: cpu
type: group
fields:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
}
},
"status": {
"disk_pressure": "false",
"memory_pressure": "false",
"out_of_disk": "false",
"ready": "true",
"unschedulable": false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
}
},
"status": {
"disk_pressure": "false",
"memory_pressure": "false",
"pid_pressure": "false",
"ready": "true",
jsoriano marked this conversation as resolved.
Show resolved Hide resolved
"unschedulable": false
}
Expand Down
14 changes: 9 additions & 5 deletions metricbeat/module/kubernetes/state_node/state_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,16 @@ var (
"kube_node_status_allocatable_cpu_cores": p.Metric("cpu.allocatable.cores"),
"kube_node_spec_unschedulable": p.BooleanMetric("status.unschedulable"),
"kube_node_status_ready": p.LabelMetric("status.ready", "condition"),
"kube_node_status_condition": p.LabelMetric("status.ready", "status",
p.OpFilter(map[string]string{
"condition": "Ready",
})),
"kube_node_status_condition": p.LabelMetric("status", "status", p.OpFilterMap(
"condition", map[string]string{
"Ready": "ready",
"MemoryPressure": "memory_pressure",
"DiskPressure": "disk_pressure",
"OutOfDisk": "out_of_disk",
"PIDPressure": "pid_pressure",
},
)),
},

Labels: map[string]p.LabelMap{
"node": p.KeyLabel("name"),
},
Expand Down