Skip to content

Commit

Permalink
[grpc][v2] Implement GetServices Call in GRPC reader for remote sto…
Browse files Browse the repository at this point in the history
…rage api v2 (jaegertracing#6829)

<!--
!! Please DELETE this comment before posting.
We appreciate your contribution to the Jaeger project! 👋🎉
-->

## Which problem is this PR solving?
- Towards jaegertracing#6789

## Description of the changes
- This PR implements a `TraceReader` for the remote storage API v2 along
with `GetServices` call.

## How was this change tested?
- Added a unit test

## Checklist
- [x] I have read
https://github.com/jaegertracing/jaeger/blob/master/CONTRIBUTING_GUIDELINES.md
- [x] I have signed all commits
- [x] I have added unit tests for the new functionality
- [x] I have run lint and test steps successfully
  - for `jaeger`: `make lint test`
  - for `jaeger-ui`: `npm run lint` and `npm run test`

---------

Signed-off-by: Mahad Zaryab <[email protected]>
  • Loading branch information
mahadzaryab1 authored Mar 11, 2025
1 parent 136beac commit 2ee205b
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 0 deletions.
14 changes: 14 additions & 0 deletions internal/storage/v2/grpc/package_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright (c) 2025 The Jaeger Authors.
// SPDX-License-Identifier: Apache-2.0

package grpc

import (
"testing"

"github.com/jaegertracing/jaeger/pkg/testutils"
)

func TestMain(m *testing.M) {
testutils.VerifyGoLeaks(m)
}
70 changes: 70 additions & 0 deletions internal/storage/v2/grpc/tracereader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) 2025 The Jaeger Authors.
// SPDX-License-Identifier: Apache-2.0

package grpc

import (
"context"
"errors"
"fmt"
"iter"

"go.opentelemetry.io/collector/pdata/ptrace"
"google.golang.org/grpc"

"github.com/jaegertracing/jaeger/internal/storage/v2/api/tracestore"
"github.com/jaegertracing/jaeger/proto-gen/storage/v2"
)

var _ tracestore.Reader = (*TraceReader)(nil)

var errFailedToGetServices = errors.New("failed to get services")

type TraceReader struct {
client storage.TraceReaderClient
}

// NewTraceReader creates a TraceReader that communicates with a remote gRPC storage server.
// The provided gRPC connection is used exclusively for reading traces, meaning it is safe
// to enable instrumentation on the connection without risk of recursively generating traces.
func NewTraceReader(conn *grpc.ClientConn) *TraceReader {
return &TraceReader{
client: storage.NewTraceReaderClient(conn),
}
}

func (*TraceReader) GetTraces(
context.Context,
...tracestore.GetTraceParams,
) iter.Seq2[[]ptrace.Traces, error] {
panic("not implemented")
}

func (tr *TraceReader) GetServices(ctx context.Context) ([]string, error) {
resp, err := tr.client.GetServices(ctx, &storage.GetServicesRequest{})
if err != nil {
return nil, fmt.Errorf("%w: %w", errFailedToGetServices, err)
}
return resp.Services, nil
}

func (*TraceReader) GetOperations(
context.Context,
tracestore.OperationQueryParams,
) ([]tracestore.Operation, error) {
panic("not implemented")
}

func (*TraceReader) FindTraces(
context.Context,
tracestore.TraceQueryParams,
) iter.Seq2[[]ptrace.Traces, error] {
panic("not implemented")
}

func (*TraceReader) FindTraceIDs(
context.Context,
tracestore.TraceQueryParams,
) iter.Seq2[[]tracestore.FoundTraceID, error] {
panic("not implemented")
}
132 changes: 132 additions & 0 deletions internal/storage/v2/grpc/tracereader_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright (c) 2025 The Jaeger Authors.
// SPDX-License-Identifier: Apache-2.0

package grpc

import (
"context"
"net"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/jaegertracing/jaeger/internal/storage/v2/api/tracestore"
"github.com/jaegertracing/jaeger/proto-gen/storage/v2"
)

// testServer implements the storage.TraceReaderServer interface
// to simulate responses for testing.
type testServer struct {
storage.UnimplementedTraceReaderServer

getServicesError error
}

func (s *testServer) GetServices(
context.Context,
*storage.GetServicesRequest,
) (*storage.GetServicesResponse, error) {
if s.getServicesError != nil {
return nil, s.getServicesError
}
return &storage.GetServicesResponse{
Services: []string{"service-a", "service-b"},
}, nil
}

func startTestServer(t *testing.T, testServer *testServer) *grpc.ClientConn {
listener, err := net.Listen("tcp", ":0")
require.NoError(t, err)

server := grpc.NewServer()
storage.RegisterTraceReaderServer(server, testServer)

go func() {
server.Serve(listener)
}()

conn, err := grpc.NewClient(
listener.Addr().String(),
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
require.NoError(t, err)

t.Cleanup(
func() {
conn.Close()
server.Stop()
listener.Close()
},
)

return conn
}

func TestTraceReader_GetTraces(t *testing.T) {
tr := &TraceReader{}

require.Panics(t, func() {
tr.GetTraces(context.Background(), tracestore.GetTraceParams{})
})
}

func TestTraceReader_GetServices(t *testing.T) {
tests := []struct {
name string
testServer *testServer
expectedServices []string
expectedError error
}{
{
name: "success",
testServer: &testServer{},
expectedServices: []string{"service-a", "service-b"},
},
{
name: "error",
testServer: &testServer{
getServicesError: assert.AnError,
},
expectedError: errFailedToGetServices,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
conn := startTestServer(t, test.testServer)

reader := NewTraceReader(conn)
services, err := reader.GetServices(context.Background())

require.ErrorIs(t, err, test.expectedError)
require.Equal(t, test.expectedServices, services)
})
}
}

func TestTraceReader_GetOperations(t *testing.T) {
tr := &TraceReader{}

require.Panics(t, func() {
tr.GetOperations(context.Background(), tracestore.OperationQueryParams{})
})
}

func TestTraceReader_FindTraces(t *testing.T) {
tr := &TraceReader{}

require.Panics(t, func() {
tr.FindTraces(context.Background(), tracestore.TraceQueryParams{})
})
}

func TestTraceReader_FindTraceIDs(t *testing.T) {
tr := &TraceReader{}

require.Panics(t, func() {
tr.FindTraceIDs(context.Background(), tracestore.TraceQueryParams{})
})
}

0 comments on commit 2ee205b

Please sign in to comment.