github.com/cilium/cilium@v1.16.2/pkg/hubble/metrics/port-distribution/handler.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Hubble
     3  
     4  package portdistribution
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"github.com/prometheus/client_golang/prometheus"
    11  
    12  	flowpb "github.com/cilium/cilium/api/v1/flow"
    13  	"github.com/cilium/cilium/pkg/hubble/metrics/api"
    14  )
    15  
    16  type portDistributionHandler struct {
    17  	portDistribution *prometheus.CounterVec
    18  	context          *api.ContextOptions
    19  }
    20  
    21  func (h *portDistributionHandler) Init(registry *prometheus.Registry, options api.Options) error {
    22  	c, err := api.ParseContextOptions(options)
    23  	if err != nil {
    24  		return err
    25  	}
    26  	h.context = c
    27  
    28  	labels := []string{"protocol", "port"}
    29  	labels = append(labels, h.context.GetLabelNames()...)
    30  
    31  	h.portDistribution = prometheus.NewCounterVec(prometheus.CounterOpts{
    32  		Namespace: api.DefaultPrometheusNamespace,
    33  		Name:      "port_distribution_total",
    34  		Help:      "Numbers of packets distributed by destination port",
    35  	}, labels)
    36  
    37  	registry.MustRegister(h.portDistribution)
    38  	return nil
    39  }
    40  
    41  func (h *portDistributionHandler) Status() string {
    42  	return h.context.Status()
    43  }
    44  
    45  func (h *portDistributionHandler) Context() *api.ContextOptions {
    46  	return h.context
    47  }
    48  
    49  func (h *portDistributionHandler) ListMetricVec() []*prometheus.MetricVec {
    50  	return []*prometheus.MetricVec{h.portDistribution.MetricVec}
    51  }
    52  
    53  func (h *portDistributionHandler) ProcessFlow(ctx context.Context, flow *flowpb.Flow) error {
    54  	// if we are not certain if a flow is a reply (i.e. flow.GetIsReply() == nil)
    55  	// we do not want to consider its destination port for the metric
    56  	skipReply := flow.GetIsReply() == nil || flow.GetIsReply().GetValue()
    57  	if (flow.GetVerdict() != flowpb.Verdict_FORWARDED && flow.GetVerdict() != flowpb.Verdict_REDIRECTED) ||
    58  		flow.GetL4() == nil || skipReply {
    59  		return nil
    60  	}
    61  
    62  	labelValues, err := h.context.GetLabelValues(flow)
    63  	if err != nil {
    64  		return err
    65  	}
    66  
    67  	if tcp := flow.GetL4().GetTCP(); tcp != nil {
    68  		labels := append([]string{"TCP", fmt.Sprintf("%d", tcp.DestinationPort)}, labelValues...)
    69  		h.portDistribution.WithLabelValues(labels...).Inc()
    70  	}
    71  
    72  	if udp := flow.GetL4().GetUDP(); udp != nil {
    73  		labels := append([]string{"UDP", fmt.Sprintf("%d", udp.DestinationPort)}, labelValues...)
    74  		h.portDistribution.WithLabelValues(labels...).Inc()
    75  	}
    76  
    77  	if sctp := flow.GetL4().GetSCTP(); sctp != nil {
    78  		labels := append([]string{"SCTP", fmt.Sprintf("%d", sctp.DestinationPort)}, labelValues...)
    79  		h.portDistribution.WithLabelValues(labels...).Inc()
    80  	}
    81  
    82  	if flow.GetL4().GetICMPv4() != nil {
    83  		labels := append([]string{"ICMPv4", "0"}, labelValues...)
    84  		h.portDistribution.WithLabelValues(labels...).Inc()
    85  	}
    86  
    87  	if flow.GetL4().GetICMPv6() != nil {
    88  		labels := append([]string{"ICMPv6", "0"}, labelValues...)
    89  		h.portDistribution.WithLabelValues(labels...).Inc()
    90  	}
    91  	return nil
    92  }