1// +build !providerless
2
3/*
4Copyright 2018 The Kubernetes Authors.
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17*/
18
19package metrics
20
21import (
22	"strings"
23	"time"
24
25	"k8s.io/component-base/metrics"
26	"k8s.io/component-base/metrics/legacyregistry"
27)
28
29const (
30	azureMetricsNamespace = "cloudprovider_azure"
31)
32
33var (
34	metricLabels = []string{
35		"request",         // API function that is being invoked
36		"resource_group",  // Resource group of the resource being monitored
37		"subscription_id", // Subscription ID of the resource being monitored
38		"source",          // Operation source(optional)
39	}
40
41	apiMetrics       = registerAPIMetrics(metricLabels...)
42	operationMetrics = registerOperationMetrics(metricLabels...)
43)
44
45// apiCallMetrics is the metrics measuring the performance of a single API call
46// e.g., GET, POST ...
47type apiCallMetrics struct {
48	latency          *metrics.HistogramVec
49	errors           *metrics.CounterVec
50	rateLimitedCount *metrics.CounterVec
51	throttledCount   *metrics.CounterVec
52}
53
54// operationCallMetrics is the metrics measuring the performance of a whole operation
55// e.g., the create / update / delete process of a loadbalancer or route.
56type operationCallMetrics struct {
57	operationLatency      *metrics.HistogramVec
58	operationFailureCount *metrics.CounterVec
59}
60
61// MetricContext indicates the context for Azure client metrics.
62type MetricContext struct {
63	start      time.Time
64	attributes []string
65}
66
67// NewMetricContext creates a new MetricContext.
68func NewMetricContext(prefix, request, resourceGroup, subscriptionID, source string) *MetricContext {
69	return &MetricContext{
70		start:      time.Now(),
71		attributes: []string{prefix + "_" + request, strings.ToLower(resourceGroup), subscriptionID, source},
72	}
73}
74
75// RateLimitedCount records the metrics for rate limited request count.
76func (mc *MetricContext) RateLimitedCount() {
77	apiMetrics.rateLimitedCount.WithLabelValues(mc.attributes...).Inc()
78}
79
80// ThrottledCount records the metrics for throttled request count.
81func (mc *MetricContext) ThrottledCount() {
82	apiMetrics.throttledCount.WithLabelValues(mc.attributes...).Inc()
83}
84
85// Observe observes the request latency and failed requests.
86func (mc *MetricContext) Observe(err error) error {
87	apiMetrics.latency.WithLabelValues(mc.attributes...).Observe(
88		time.Since(mc.start).Seconds())
89	if err != nil {
90		apiMetrics.errors.WithLabelValues(mc.attributes...).Inc()
91	}
92
93	return err
94}
95
96// ObserveOperationWithResult observes the request latency and failed requests of an operation.
97func (mc *MetricContext) ObserveOperationWithResult(isOperationSucceeded bool) {
98	operationMetrics.operationLatency.WithLabelValues(mc.attributes...).Observe(
99		time.Since(mc.start).Seconds())
100	if !isOperationSucceeded {
101		mc.CountFailedOperation()
102	}
103}
104
105// CountFailedOperation increase the number of failed operations
106func (mc *MetricContext) CountFailedOperation() {
107	operationMetrics.operationFailureCount.WithLabelValues(mc.attributes...).Inc()
108}
109
110// registerAPIMetrics registers the API metrics.
111func registerAPIMetrics(attributes ...string) *apiCallMetrics {
112	metrics := &apiCallMetrics{
113		latency: metrics.NewHistogramVec(
114			&metrics.HistogramOpts{
115				Namespace:      azureMetricsNamespace,
116				Name:           "api_request_duration_seconds",
117				Help:           "Latency of an Azure API call",
118				Buckets:        []float64{.1, .25, .5, 1, 2.5, 5, 10, 15, 25, 50, 120, 300, 600, 1200},
119				StabilityLevel: metrics.ALPHA,
120			},
121			attributes,
122		),
123		errors: metrics.NewCounterVec(
124			&metrics.CounterOpts{
125				Namespace:      azureMetricsNamespace,
126				Name:           "api_request_errors",
127				Help:           "Number of errors for an Azure API call",
128				StabilityLevel: metrics.ALPHA,
129			},
130			attributes,
131		),
132		rateLimitedCount: metrics.NewCounterVec(
133			&metrics.CounterOpts{
134				Namespace:      azureMetricsNamespace,
135				Name:           "api_request_ratelimited_count",
136				Help:           "Number of rate limited Azure API calls",
137				StabilityLevel: metrics.ALPHA,
138			},
139			attributes,
140		),
141		throttledCount: metrics.NewCounterVec(
142			&metrics.CounterOpts{
143				Namespace:      azureMetricsNamespace,
144				Name:           "api_request_throttled_count",
145				Help:           "Number of throttled Azure API calls",
146				StabilityLevel: metrics.ALPHA,
147			},
148			attributes,
149		),
150	}
151
152	legacyregistry.MustRegister(metrics.latency)
153	legacyregistry.MustRegister(metrics.errors)
154	legacyregistry.MustRegister(metrics.rateLimitedCount)
155	legacyregistry.MustRegister(metrics.throttledCount)
156
157	return metrics
158}
159
160// registerOperationMetrics registers the operation metrics.
161func registerOperationMetrics(attributes ...string) *operationCallMetrics {
162	metrics := &operationCallMetrics{
163		operationLatency: metrics.NewHistogramVec(
164			&metrics.HistogramOpts{
165				Namespace:      azureMetricsNamespace,
166				Name:           "op_duration_seconds",
167				Help:           "Latency of an Azure service operation",
168				StabilityLevel: metrics.ALPHA,
169				Buckets:        []float64{0.1, 0.2, 0.5, 1, 10, 20, 30, 40, 50, 60, 100, 200, 300},
170			},
171			attributes,
172		),
173		operationFailureCount: metrics.NewCounterVec(
174			&metrics.CounterOpts{
175				Namespace:      azureMetricsNamespace,
176				Name:           "op_failure_count",
177				Help:           "Number of failed Azure service operations",
178				StabilityLevel: metrics.ALPHA,
179			},
180			attributes,
181		),
182	}
183
184	legacyregistry.MustRegister(metrics.operationLatency)
185	legacyregistry.MustRegister(metrics.operationFailureCount)
186
187	return metrics
188}
189