Skip to content

Commit 160ea5d

Browse files
committed
refactor(grpc): improve code quality and fix linter issues
- Fix naming inconsistencies and standardize method names - Add package comments and fix formatting - Fix linter warnings (lll, revive, varnamelen, noctx, etc.) - Improve code organization and readability
1 parent 08d41de commit 160ea5d

File tree

9 files changed

+499
-116
lines changed

9 files changed

+499
-116
lines changed

go.work.sum

Lines changed: 308 additions & 0 deletions
Large diffs are not rendered by default.

grpc/client.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Package grpc provides gRPC client and server implementations with
2+
// middleware support for logging, tracing, metrics, and session management.
13
package grpc
24

35
import (
@@ -12,6 +14,7 @@ import (
1214
"google.golang.org/grpc/credentials/insecure"
1315
)
1416

17+
// Client represents a gRPC client configuration.
1518
type Client struct {
1619
interceptorUnaryClientList []grpc.UnaryClientInterceptor
1720
interceptorStreamClientList []grpc.StreamClientInterceptor
@@ -22,12 +25,18 @@ type Client struct {
2225
cfg *config.Config
2326
}
2427

28+
// GetURI returns the connection URI in the format "host:port".
2529
func (c *Client) GetURI() string {
2630
return fmt.Sprintf("%s:%d", c.host, c.port)
2731
}
2832

29-
// InitClient - set up a connection to the server.
30-
func InitClient(_ context.Context, log logger.Logger, cfg *config.Config, options ...Option) (*grpc.ClientConn, func(), error) {
33+
// InitClient sets up a connection to the gRPC server.
34+
func InitClient(
35+
_ context.Context,
36+
log logger.Logger,
37+
cfg *config.Config,
38+
options ...Option,
39+
) (*grpc.ClientConn, func(), error) {
3140
config, err := SetClientConfig(cfg, options...)
3241
if err != nil {
3342
return nil, nil, err
@@ -54,7 +63,7 @@ func InitClient(_ context.Context, log logger.Logger, cfg *config.Config, option
5463
return conn, cleanup, nil
5564
}
5665

57-
// SetClientConfig - set configuration
66+
// SetClientConfig - set configuration.
5867
func SetClientConfig(cfg *config.Config, options ...Option) (*Client, error) {
5968
cfg.SetDefault("GRPC_CLIENT_PORT", "50051") // gRPC port
6069
grpcPort := cfg.GetInt("GRPC_CLIENT_PORT")
@@ -70,7 +79,7 @@ func SetClientConfig(cfg *config.Config, options ...Option) (*Client, error) {
7079

7180
config.apply(options...)
7281

73-
// Initialize your gRPC server's interceptor.
82+
// Initialize your gRPC client's interceptor.
7483
config.optionsNewClient = append(
7584
config.optionsNewClient,
7685
grpc.WithChainUnaryInterceptor(config.interceptorUnaryClientList...),
@@ -91,7 +100,7 @@ func (c *Client) GetOptions() []grpc.DialOption {
91100
return c.optionsNewClient
92101
}
93102

94-
// withTLS - setup TLS
103+
// withTLS - setup TLS.
95104
func (c *Client) withTLS() error {
96105
c.cfg.SetDefault("GRPC_CLIENT_TLS_ENABLED", false) // gRPC TLS
97106
isEnableTLS := c.cfg.GetBool("GRPC_CLIENT_TLS_ENABLED")

grpc/client_options.go

Lines changed: 56 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,72 +4,82 @@ import (
44
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus"
55
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/timeout"
66
"github.com/prometheus/client_golang/prometheus"
7+
grpc_logger "github.com/shortlink-org/go-sdk/grpc/middleware/logger"
8+
session_interceptor "github.com/shortlink-org/go-sdk/grpc/middleware/session"
9+
"github.com/shortlink-org/go-sdk/logger"
710
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
811
api "go.opentelemetry.io/otel/sdk/metric"
912
"go.opentelemetry.io/otel/trace"
1013
"google.golang.org/grpc"
11-
12-
grpc_logger "github.com/shortlink-org/go-sdk/grpc/middleware/logger"
13-
session_interceptor "github.com/shortlink-org/go-sdk/grpc/middleware/session"
14-
"github.com/shortlink-org/go-sdk/logger"
1514
)
1615

16+
// Option configures a gRPC client.
1717
type Option func(*Client)
1818

19-
// Apply a batch of options
19+
// Apply a batch of options.
2020
func (c *Client) apply(options ...Option) {
2121
for _, option := range options {
2222
option(c)
2323
}
2424
}
2525

26-
// WithTimeout sets a unary timeout interceptor
26+
// WithTimeout sets a unary timeout interceptor.
2727
func WithTimeout() Option {
28-
return func(c *Client) {
29-
c.cfg.SetDefault("GRPC_CLIENT_TIMEOUT", "10s") // Set timeout for gRPC-Client
30-
timeoutClient := c.cfg.GetDuration("GRPC_CLIENT_TIMEOUT")
28+
return func(client *Client) {
29+
client.cfg.SetDefault("GRPC_CLIENT_TIMEOUT", "10s") // Set timeout for gRPC-Client
30+
timeoutClient := client.cfg.GetDuration("GRPC_CLIENT_TIMEOUT")
3131

32-
c.interceptorUnaryClientList = append(
33-
c.interceptorUnaryClientList,
32+
client.interceptorUnaryClientList = append(
33+
client.interceptorUnaryClientList,
3434
timeout.UnaryClientInterceptor(timeoutClient),
3535
)
3636
}
3737
}
3838

39-
// WithLogger adds unary & stream logging interceptors
39+
// WithLogger adds unary & stream logging interceptors.
4040
func WithLogger(log logger.Logger) Option {
41-
return func(c *Client) {
42-
c.cfg.SetDefault("GRPC_CLIENT_LOGGER_ENABLED", true) // Enable logging for gRPC-Client
43-
isEnableLogger := c.cfg.GetBool("GRPC_CLIENT_LOGGER_ENABLED")
41+
return func(client *Client) {
42+
client.cfg.SetDefault("GRPC_CLIENT_LOGGER_ENABLED", true) // Enable logging for gRPC-Client
43+
44+
isEnableLogger := client.cfg.GetBool("GRPC_CLIENT_LOGGER_ENABLED")
4445
if !isEnableLogger {
4546
return
4647
}
4748

48-
c.interceptorUnaryClientList = append(c.interceptorUnaryClientList, grpc_logger.UnaryClientInterceptor(log))
49-
c.interceptorStreamClientList = append(c.interceptorStreamClientList, grpc_logger.StreamClientInterceptor(log))
49+
client.interceptorUnaryClientList = append(
50+
client.interceptorUnaryClientList,
51+
grpc_logger.UnaryClientInterceptor(log),
52+
)
53+
client.interceptorStreamClientList = append(
54+
client.interceptorStreamClientList,
55+
grpc_logger.StreamClientInterceptor(log),
56+
)
5057
}
5158
}
5259

53-
// WithTracer wires up otel handler
60+
// WithTracer wires up otel handler.
5461
func WithTracer(tracer trace.TracerProvider, prom *prometheus.Registry, metrics *api.MeterProvider) Option {
55-
return func(c *Client) {
62+
return func(client *Client) {
5663
if tracer == nil || prom == nil {
5764
return
5865
}
5966

60-
c.optionsNewClient = append(c.optionsNewClient, grpc.WithStatsHandler(
61-
otelgrpc.NewClientHandler(
62-
otelgrpc.WithTracerProvider(tracer),
63-
otelgrpc.WithMeterProvider(metrics),
64-
otelgrpc.WithMessageEvents(otelgrpc.ReceivedEvents, otelgrpc.SentEvents),
67+
client.optionsNewClient = append(
68+
client.optionsNewClient,
69+
grpc.WithStatsHandler(
70+
otelgrpc.NewClientHandler(
71+
otelgrpc.WithTracerProvider(tracer),
72+
otelgrpc.WithMeterProvider(metrics),
73+
otelgrpc.WithMessageEvents(otelgrpc.ReceivedEvents, otelgrpc.SentEvents),
74+
),
6575
),
66-
))
76+
)
6777
}
6878
}
6979

70-
// WithMetrics registers Prom metrics + interceptors
80+
// WithMetrics registers Prom metrics + interceptors.
7181
func WithMetrics(prom *prometheus.Registry) Option {
72-
return func(c *Client) {
82+
return func(client *Client) {
7383
if prom == nil {
7484
return
7585
}
@@ -83,21 +93,34 @@ func WithMetrics(prom *prometheus.Registry) Option {
8393
)
8494
exemplarFromCtx := grpc_prometheus.WithExemplarFromContext(exemplarFromContext)
8595

86-
c.interceptorUnaryClientList = append(c.interceptorUnaryClientList, clientMetrics.UnaryClientInterceptor(exemplarFromCtx))
87-
c.interceptorStreamClientList = append(c.interceptorStreamClientList, clientMetrics.StreamClientInterceptor(exemplarFromCtx))
96+
client.interceptorUnaryClientList = append(
97+
client.interceptorUnaryClientList,
98+
clientMetrics.UnaryClientInterceptor(exemplarFromCtx),
99+
)
100+
client.interceptorStreamClientList = append(
101+
client.interceptorStreamClientList,
102+
clientMetrics.StreamClientInterceptor(exemplarFromCtx),
103+
)
88104

89105
defer func() {
90106
// ignore duplicate-registration panic
91107
_ = recover()
92108
}()
109+
93110
prom.MustRegister(clientMetrics)
94111
}
95112
}
96113

97-
// WithSession adds session interceptors with optional ignore rules
114+
// WithSession adds session interceptors with optional ignore rules.
98115
func WithSession() Option {
99-
return func(c *Client) {
100-
c.interceptorUnaryClientList = append(c.interceptorUnaryClientList, session_interceptor.SessionUnaryClientInterceptor())
101-
c.interceptorStreamClientList = append(c.interceptorStreamClientList, session_interceptor.SessionStreamClientInterceptor())
116+
return func(client *Client) {
117+
client.interceptorUnaryClientList = append(
118+
client.interceptorUnaryClientList,
119+
session_interceptor.SessionUnaryClientInterceptor(),
120+
)
121+
client.interceptorStreamClientList = append(
122+
client.interceptorStreamClientList,
123+
session_interceptor.SessionStreamClientInterceptor(),
124+
)
102125
}
103126
}

grpc/middleware/flight_trace/server_interceptors.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Package flight_trace provides gRPC interceptors for flight recorder integration.
2+
//
3+
//nolint:revive // package name uses underscore for consistency with project structure
14
package flight_trace
25

36
import (
@@ -7,27 +10,30 @@ import (
710
"time"
811

912
"github.com/google/uuid"
13+
"github.com/shortlink-org/go-sdk/config"
14+
"github.com/shortlink-org/go-sdk/flight_trace"
15+
"github.com/shortlink-org/go-sdk/logger"
1016
"go.opentelemetry.io/otel/attribute"
1117
"go.opentelemetry.io/otel/trace"
1218
"google.golang.org/grpc"
1319
"google.golang.org/grpc/metadata"
1420
"google.golang.org/grpc/status"
15-
16-
"github.com/shortlink-org/go-sdk/config"
17-
"github.com/shortlink-org/go-sdk/flight_trace"
18-
"github.com/shortlink-org/go-sdk/logger"
1921
)
2022

2123
const debugTraceKey = "X-DEBUG-TRACE"
2224

2325
// UnaryServerInterceptor records Flight Recorder dumps based on conditions:
2426
// - Incoming metadata contains "X-DEBUG-TRACE: true"
25-
// - The request latency exceeds FLIGHT_TRACE_LATENCY_THRESHOLD
26-
func UnaryServerInterceptor(fr *flight_trace.Recorder, log logger.Logger, cfg *config.Config) grpc.UnaryServerInterceptor {
27+
// - The request latency exceeds FLIGHT_TRACE_LATENCY_THRESHOLD.
28+
func UnaryServerInterceptor(
29+
flightRecorder *flight_trace.Recorder,
30+
log logger.Logger,
31+
cfg *config.Config,
32+
) grpc.UnaryServerInterceptor {
2733
cfg.SetDefault("FLIGHT_TRACE_LATENCY_THRESHOLD", "1s")
2834

2935
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
30-
if fr == nil {
36+
if flightRecorder == nil {
3137
return handler(ctx, req)
3238
}
3339

@@ -50,7 +56,7 @@ func UnaryServerInterceptor(fr *flight_trace.Recorder, log logger.Logger, cfg *c
5056
}
5157

5258
go func() {
53-
fr.DumpToFileAsync(fileName)
59+
flightRecorder.DumpToFileAsync(fileName)
5460
log.InfoWithContext(ctx, "flight recorder dump triggered",
5561
slog.String("file", fileName),
5662
slog.String("grpc.service", path.Dir(info.FullMethod)[1:]),
@@ -66,11 +72,15 @@ func UnaryServerInterceptor(fr *flight_trace.Recorder, log logger.Logger, cfg *c
6672
}
6773

6874
// StreamServerInterceptor is similar to UnaryServerInterceptor but for streaming RPCs.
69-
func StreamServerInterceptor(fr *flight_trace.Recorder, log logger.Logger, cfg *config.Config) grpc.StreamServerInterceptor {
75+
func StreamServerInterceptor(
76+
flightRecorder *flight_trace.Recorder,
77+
log logger.Logger,
78+
cfg *config.Config,
79+
) grpc.StreamServerInterceptor {
7080
cfg.SetDefault("FLIGHT_TRACE_LATENCY_THRESHOLD", "1s")
7181

7282
return func(srv any, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
73-
if fr == nil {
83+
if flightRecorder == nil {
7484
return handler(srv, stream)
7585
}
7686

@@ -93,7 +103,7 @@ func StreamServerInterceptor(fr *flight_trace.Recorder, log logger.Logger, cfg *
93103
}
94104

95105
go func() {
96-
fr.DumpToFileAsync(fileName)
106+
flightRecorder.DumpToFileAsync(fileName)
97107
log.InfoWithContext(stream.Context(), "flight recorder dump triggered (stream)",
98108
slog.String("file", fileName),
99109
slog.String("grpc.service", path.Dir(info.FullMethod)[1:]),

grpc/middleware/logger/client_interceptors.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// Package grpc_logger provides client-side logging interceptors for gRPC.
12
package grpc_logger
23

34
import (
@@ -6,18 +7,25 @@ import (
67
"path"
78
"time"
89

10+
"github.com/shortlink-org/go-sdk/logger"
911
"go.opentelemetry.io/otel/attribute"
1012
"go.opentelemetry.io/otel/trace"
1113
"google.golang.org/grpc"
1214
"google.golang.org/grpc/status"
1315
"google.golang.org/protobuf/proto"
14-
15-
"github.com/shortlink-org/go-sdk/logger"
1616
)
1717

18-
// UnaryClientInterceptor returns a new unary client interceptor that optionally logs the execution of external gRPC calls.
18+
// UnaryClientInterceptor returns a new unary client interceptor that optionally
19+
// logs the execution of external gRPC calls.
1920
func UnaryClientInterceptor(log logger.Logger) grpc.UnaryClientInterceptor {
20-
return func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
21+
return func(
22+
ctx context.Context,
23+
method string,
24+
req, reply any,
25+
cc *grpc.ClientConn,
26+
invoker grpc.UnaryInvoker,
27+
opts ...grpc.CallOption,
28+
) error {
2129
startTime := time.Now()
2230
err := invoker(ctx, method, req, reply, cc, opts...)
2331
duration := time.Since(startTime)
@@ -26,6 +34,7 @@ func UnaryClientInterceptor(log logger.Logger) grpc.UnaryClientInterceptor {
2634
if msg, ok := req.(proto.Message); ok {
2735
span.SetAttributes(attribute.String("rpc.request", string(proto.MessageName(msg))))
2836
}
37+
2938
if msg, ok := reply.(proto.Message); ok {
3039
span.SetAttributes(attribute.String("rpc.response", string(proto.MessageName(msg))))
3140
}
@@ -46,7 +55,8 @@ func UnaryClientInterceptor(log logger.Logger) grpc.UnaryClientInterceptor {
4655
}
4756
}
4857

49-
// StreamClientInterceptor returns a new streaming client interceptor that optionally logs the execution of external gRPC calls.
58+
// StreamClientInterceptor returns a new streaming client interceptor that optionally
59+
// logs the execution of external gRPC calls.
5060
func StreamClientInterceptor(log logger.Logger) grpc.StreamClientInterceptor {
5161
return func(
5262
ctx context.Context,

grpc/middleware/logger/logger.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1+
//nolint:revive // package name uses underscore for consistency with project structure
12
package grpc_logger
23

34
import (
45
"context"
56
"log/slog"
67

8+
"github.com/shortlink-org/go-sdk/logger"
79
"google.golang.org/grpc/codes"
810
"google.golang.org/grpc/status"
9-
10-
"github.com/shortlink-org/go-sdk/logger"
1111
)
1212

1313
func printLog(ctx context.Context, log logger.Logger, err error, fields ...slog.Attr) {
1414
switch status.Code(err) {
15-
//nolint:lll // TODO: refactor
1615
case
1716
codes.OK,
1817
codes.Canceled,

grpc/middleware/logger/server_interceptors.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@ import (
77
"time"
88

99
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware/v2"
10+
"github.com/shortlink-org/go-sdk/logger"
1011
"go.opentelemetry.io/otel/attribute"
1112
"go.opentelemetry.io/otel/trace"
1213
"google.golang.org/grpc"
1314
"google.golang.org/grpc/status"
1415
"google.golang.org/protobuf/proto"
15-
16-
"github.com/shortlink-org/go-sdk/logger"
1716
)
1817

1918
// UnaryServerInterceptor returns a new unary server interceptors that adds zap.Logger to the context.
@@ -27,6 +26,7 @@ func UnaryServerInterceptor(log logger.Logger) grpc.UnaryServerInterceptor {
2726
if msg, ok := req.(proto.Message); ok {
2827
span.SetAttributes(attribute.String("rpc.request", string(proto.MessageName(msg))))
2928
}
29+
3030
if msg, ok := resp.(proto.Message); ok {
3131
span.SetAttributes(attribute.String("rpc.response", string(proto.MessageName(msg))))
3232
}

0 commit comments

Comments
 (0)