Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/ws-manager-mk2/pkg/proxy/servicename-prefixer.go
2500 views
1
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package proxy
6
7
import (
8
"context"
9
"strings"
10
11
"github.com/gitpod-io/gitpod/common-go/log"
12
"google.golang.org/grpc"
13
)
14
15
// ServiceNamePrefixerInterceptor adds a prefix to the service name in gRPC method calls for metrics
16
type ServiceNamePrefixerInterceptor struct {
17
// Prefix is added before the first dot in the gRPC method name.
18
// For example, if the original method is "/builder.ImageBuilder/Build",
19
// and Prefix is "proxied", the modified method will be "/proxied.builder.ImageBuilder/Build".
20
Prefix string
21
}
22
23
// UnaryServerInterceptor returns a unary server interceptor that prefixes service names
24
func (s *ServiceNamePrefixerInterceptor) UnaryServerInterceptor() grpc.UnaryServerInterceptor {
25
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
26
// Modify the FullMethod to include the prefix
27
originalMethod := info.FullMethod
28
log.Info("Intercepting gRPC unary call", "method", originalMethod, "prefix", s.Prefix)
29
info.FullMethod = s.prefixServiceName(originalMethod)
30
31
// Call the handler with modified info
32
resp, err := handler(ctx, req)
33
34
// Restore original method name
35
info.FullMethod = originalMethod
36
37
return resp, err
38
}
39
}
40
41
// StreamServerInterceptor returns a stream server interceptor that prefixes service names
42
func (s *ServiceNamePrefixerInterceptor) StreamServerInterceptor() grpc.StreamServerInterceptor {
43
return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
44
// Modify the FullMethod to include the prefix
45
originalMethod := info.FullMethod
46
log.Info("Intercepting gRPC stream call", "method", originalMethod, "prefix", s.Prefix)
47
info.FullMethod = s.prefixServiceName(originalMethod)
48
49
// Call the handler with modified info
50
err := handler(srv, ss)
51
52
// Restore original method name
53
info.FullMethod = originalMethod
54
55
return err
56
}
57
}
58
59
func (s *ServiceNamePrefixerInterceptor) prefixServiceName(fullMethod string) string {
60
// fullMethod format is /package.Service/Method
61
// We want to change it to /proxied.package.Service/Method using the first dot as anchor
62
if s.Prefix == "" || len(fullMethod) == 0 {
63
return fullMethod
64
}
65
66
// Find the first dot after the leading slash
67
if !strings.HasPrefix(fullMethod, "/") {
68
return fullMethod // malformed input
69
}
70
71
// Look for the first dot in the method name
72
dotIndex := strings.Index(fullMethod[1:], ".") // skip the leading slash
73
if dotIndex == -1 {
74
return fullMethod // no dot found, return original
75
}
76
77
// Insert prefix before the first dot
78
// /builder.ImageBuilder/Build -> /proxied.builder.ImageBuilder/Build
79
prefix := strings.TrimPrefix(strings.TrimSuffix(s.Prefix, "/"), "/")
80
return "/" + prefix + "." + fullMethod[1:]
81
}
82
83