github.com/grafana/pyroscope@v1.18.0/pkg/metastore/tenant_service.go (about) 1 package metastore 2 3 import ( 4 "context" 5 6 "github.com/go-kit/log" 7 "github.com/opentracing/opentracing-go" 8 "github.com/opentracing/opentracing-go/ext" 9 "go.etcd.io/bbolt" 10 "google.golang.org/grpc/codes" 11 "google.golang.org/grpc/status" 12 13 metastorev1 "github.com/grafana/pyroscope/api/gen/proto/go/metastore/v1" 14 "github.com/grafana/pyroscope/pkg/metastore/raftnode" 15 ) 16 17 type TenantIndex interface { 18 GetTenants(tx *bbolt.Tx) []string 19 GetTenantStats(tx *bbolt.Tx, tenant string) *metastorev1.TenantStats 20 } 21 22 type TenantService struct { 23 metastorev1.TenantServiceServer 24 25 logger log.Logger 26 state State 27 index TenantIndex 28 } 29 30 func NewTenantService( 31 logger log.Logger, 32 state State, 33 index TenantIndex, 34 ) *TenantService { 35 return &TenantService{ 36 logger: logger, 37 state: state, 38 index: index, 39 } 40 } 41 42 func (svc *TenantService) GetTenants( 43 ctx context.Context, 44 _ *metastorev1.GetTenantsRequest, 45 ) (resp *metastorev1.GetTenantsResponse, err error) { 46 span, ctx := opentracing.StartSpanFromContext(ctx, "TenantService.GetTenants") 47 defer func() { 48 if err != nil { 49 ext.LogError(span, err) 50 } 51 span.Finish() 52 }() 53 54 read := func(tx *bbolt.Tx, _ raftnode.ReadIndex) { 55 resp = &metastorev1.GetTenantsResponse{TenantIds: svc.index.GetTenants(tx)} 56 } 57 if readErr := svc.state.ConsistentRead(ctx, read); readErr != nil { 58 return nil, status.Error(codes.Unavailable, readErr.Error()) 59 } 60 span.SetTag("tenant_count", len(resp.GetTenantIds())) 61 return resp, err 62 } 63 64 func (svc *TenantService) GetTenant( 65 ctx context.Context, 66 req *metastorev1.GetTenantRequest, 67 ) (resp *metastorev1.GetTenantResponse, err error) { 68 span, ctx := opentracing.StartSpanFromContext(ctx, "TenantService.GetTenant") 69 defer func() { 70 if err != nil { 71 ext.LogError(span, err) 72 } 73 span.Finish() 74 }() 75 76 span.SetTag("tenant_id", req.GetTenantId()) 77 78 read := func(tx *bbolt.Tx, _ raftnode.ReadIndex) { 79 resp = &metastorev1.GetTenantResponse{Stats: svc.index.GetTenantStats(tx, req.TenantId)} 80 } 81 if readErr := svc.state.ConsistentRead(ctx, read); readErr != nil { 82 return nil, status.Error(codes.Unavailable, readErr.Error()) 83 } 84 if stats := resp.GetStats(); stats != nil { 85 span.SetTag("data_ingested", stats.GetDataIngested()) 86 span.SetTag("oldest_profile_time", stats.GetOldestProfileTime()) 87 span.SetTag("newest_profile_time", stats.GetNewestProfileTime()) 88 } else { 89 span.SetTag("data_ingested", false) 90 } 91 return resp, err 92 } 93 94 func (svc *TenantService) DeleteTenant( 95 context.Context, 96 *metastorev1.DeleteTenantRequest, 97 ) (*metastorev1.DeleteTenantResponse, error) { 98 // TODO(kolesnikovae): Implement. 99 return new(metastorev1.DeleteTenantResponse), nil 100 }