Skip to content

Commit 464471d

Browse files
authored
Make ES number of shards and replicas configurable (#303)
1 parent 77dc8bd commit 464471d

File tree

6 files changed

+90
-14
lines changed

6 files changed

+90
-14
lines changed

cmd/collector/app/builder/span_handler_builder.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,13 @@ func (e *esSpanHandlerBuilder) BuildHandlers() (app.ZipkinSpansHandler, app.Jaeg
161161
if err != nil {
162162
return nil, nil, err
163163
}
164-
spanStore := esSpanstore.NewSpanWriter(client, e.logger, e.metricsFactory)
164+
spanStore := esSpanstore.NewSpanWriter(
165+
client,
166+
e.logger,
167+
e.metricsFactory,
168+
e.configuration.NumShards,
169+
e.configuration.NumReplicas,
170+
)
165171

166172
return buildHandlers(spanStore, e.logger, e.metricsFactory)
167173
}

pkg/es/config/config.go

+8-6
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@ import (
2929
"github.com/uber/jaeger/pkg/es"
3030
)
3131

32-
// Configuration describes the configuration properties needed to connect to a ElasticSearch cluster
32+
// Configuration describes the configuration properties needed to connect to an ElasticSearch cluster
3333
type Configuration struct {
34-
Servers []string
35-
Username string
36-
Password string
37-
Sniffer bool // https://github.com/olivere/elastic/wiki/Sniffing
38-
MaxSpanAge time.Duration // configures the maximum lookback on span reads
34+
Servers []string
35+
Username string
36+
Password string
37+
Sniffer bool // https://github.com/olivere/elastic/wiki/Sniffing
38+
MaxSpanAge time.Duration `yaml:"max_span_age"` // configures the maximum lookback on span reads
39+
NumShards int64 `yaml:"shards"`
40+
NumReplicas int64 `yaml:"replicas"`
3941
}
4042

4143
// NewClient creates a new ElasticSearch client

plugin/storage/es/spanstore/schema.go

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import "fmt"
2525
// TODO: resolve traceID concerns (may not require any changes here)
2626
const mapping = `{
2727
"settings":{
28+
"index.number_of_shards": ${__NUMBER_OF_SHARDS__},
29+
"index.number_of_replicas": ${__NUMBER_OF_REPLICAS__},
2830
"index.mapping.nested_fields.limit":50,
2931
"index.requests.cache.enable":true,
3032
"index.mapper.dynamic":false

plugin/storage/es/spanstore/writer.go

+29-2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ package spanstore
2222

2323
import (
2424
"context"
25+
"strconv"
26+
"strings"
2527
"time"
2628

2729
"github.com/pkg/errors"
@@ -39,6 +41,9 @@ import (
3941
const (
4042
spanType = "span"
4143
serviceType = "service"
44+
45+
defaultNumShards = 5
46+
defaultNumReplicas = 2
4247
)
4348

4449
type spanWriterMetrics struct {
@@ -56,6 +61,8 @@ type SpanWriter struct {
5661
writerMetrics spanWriterMetrics // TODO: build functions to wrap around each Do fn
5762
indexCache cache.Cache
5863
serviceWriter serviceWriter
64+
numShards int64
65+
numReplicas int64
5966
}
6067

6168
// Service is the JSON struct for service:operation documents in ElasticSearch
@@ -65,8 +72,20 @@ type Service struct {
6572
}
6673

6774
// NewSpanWriter creates a new SpanWriter for use
68-
func NewSpanWriter(client es.Client, logger *zap.Logger, metricsFactory metrics.Factory) *SpanWriter {
75+
func NewSpanWriter(
76+
client es.Client,
77+
logger *zap.Logger,
78+
metricsFactory metrics.Factory,
79+
numShards int64,
80+
numReplicas int64,
81+
) *SpanWriter {
6982
ctx := context.Background()
83+
if numShards == 0 {
84+
numShards = defaultNumShards
85+
}
86+
if numReplicas == 0 {
87+
numReplicas = defaultNumReplicas
88+
}
7089
// TODO: Configurable TTL
7190
serviceOperationStorage := NewServiceOperationStorage(ctx, client, metricsFactory, logger, time.Hour*12)
7291
return &SpanWriter{
@@ -84,6 +103,8 @@ func NewSpanWriter(client es.Client, logger *zap.Logger, metricsFactory metrics.
84103
TTL: 48 * time.Hour,
85104
},
86105
),
106+
numShards: numShards,
107+
numReplicas: numReplicas,
87108
}
88109
}
89110

@@ -121,7 +142,7 @@ func (s *SpanWriter) createIndex(indexName string, mapping string, jsonSpan *jMo
121142
// if there are multiple collectors writing to the same elasticsearch host, if the collectors pass
122143
// the exists check above and try to create the same index all at once, this might fail and
123144
// drop a couple spans (~1 per collector). Creating indices ahead of time alleviates this issue.
124-
_, err := s.client.CreateIndex(indexName).Body(mapping).Do(s.ctx)
145+
_, err := s.client.CreateIndex(indexName).Body(s.fixMapping(mapping)).Do(s.ctx)
125146
s.writerMetrics.indexCreate.Emit(err, time.Since(start))
126147
if err != nil {
127148
return s.logError(jsonSpan, err, "Failed to create index", s.logger)
@@ -140,6 +161,12 @@ func writeCache(key string, c cache.Cache) {
140161
c.Put(key, key)
141162
}
142163

164+
func (s *SpanWriter) fixMapping(mapping string) string {
165+
mapping = strings.Replace(mapping, "${__NUMBER_OF_SHARDS__}", strconv.FormatInt(s.numShards, 10), 1)
166+
mapping = strings.Replace(mapping, "${__NUMBER_OF_REPLICAS__}", strconv.FormatInt(s.numReplicas, 10), 1)
167+
return mapping
168+
}
169+
143170
func (s *SpanWriter) writeService(indexName string, jsonSpan *jModel.Span) error {
144171
return s.serviceWriter(indexName, jsonSpan)
145172
}

plugin/storage/es/spanstore/writer_test.go

+43-4
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func withSpanWriter(fn func(w *spanWriterTest)) {
5555
client: client,
5656
logger: logger,
5757
logBuffer: logBuffer,
58-
writer: NewSpanWriter(client, logger, metricsFactory),
58+
writer: NewSpanWriter(client, logger, metricsFactory, 0, 0),
5959
}
6060
fn(w)
6161
}
@@ -178,11 +178,11 @@ func TestSpanWriter_WriteSpan(t *testing.T) {
178178
spanExistsService.On("Do", mock.AnythingOfType("*context.emptyCtx")).Return(testCase.spanIndexExists, nil)
179179

180180
serviceCreateService := &mocks.IndicesCreateService{}
181-
serviceCreateService.On("Body", stringMatcher(serviceMapping)).Return(serviceCreateService)
181+
serviceCreateService.On("Body", stringMatcher(w.writer.fixMapping(serviceMapping))).Return(serviceCreateService)
182182
serviceCreateService.On("Do", mock.AnythingOfType("*context.emptyCtx")).Return(nil, testCase.serviceIndexCreateError)
183183

184184
spanCreateService := &mocks.IndicesCreateService{}
185-
spanCreateService.On("Body", stringMatcher(spanMapping)).Return(spanCreateService)
185+
spanCreateService.On("Body", stringMatcher(w.writer.fixMapping(spanMapping))).Return(spanCreateService)
186186
spanCreateService.On("Do", mock.AnythingOfType("*context.emptyCtx")).Return(nil, testCase.spanIndexCreateError)
187187

188188
indexService := &mocks.IndexService{}
@@ -272,7 +272,7 @@ func TestCheckAndCreateIndex(t *testing.T) {
272272
existsService.On("Do", mock.AnythingOfType("*context.emptyCtx")).Return(testCase.indexExists, testCase.indexExistsError)
273273

274274
createService := &mocks.IndicesCreateService{}
275-
createService.On("Body", stringMatcher(spanMapping)).Return(createService)
275+
createService.On("Body", stringMatcher(w.writer.fixMapping(spanMapping))).Return(createService)
276276
createService.On("Do", mock.AnythingOfType("*context.emptyCtx")).Return(testCase.createResult, testCase.createError)
277277

278278
indexName := "jaeger-1995-04-21"
@@ -306,6 +306,45 @@ func TestCheckAndCreateIndex(t *testing.T) {
306306
}
307307
}
308308

309+
func TestFixMapping(t *testing.T) {
310+
withSpanWriter(func(w *spanWriterTest) {
311+
testMapping := `{
312+
"settings":{
313+
"index.number_of_shards": ${__NUMBER_OF_SHARDS__},
314+
"index.number_of_replicas": ${__NUMBER_OF_REPLICAS__},
315+
"index.mapping.nested_fields.limit":50,
316+
"index.requests.cache.enable":true,
317+
"index.mapper.dynamic":false
318+
},
319+
"mappings":{
320+
"_default_":{
321+
"_all":{
322+
"enabled":false
323+
}
324+
}
325+
}
326+
}`
327+
expectedMapping := `{
328+
"settings":{
329+
"index.number_of_shards": 5,
330+
"index.number_of_replicas": 2,
331+
"index.mapping.nested_fields.limit":50,
332+
"index.requests.cache.enable":true,
333+
"index.mapper.dynamic":false
334+
},
335+
"mappings":{
336+
"_default_":{
337+
"_all":{
338+
"enabled":false
339+
}
340+
}
341+
}
342+
}`
343+
344+
assert.Equal(t, expectedMapping, w.writer.fixMapping(testMapping))
345+
})
346+
}
347+
309348
func TestWriteSpanInternal(t *testing.T) {
310349
withSpanWriter(func(w *spanWriterTest) {
311350
indexService := &mocks.IndexService{}

plugin/storage/integration/es_integration_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ func (s *ESStorageIntegration) esCleanUp() error {
8484

8585
func (s *ESStorageIntegration) initSpanstore() {
8686
client := es.WrapESClient(s.client)
87-
s.spanWriter = spanstore.NewSpanWriter(client, s.logger, metrics.NullFactory)
87+
s.spanWriter = spanstore.NewSpanWriter(client, s.logger, metrics.NullFactory, 0, 0)
8888
s.spanReader = spanstore.NewSpanReader(client, s.logger, 72*time.Hour, metrics.NullFactory)
8989
}
9090

0 commit comments

Comments
 (0)