Path: blob/main/components/ws-manager-mk2/pkg/proxy/servicename-prefixer.go
2500 views
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package proxy56import (7"context"8"strings"910"github.com/gitpod-io/gitpod/common-go/log"11"google.golang.org/grpc"12)1314// ServiceNamePrefixerInterceptor adds a prefix to the service name in gRPC method calls for metrics15type ServiceNamePrefixerInterceptor struct {16// Prefix is added before the first dot in the gRPC method name.17// For example, if the original method is "/builder.ImageBuilder/Build",18// and Prefix is "proxied", the modified method will be "/proxied.builder.ImageBuilder/Build".19Prefix string20}2122// UnaryServerInterceptor returns a unary server interceptor that prefixes service names23func (s *ServiceNamePrefixerInterceptor) UnaryServerInterceptor() grpc.UnaryServerInterceptor {24return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {25// Modify the FullMethod to include the prefix26originalMethod := info.FullMethod27log.Info("Intercepting gRPC unary call", "method", originalMethod, "prefix", s.Prefix)28info.FullMethod = s.prefixServiceName(originalMethod)2930// Call the handler with modified info31resp, err := handler(ctx, req)3233// Restore original method name34info.FullMethod = originalMethod3536return resp, err37}38}3940// StreamServerInterceptor returns a stream server interceptor that prefixes service names41func (s *ServiceNamePrefixerInterceptor) StreamServerInterceptor() grpc.StreamServerInterceptor {42return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {43// Modify the FullMethod to include the prefix44originalMethod := info.FullMethod45log.Info("Intercepting gRPC stream call", "method", originalMethod, "prefix", s.Prefix)46info.FullMethod = s.prefixServiceName(originalMethod)4748// Call the handler with modified info49err := handler(srv, ss)5051// Restore original method name52info.FullMethod = originalMethod5354return err55}56}5758func (s *ServiceNamePrefixerInterceptor) prefixServiceName(fullMethod string) string {59// fullMethod format is /package.Service/Method60// We want to change it to /proxied.package.Service/Method using the first dot as anchor61if s.Prefix == "" || len(fullMethod) == 0 {62return fullMethod63}6465// Find the first dot after the leading slash66if !strings.HasPrefix(fullMethod, "/") {67return fullMethod // malformed input68}6970// Look for the first dot in the method name71dotIndex := strings.Index(fullMethod[1:], ".") // skip the leading slash72if dotIndex == -1 {73return fullMethod // no dot found, return original74}7576// Insert prefix before the first dot77// /builder.ImageBuilder/Build -> /proxied.builder.ImageBuilder/Build78prefix := strings.TrimPrefix(strings.TrimSuffix(s.Prefix, "/"), "/")79return "/" + prefix + "." + fullMethod[1:]80}818283