9
9
"google.golang.org/grpc/status"
10
10
11
11
"github.com/cloudevents/sdk-go/v2/binding"
12
+ cetypes "github.com/cloudevents/sdk-go/v2/types"
12
13
pbv1 "open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/protobuf/v1"
13
14
"open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/protocol"
14
15
"open-cluster-management.io/sdk-go/pkg/cloudevents/generic/types"
@@ -21,37 +22,51 @@ const grpcCEMetricsSubsystem = "grpc_server_ce"
21
22
22
23
// Names of the labels added to metrics:
23
24
const (
25
+ grpcCEMetricsClusterLabel = "consumer"
24
26
grpcCEMetricsDataTypeLabel = "data_type"
25
27
grpcCEMetricsMethodLabel = "method"
26
28
grpcMetricsCodeLabel = "grpc_code"
27
29
)
28
30
29
- // grpcCEMetricsLabels - Array of labels added to grpc server metrics for cloudevents:
30
- var grpcCEMetricsLabels = []string {
31
+ // grpcCEMetricsCommonLabels - Array of common labels added to grpc server metrics for cloudevents:
32
+ var grpcCEMetricsCommonLabels = []string {
33
+ grpcCEMetricsClusterLabel ,
31
34
grpcCEMetricsDataTypeLabel ,
32
- grpcCEMetricsMethodLabel ,
33
35
}
34
36
37
+ // grpcCEMetricsHandlerLabels - Array of handler labels added to grpc server metrics for cloudevents:
38
+ var grpcCEMetricsHandlerLabels = append (grpcCEMetricsCommonLabels , grpcCEMetricsMethodLabel )
39
+
35
40
// grpcCEMetricsAllLabels - Array of all labels added to grpc server metrics for cloudevents:
36
- var grpcCEMetricsAllLabels = append (grpcCEMetricsLabels , grpcMetricsCodeLabel )
41
+ var grpcCEMetricsAllLabels = append (grpcCEMetricsHandlerLabels , grpcMetricsCodeLabel )
37
42
38
43
// Names of the grpc server metrics for cloudevents:
39
44
const (
45
+ subscribersMetric = "subscribers"
40
46
calledCountMetric = "called_total"
41
47
processedCountMetric = "processed_total"
42
48
processingDurationMetric = "processing_duration_seconds"
43
49
messageReceivedCountMetric = "msg_received_total"
44
50
messageSentCountMetric = "msg_sent_total"
45
51
)
46
52
53
+ // grpcCESubscribersMetric is a gauge metric that tracks the number of registered
54
+ // subscribers for cloudevents on the gRPC server.
55
+ var grpcCESubscribersMetric = k8smetrics .NewGaugeVec (& k8smetrics.GaugeOpts {
56
+ Subsystem : grpcCEMetricsSubsystem ,
57
+ Name : subscribersMetric ,
58
+ StabilityLevel : k8smetrics .ALPHA ,
59
+ Help : "Number of registered subscribers for cloudevents on the grpc server." ,
60
+ }, grpcCEMetricsCommonLabels )
61
+
47
62
// grpcCECalledCountMetric is a counter metric that tracks the total number of
48
63
// RPC requests for cloudevents called on the gRPC server.
49
64
var grpcCECalledCountMetric = k8smetrics .NewCounterVec (& k8smetrics.CounterOpts {
50
65
Subsystem : grpcCEMetricsSubsystem ,
51
66
Name : calledCountMetric ,
52
67
StabilityLevel : k8smetrics .ALPHA ,
53
68
Help : "Total number of RPC requests for cloudevents called on the grpc server." ,
54
- }, grpcCEMetricsLabels )
69
+ }, grpcCEMetricsHandlerLabels )
55
70
56
71
// grpcCEMessageReceivedCountMetric is a counter metric that tracks the total number of
57
72
// messages for cloudevents received on the gRPC server.
@@ -60,7 +75,7 @@ var grpcCEMessageReceivedCountMetric = k8smetrics.NewCounterVec(&k8smetrics.Coun
60
75
Name : messageReceivedCountMetric ,
61
76
StabilityLevel : k8smetrics .ALPHA ,
62
77
Help : "Total number of messages for cloudevents received on the gRPC server." ,
63
- }, grpcCEMetricsLabels )
78
+ }, grpcCEMetricsHandlerLabels )
64
79
65
80
// grpcCEMessageSentCountMetric is a counter metric that tracks the total number of
66
81
// messages for cloudevents sent by the gRPC server.
@@ -69,7 +84,7 @@ var grpcCEMessageSentCountMetric = k8smetrics.NewCounterVec(&k8smetrics.CounterO
69
84
Name : messageSentCountMetric ,
70
85
StabilityLevel : k8smetrics .ALPHA ,
71
86
Help : "Total number of messages for cloudevents sent by the gRPC server." ,
72
- }, grpcCEMetricsLabels )
87
+ }, grpcCEMetricsHandlerLabels )
73
88
74
89
// grpcCEProcessedCountMetric is a counter metric that tracks the total number of
75
90
// RPC requests for cloudevents processed on the server, regardless of success or failure.
@@ -106,61 +121,72 @@ func NewCloudEventsMetricsUnaryInterceptor() grpc.UnaryServerInterceptor {
106
121
}
107
122
108
123
// initialize defaults for error cases
124
+ cluster := "unknown"
109
125
dataType := "unknown"
110
126
111
127
pubReq , ok := req .(* pbv1.PublishRequest )
112
128
if ! ok {
113
129
err := fmt .Errorf ("invalid request type for Publish method" )
114
- recordCloudEventsMetrics (dataType , method , err , startTime )
130
+ recordCloudEventsMetrics (cluster , dataType , method , err , startTime )
115
131
return nil , err
116
132
}
117
133
// convert the request to cloudevent and extract the source
118
134
evt , err := binding .ToEvent (ctx , protocol .NewMessage (pubReq .Event ))
119
135
if err != nil {
120
136
err = fmt .Errorf ("failed to convert to cloudevent: %v" , err )
121
- recordCloudEventsMetrics (dataType , method , err , startTime )
137
+ recordCloudEventsMetrics (cluster , dataType , method , err , startTime )
138
+ return nil , err
139
+ }
140
+
141
+ // extract the cluster name from event extensions
142
+ clusterVal , err := cetypes .ToString (evt .Context .GetExtensions ()[types .ExtensionClusterName ])
143
+ if err != nil {
144
+ err = fmt .Errorf ("failed to get clustername extension: %v" , err )
145
+ recordCloudEventsMetrics (cluster , dataType , method , err , startTime )
122
146
return nil , err
123
147
}
148
+ cluster = clusterVal
124
149
125
150
// extract the data type from event type
126
151
eventType , err := types .ParseCloudEventsType (evt .Type ())
127
152
if err != nil {
128
153
err = fmt .Errorf ("failed to parse cloud event type %s, %v" , evt .Type (), err )
129
- recordCloudEventsMetrics (dataType , method , err , startTime )
154
+ recordCloudEventsMetrics (cluster , dataType , method , err , startTime )
130
155
return nil , err
131
156
}
132
157
dataType = eventType .CloudEventsDataType .String ()
133
158
134
- grpcCECalledCountMetric .WithLabelValues (dataType , method ).Inc ()
135
- grpcCEMessageReceivedCountMetric .WithLabelValues (dataType , method ).Inc ()
159
+ grpcCECalledCountMetric .WithLabelValues (cluster , dataType , method ).Inc ()
160
+ grpcCEMessageReceivedCountMetric .WithLabelValues (cluster , dataType , method ).Inc ()
136
161
// call rpc handler to handle RPC request
137
162
resp , err := handler (ctx , req )
138
163
duration := time .Since (startTime ).Seconds ()
139
- grpcCEMessageSentCountMetric .WithLabelValues (dataType , method ).Inc ()
164
+ grpcCEMessageSentCountMetric .WithLabelValues (cluster , dataType , method ).Inc ()
140
165
141
166
// get status code from error
142
167
status := statusFromError (err )
143
168
code := status .Code ()
144
- grpcCEProcessedCountMetric .WithLabelValues (dataType , method , code .String ()).Inc ()
145
- grpcCEProcessingDurationMetric .WithLabelValues (dataType , method , code .String ()).Observe (duration )
169
+ grpcCEProcessedCountMetric .WithLabelValues (cluster , dataType , method , code .String ()).Inc ()
170
+ grpcCEProcessingDurationMetric .WithLabelValues (cluster , dataType , method , code .String ()).Observe (duration )
146
171
147
172
return resp , err
148
173
}
149
174
}
150
175
151
- func recordCloudEventsMetrics (dataType , method string , err error , startTime time.Time ) {
176
+ func recordCloudEventsMetrics (cluster , dataType , method string , err error , startTime time.Time ) {
152
177
duration := time .Since (startTime ).Seconds ()
153
178
status := statusFromError (err )
154
179
code := status .Code ()
155
- grpcCEProcessedCountMetric .WithLabelValues (dataType , method , code .String ()).Inc ()
156
- grpcCEProcessingDurationMetric .WithLabelValues (dataType , method , code .String ()).Observe (duration )
180
+ grpcCEProcessedCountMetric .WithLabelValues (cluster , dataType , method , code .String ()).Inc ()
181
+ grpcCEProcessingDurationMetric .WithLabelValues (cluster , dataType , method , code .String ()).Observe (duration )
157
182
}
158
183
159
184
// wrappedCloudEventsMetricsStream wraps a grpc.ServerStream, capturing the request source
160
185
// emitting metrics for the stream interceptor.
161
186
type wrappedCloudEventsMetricsStream struct {
162
- dataType * string
163
- method string
187
+ clusterName * string
188
+ dataType * string
189
+ method string
164
190
grpc.ServerStream
165
191
ctx context.Context
166
192
}
@@ -178,10 +204,11 @@ func (w *wrappedCloudEventsMetricsStream) RecvMsg(m interface{}) error {
178
204
return fmt .Errorf ("invalid request type for Subscribe method" )
179
205
}
180
206
181
- if w .dataType != nil {
207
+ if w .clusterName != nil && w .dataType != nil {
208
+ * w .clusterName = subReq .ClusterName
182
209
* w .dataType = subReq .DataType
183
- grpcCECalledCountMetric .WithLabelValues (* w .dataType , w .method ).Inc ()
184
- grpcCEMessageReceivedCountMetric .WithLabelValues (* w .dataType , w .method ).Inc ()
210
+ grpcCECalledCountMetric .WithLabelValues (* w .clusterName , * w . dataType , w .method ).Inc ()
211
+ grpcCEMessageReceivedCountMetric .WithLabelValues (* w .clusterName , * w . dataType , w .method ).Inc ()
185
212
}
186
213
187
214
return nil
@@ -194,16 +221,16 @@ func (w *wrappedCloudEventsMetricsStream) SendMsg(m interface{}) error {
194
221
return err
195
222
}
196
223
197
- if w .dataType != nil && * w .dataType != "" {
198
- grpcCEMessageSentCountMetric .WithLabelValues (* w .dataType , w .method ).Inc ()
224
+ if w .clusterName != nil && w . dataType != nil && * w . clusterName != "" && * w .dataType != "" {
225
+ grpcCEMessageSentCountMetric .WithLabelValues (* w .clusterName , * w . dataType , w .method ).Inc ()
199
226
}
200
227
201
228
return nil
202
229
}
203
230
204
- // newWrappedCloudEventsMetricsStream creates a wrappedCloudEventsMetricsStream with the specified type reference.
205
- func newWrappedCloudEventsMetricsStream (dataType * string , method string , ctx context.Context , ss grpc.ServerStream ) grpc.ServerStream {
206
- return & wrappedCloudEventsMetricsStream {dataType , method , ss , ctx }
231
+ // newWrappedCloudEventsMetricsStream creates a wrappedCloudEventsMetricsStream with the specified type and cluster reference.
232
+ func newWrappedCloudEventsMetricsStream (clusterName , dataType * string , method string , ctx context.Context , ss grpc.ServerStream ) grpc.ServerStream {
233
+ return & wrappedCloudEventsMetricsStream {clusterName , dataType , method , ss , ctx }
207
234
}
208
235
209
236
// NewCloudEventsMetricsStreamInterceptor creates a stream server interceptor for server metrics.
@@ -217,15 +244,16 @@ func NewCloudEventsMetricsStreamInterceptor() grpc.StreamServerInterceptor {
217
244
}
218
245
219
246
dataType := ""
247
+ cluster := ""
220
248
// create a wrapped stream to capture the source and emit metrics
221
- wrappedCEMetricsStream := newWrappedCloudEventsMetricsStream (& dataType , method , stream .Context (), stream )
249
+ wrappedCEMetricsStream := newWrappedCloudEventsMetricsStream (& cluster , & dataType , method , stream .Context (), stream )
222
250
// call rpc handler to handle RPC request
223
251
err := handler (srv , wrappedCEMetricsStream )
224
252
225
253
// get status code from error
226
254
status := statusFromError (err )
227
255
code := status .Code ()
228
- grpcCEProcessedCountMetric .WithLabelValues (dataType , method , code .String ()).Inc ()
256
+ grpcCEProcessedCountMetric .WithLabelValues (cluster , dataType , method , code .String ()).Inc ()
229
257
230
258
return err
231
259
}
@@ -264,10 +292,21 @@ func SplitMethod(fullMethod string) (service, method string) {
264
292
// Register all the grpc server metrics for cloudevents.
265
293
func CloudEventsGRPCMetrics () []k8smetrics.Registerable {
266
294
return []k8smetrics.Registerable {
295
+ grpcCESubscribersMetric ,
267
296
grpcCECalledCountMetric ,
268
297
grpcCEProcessedCountMetric ,
269
298
grpcCEProcessingDurationMetric ,
270
299
grpcCEMessageReceivedCountMetric ,
271
300
grpcCEMessageSentCountMetric ,
272
301
}
273
302
}
303
+
304
+ // IncGRPCCESubscribersMetric increments the grpcCESubscribersMetric by 1 for the given cluster and dataType.
305
+ func IncGRPCCESubscribersMetric (cluster , dataType string ) {
306
+ grpcCESubscribersMetric .WithLabelValues (cluster , dataType ).Inc ()
307
+ }
308
+
309
+ // DecGRPCCESubscribersMetric decrements the grpcCESubscribersMetric by 1 for the given cluster and dataType.
310
+ func DecGRPCCESubscribersMetric (cluster , dataType string ) {
311
+ grpcCESubscribersMetric .WithLabelValues (cluster , dataType ).Dec ()
312
+ }
0 commit comments