File size: 2,542 Bytes
6380833
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package redis

import (
	"crypto/tls"
	"fmt"

	"github.com/redis/go-redis/extra/redisotel/v9"
	"github.com/redis/go-redis/v9"
	"go.opentelemetry.io/otel/metric"
	"go.opentelemetry.io/otel/trace"
)

type Option func(*Options)

// WithTracingProvider allows to instrument redis.Client with custom tracing provider
func WithTracingProvider(p trace.TracerProvider) Option {
	return func(o *Options) {
		if p != nil {
			o.TracingProvider = p
		}
	}
}

// WithMeterProvider allows to instrument redis.Client with custom metrics provider
func WithMeterProvider(p metric.MeterProvider) Option {
	return func(o *Options) {
		if p != nil {
			o.MeterProvider = p
		}
	}
}

// Options stores all the input parameters to initialize new redis.Client
type Options struct {
	Config

	TracingProvider trace.TracerProvider
	MeterProvider   metric.MeterProvider
}

// NewClient returns a new redis.Client initialized by using configuration parameters provided in Options.
func NewClient(o Options, opts ...Option) (*redis.Client, error) {
	// Apply extra options
	for _, opt := range opts {
		opt(&o)
	}

	// Setup TLS if enabled
	var tlsConfig *tls.Config
	if o.TLS.Enabled {
		tlsConfig = &tls.Config{
			InsecureSkipVerify: o.TLS.InsecureSkipVerify,
			MinVersion:         tls.VersionTLS13,
		}
	}

	// Initialize Redis Client
	var client *redis.Client
	if o.Sentinel.Enabled {
		client = redis.NewFailoverClient(&redis.FailoverOptions{
			MasterName:    o.Sentinel.MasterName,
			SentinelAddrs: []string{o.Address},
			DB:            o.Database,
			Username:      o.Username,
			Password:      o.Password,
			TLSConfig:     tlsConfig,
		})
	} else {
		client = redis.NewClient(&redis.Options{
			Addr:      o.Address,
			DB:        o.Database,
			Username:  o.Username,
			Password:  o.Password,
			TLSConfig: tlsConfig,
		})
	}

	// Enable tracing
	var tracingOpts []redisotel.TracingOption
	if o.TracingProvider != nil {
		tracingOpts = append(tracingOpts, redisotel.WithTracerProvider(o.TracingProvider))
	}
	if err := redisotel.InstrumentTracing(client, tracingOpts...); err != nil {
		return nil, fmt.Errorf("failed to instrument redis client with tracing provider: %w", err)
	}

	// Enable metrics
	var metricsOpts []redisotel.MetricsOption
	if o.MeterProvider != nil {
		metricsOpts = append(metricsOpts, redisotel.WithMeterProvider(o.MeterProvider))
	}
	if err := redisotel.InstrumentMetrics(client, metricsOpts...); err != nil {
		return nil, fmt.Errorf("failed to instrument redis client with meter provider: %w", err)
	}

	return client, nil
}