Skip to content

Commit 283f050

Browse files
committed
feat(service): add kube_service_ports metric
Signed-off-by: nahuel11500 <[email protected]>
1 parent 905d50c commit 283f050

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

docs/metrics/service/service-metrics.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@
1010
| kube_service_spec_external_ip | Gauge | Service external ips. One series for each ip | | `service`=&lt;service-name&gt; <br> `namespace`=&lt;service-namespace&gt; <br> `uid`=&lt;service-uid&gt; <br> `external_ip`=&lt;external-ip&gt; | STABLE |
1111
| kube_service_status_load_balancer_ingress | Gauge | Service load balancer ingress status | | `service`=&lt;service-name&gt; <br> `namespace`=&lt;service-namespace&gt; <br> `uid`=&lt;service-uid&gt; <br> `ip`=&lt;load-balancer-ingress-ip&gt; <br> `hostname`=&lt;load-balancer-ingress-hostname&gt; | STABLE |
1212
| kube_service_deletion_timestamp | Gauge | Unix deletion timestamp | seconds | `service`=&lt;service-name&gt; <br> `namespace`=&lt;service-namespace&gt; <br> `uid`=&lt;service-uid&gt; | EXPERIMENTAL |
13+
| kube_service_ports | Gauge | Metric providing details about the ports exposed by services. | | `service`=&lt;service-name&gt; <br> `namespace`=&lt;service-namespace&gt; <br> `uid`=&lt;service-uid&gt; <br> `port_name`=&lt;service-port-name&gt; <br> `port_protocol`=&lt;service-port-protocol&gt; <br> `port_number`=&lt;service-port-number&gt; <br> `port_target`=&lt;service-port-target&gt; <br> `port_app_protocol`=&lt;service-port-appProtocol&gt; <br> `port_node_number`=&lt;service-node-port-number&gt; | EXPERIMENTAL |

internal/store/service.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package store
1818

1919
import (
2020
"context"
21+
"strconv"
2122

2223
v1 "k8s.io/api/core/v1"
2324
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -184,6 +185,49 @@ func serviceMetricFamilies(allowAnnotationsList, allowLabelsList []string) []gen
184185
}
185186
}),
186187
),
188+
*generator.NewFamilyGeneratorWithStability(
189+
"kube_service_ports",
190+
"Metric providing details about the ports exposed by services.",
191+
metric.Gauge,
192+
basemetrics.ALPHA,
193+
"",
194+
wrapSvcFunc(func(e *v1.Service) *metric.Family {
195+
ms := []*metric.Metric{}
196+
labelKeys := []string{"port_protocol", "port_number", "port_name", "port_target", "port_node_number", "port_app_protocol"}
197+
for _, port := range e.Spec.Ports {
198+
appProtocol := ""
199+
if port.AppProtocol != nil {
200+
appProtocol = *port.AppProtocol
201+
}
202+
var labelValues []string
203+
portNumber := strconv.FormatInt(int64(port.Port), 10)
204+
targetPort := port.TargetPort.String()
205+
nodePort := ""
206+
207+
if port.NodePort != 0 {
208+
nodePort = strconv.FormatInt(int64(port.NodePort), 10)
209+
}
210+
211+
labelValues = []string{
212+
string(port.Protocol),
213+
portNumber,
214+
port.Name,
215+
targetPort,
216+
nodePort,
217+
appProtocol,
218+
}
219+
220+
ms = append(ms, &metric.Metric{
221+
LabelValues: labelValues,
222+
LabelKeys: labelKeys,
223+
Value: 1,
224+
})
225+
}
226+
return &metric.Family{
227+
Metrics: ms,
228+
}
229+
}),
230+
),
187231
*generator.NewFamilyGeneratorWithStability(
188232
"kube_service_deletion_timestamp",
189233
"Unix deletion timestamp",

internal/store/service_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
v1 "k8s.io/api/core/v1"
2424
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25+
"k8s.io/apimachinery/pkg/util/intstr"
2526

2627
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
2728
)
@@ -44,6 +45,8 @@ func TestServiceStore(t *testing.T) {
4445
# TYPE kube_service_spec_external_ip gauge
4546
# HELP kube_service_status_load_balancer_ingress [STABLE] Service load balancer ingress status
4647
# TYPE kube_service_status_load_balancer_ingress gauge
48+
# HELP kube_service_ports Metric providing details about the ports exposed by services.
49+
# TYPE kube_service_ports gauge
4750
# HELP kube_service_deletion_timestamp Unix deletion timestamp
4851
# TYPE kube_service_deletion_timestamp gauge
4952
`
@@ -70,11 +73,13 @@ func TestServiceStore(t *testing.T) {
7073
# HELP kube_service_info [STABLE] Information about service.
7174
# HELP kube_service_labels [STABLE] Kubernetes labels converted to Prometheus labels.
7275
# HELP kube_service_spec_type [STABLE] Type about service.
76+
# HELP kube_service_ports Metric providing details about the ports exposed by services.
7377
# TYPE kube_service_annotations gauge
7478
# TYPE kube_service_created gauge
7579
# TYPE kube_service_info gauge
7680
# TYPE kube_service_labels gauge
7781
# TYPE kube_service_spec_type gauge
82+
# TYPE kube_service_ports gauge
7883
kube_service_created{namespace="default",service="test-service1",uid="uid1"} 1.5e+09
7984
kube_service_info{cluster_ip="1.2.3.4",external_name="",external_traffic_policy="",load_balancer_ip="",namespace="default",service="test-service1",uid="uid1"} 1
8085
kube_service_spec_type{namespace="default",service="test-service1",type="ClusterIP",uid="uid1"} 1
@@ -85,6 +90,7 @@ func TestServiceStore(t *testing.T) {
8590
"kube_service_info",
8691
"kube_service_labels",
8792
"kube_service_spec_type",
93+
"kube_service_ports",
8894
},
8995
},
9096
{
@@ -261,6 +267,35 @@ func TestServiceStore(t *testing.T) {
261267
kube_service_spec_type{namespace="default",service="test-service8",uid="uid8",type="LoadBalancer"} 1
262268
`,
263269
},
270+
271+
{
272+
Obj: &v1.Service{
273+
ObjectMeta: metav1.ObjectMeta{
274+
Name: "test-service9",
275+
CreationTimestamp: metav1.Time{Time: time.Unix(1500000000, 0)},
276+
Namespace: "default",
277+
UID: "uid9",
278+
Labels: map[string]string{
279+
"app": "example9",
280+
},
281+
},
282+
Spec: v1.ServiceSpec{
283+
ClusterIP: "1.2.3.14",
284+
LoadBalancerIP: "1.2.3.15",
285+
Type: v1.ServiceTypeLoadBalancer,
286+
ExternalTrafficPolicy: "Local",
287+
Ports: []v1.ServicePort{
288+
{Port: 80, Protocol: v1.ProtocolTCP, TargetPort: intstr.FromInt(8080), Name: "http", NodePort: 65000, AppProtocol: func(s string) *string { return &s }("grpc")},
289+
},
290+
},
291+
},
292+
Want: metadata + `
293+
kube_service_created{namespace="default",service="test-service9",uid="uid9"} 1.5e+09
294+
kube_service_info{cluster_ip="1.2.3.14",external_name="",external_traffic_policy="Local",load_balancer_ip="1.2.3.15",namespace="default",service="test-service9",uid="uid9"} 1
295+
kube_service_spec_type{namespace="default",service="test-service9",uid="uid9",type="LoadBalancer"} 1
296+
kube_service_ports{namespace="default",port_app_protocol="grpc",port_name="http",port_node_number="65000",port_number="80",port_protocol="TCP",port_target="8080",service="test-service9",uid="uid9"} 1
297+
`,
298+
},
264299
{
265300
Obj: &v1.Service{
266301
ObjectMeta: metav1.ObjectMeta{

0 commit comments

Comments
 (0)