Skip to content

Commit 1f8c1ee

Browse files
authored
[exporter/elasticsearch] use v8 client, drop support for EOL versions of ES (#37333)
#### Description Update to go-elasticsearch v8, which breaks support for older versions of Elasticsearch v7. The non-EOL v7.17.x versions of Elasticsearch are still supported by the exporter. Add an explicit statement to the README that EOL versions are not supported by the exporter. Updating to the v8 client allows us to turn on OTel tracing instrumentation for the go-elasticsearch client. #### Link to tracking issue Closes #32454 #### Testing - Tested with 8.latest, confirmed working - Tested with 7.17.lasted, confirmed working - Tested with 7.10 (EOL), confirmed that it fails with an error message: > 2025-02-05T13:23:42.788+0800 error elasticsearchexporter/bulkindexer.go:337 bulk indexer flush error {"kind": "exporter", "data_type": "metrics", "name": "elasticsearch", "error": "failed to execute the request: the client noticed that the server is not Elasticsearch and we do not support this unknown product"} (7.10 predates the product check protocol that was added to go-elasticsearch v8.) #### Documentation Updated README.
1 parent d1d4d69 commit 1f8c1ee

File tree

10 files changed

+70
-45
lines changed

10 files changed

+70
-45
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: breaking
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: elasticsearchexporter
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Use go-elasticsearch/v8, require minimum version of ES 7.17.x or 8.x
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [32454]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: [user]

exporter/elasticsearchexporter/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
This exporter supports sending logs, metrics and traces to [Elasticsearch](https://www.elastic.co/elasticsearch).
1818

19+
The Exporter is API-compatible with Elasticsearch 7.17.x and 8.x. Certain features of the exporter,
20+
such as the `otel` mapping mode, may require newer versions of Elasticsearch. Limited effort will
21+
be made to support EOL versions of Elasticsearch -- see https://www.elastic.co/support/eol.
22+
1923
## Configuration options
2024

2125
Exactly one of the following settings is required:

exporter/elasticsearchexporter/bulkindexer.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
"time"
1616

1717
"github.com/elastic/go-docappender/v2"
18-
"github.com/elastic/go-elasticsearch/v7"
18+
"github.com/elastic/go-elasticsearch/v8/esapi"
1919
"go.opentelemetry.io/collector/config/configcompression"
2020
"go.uber.org/zap"
2121
)
@@ -55,14 +55,14 @@ type bulkIndexerSession interface {
5555

5656
const defaultMaxRetries = 2
5757

58-
func newBulkIndexer(logger *zap.Logger, client *elasticsearch.Client, config *Config) (bulkIndexer, error) {
58+
func newBulkIndexer(logger *zap.Logger, client esapi.Transport, config *Config) (bulkIndexer, error) {
5959
if config.Batcher.Enabled != nil {
6060
return newSyncBulkIndexer(logger, client, config), nil
6161
}
6262
return newAsyncBulkIndexer(logger, client, config)
6363
}
6464

65-
func bulkIndexerConfig(client *elasticsearch.Client, config *Config) docappender.BulkIndexerConfig {
65+
func bulkIndexerConfig(client esapi.Transport, config *Config) docappender.BulkIndexerConfig {
6666
var maxDocRetries int
6767
if config.Retry.Enabled {
6868
maxDocRetries = defaultMaxRetries
@@ -84,7 +84,7 @@ func bulkIndexerConfig(client *elasticsearch.Client, config *Config) docappender
8484
}
8585
}
8686

87-
func newSyncBulkIndexer(logger *zap.Logger, client *elasticsearch.Client, config *Config) *syncBulkIndexer {
87+
func newSyncBulkIndexer(logger *zap.Logger, client esapi.Transport, config *Config) *syncBulkIndexer {
8888
return &syncBulkIndexer{
8989
config: bulkIndexerConfig(client, config),
9090
flushTimeout: config.Timeout,
@@ -176,7 +176,7 @@ func (s *syncBulkIndexerSession) Flush(ctx context.Context) error {
176176
}
177177
}
178178

179-
func newAsyncBulkIndexer(logger *zap.Logger, client *elasticsearch.Client, config *Config) (*asyncBulkIndexer, error) {
179+
func newAsyncBulkIndexer(logger *zap.Logger, client esapi.Transport, config *Config) (*asyncBulkIndexer, error) {
180180
numWorkers := config.NumWorkers
181181
if numWorkers == 0 {
182182
numWorkers = runtime.NumCPU()

exporter/elasticsearchexporter/bulkindexer_test.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
"testing"
1414
"time"
1515

16-
"github.com/elastic/go-elasticsearch/v7"
16+
"github.com/elastic/go-elasticsearch/v8"
1717
"github.com/stretchr/testify/assert"
1818
"github.com/stretchr/testify/require"
1919
"go.opentelemetry.io/collector/config/confighttp"
@@ -293,15 +293,11 @@ func TestAsyncBulkIndexer_logRoundTrip(t *testing.T) {
293293
runBulkIndexerOnce(t, &tt.config, client)
294294

295295
records := logObserver.AllUntimed()
296-
assert.Len(t, records, 2)
296+
require.Len(t, records, 1)
297297

298-
assert.Equal(t, "/", records[0].ContextMap()["path"])
299-
assert.Nil(t, records[0].ContextMap()["request_body"])
298+
assert.Equal(t, "/_bulk", records[0].ContextMap()["path"])
299+
assert.Equal(t, "{\"create\":{\"_index\":\"foo\"}}\n{\"foo\": \"bar\"}\n", records[0].ContextMap()["request_body"])
300300
assert.JSONEq(t, successResp, records[0].ContextMap()["response_body"].(string))
301-
302-
assert.Equal(t, "/_bulk", records[1].ContextMap()["path"])
303-
assert.Equal(t, "{\"create\":{\"_index\":\"foo\"}}\n{\"foo\": \"bar\"}\n", records[1].ContextMap()["request_body"])
304-
assert.JSONEq(t, successResp, records[1].ContextMap()["response_body"].(string))
305301
})
306302
}
307303
}
@@ -327,8 +323,9 @@ func TestSyncBulkIndexer_flushBytes(t *testing.T) {
327323
reqCnt.Add(1)
328324
}
329325
return &http.Response{
330-
Header: http.Header{"X-Elastic-Product": []string{"Elasticsearch"}},
331-
Body: io.NopCloser(strings.NewReader(successResp)),
326+
Header: http.Header{"X-Elastic-Product": []string{"Elasticsearch"}},
327+
Body: io.NopCloser(strings.NewReader(successResp)),
328+
StatusCode: http.StatusOK,
332329
}, nil
333330
},
334331
}})

exporter/elasticsearchexporter/esclient.go

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ package elasticsearchexporter // import "github.com/open-telemetry/opentelemetry
55

66
import (
77
"context"
8+
"errors"
89
"io"
910
"net/http"
1011
"time"
1112

1213
"github.com/cenkalti/backoff/v4"
13-
"github.com/elastic/go-elasticsearch/v7"
14+
elasticsearchv8 "github.com/elastic/go-elasticsearch/v8"
15+
"github.com/elastic/go-elasticsearch/v8/esapi"
1416
"github.com/klauspost/compress/gzip"
1517
"go.opentelemetry.io/collector/component"
1618
"go.uber.org/zap"
@@ -82,14 +84,14 @@ func (cl *clientLogger) ResponseBodyEnabled() bool {
8284
return cl.logResponseBody
8385
}
8486

85-
// newElasticsearchClient returns a new elasticsearch.Client
87+
// newElasticsearchClient returns a new esapi.Transport.
8688
func newElasticsearchClient(
8789
ctx context.Context,
8890
config *Config,
8991
host component.Host,
9092
telemetry component.TelemetrySettings,
9193
userAgent string,
92-
) (*elasticsearch.Client, error) {
94+
) (esapi.Transport, error) {
9395
httpClient, err := config.ClientConfig.ToClient(ctx, host, telemetry)
9496
if err != nil {
9597
return nil, err
@@ -105,18 +107,13 @@ func newElasticsearchClient(
105107
return nil, err
106108
}
107109

108-
esLogger := clientLogger{
110+
esLogger := &clientLogger{
109111
Logger: telemetry.Logger,
110112
logRequestBody: config.LogRequestBody,
111113
logResponseBody: config.LogResponseBody,
112114
}
113115

114-
maxRetries := defaultMaxRetries
115-
if config.Retry.MaxRetries != 0 {
116-
maxRetries = config.Retry.MaxRetries
117-
}
118-
119-
return elasticsearch.NewClient(elasticsearch.Config{
116+
return elasticsearchv8.NewClient(elasticsearchv8.Config{
120117
Transport: httpClient.Transport,
121118

122119
// configure connection setup
@@ -127,11 +124,12 @@ func newElasticsearchClient(
127124
Header: headers,
128125

129126
// configure retry behavior
130-
RetryOnStatus: config.Retry.RetryOnStatus,
131-
DisableRetry: !config.Retry.Enabled,
132-
EnableRetryOnTimeout: config.Retry.Enabled,
133-
// RetryOnError: retryOnError, // should be used from esclient version 8 onwards
134-
MaxRetries: maxRetries,
127+
RetryOnStatus: config.Retry.RetryOnStatus,
128+
DisableRetry: !config.Retry.Enabled,
129+
RetryOnError: func(_ *http.Request, err error) bool {
130+
return !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded)
131+
},
132+
MaxRetries: min(defaultMaxRetries, config.Retry.MaxRetries),
135133
RetryBackoff: createElasticsearchBackoffFunc(&config.Retry),
136134

137135
// configure sniffing
@@ -141,7 +139,11 @@ func newElasticsearchClient(
141139
// configure internal metrics reporting and logging
142140
EnableMetrics: false, // TODO
143141
EnableDebugLogger: false, // TODO
144-
Logger: &esLogger,
142+
Instrumentation: elasticsearchv8.NewOpenTelemetryInstrumentation(
143+
telemetry.TracerProvider,
144+
false, /* captureSearchBody */
145+
),
146+
Logger: esLogger,
145147
})
146148
}
147149

exporter/elasticsearchexporter/exporter_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,6 +1881,7 @@ func TestExporterBatcher(t *testing.T) {
18811881
exporter := newUnstartedTestLogsExporter(t, "http://testing.invalid", func(cfg *Config) {
18821882
cfg.Batcher = BatcherConfig{Enabled: &batcherEnabled}
18831883
cfg.Auth = &configauth.Authentication{AuthenticatorID: testauthID}
1884+
cfg.Retry.Enabled = false
18841885
})
18851886
err := exporter.Start(context.Background(), &mockHost{
18861887
extensions: map[component.ID]component.Component{

exporter/elasticsearchexporter/go.mod

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ go 1.22.0
44

55
require (
66
github.com/cenkalti/backoff/v4 v4.3.0
7-
github.com/elastic/go-docappender/v2 v2.4.0
8-
github.com/elastic/go-elasticsearch/v7 v7.17.10
7+
github.com/elastic/go-docappender/v2 v2.3.3
8+
github.com/elastic/go-elasticsearch/v8 v8.17.0
99
github.com/elastic/go-structform v0.0.12
1010
github.com/klauspost/compress v1.17.11
1111
github.com/lestrrat-go/strftime v1.1.0
@@ -34,7 +34,6 @@ require (
3434
github.com/armon/go-radix v1.0.0 // indirect
3535
github.com/davecgh/go-spew v1.1.1 // indirect
3636
github.com/elastic/elastic-transport-go/v8 v8.6.0 // indirect
37-
github.com/elastic/go-elasticsearch/v8 v8.17.0 // indirect
3837
github.com/elastic/go-sysinfo v1.7.1 // indirect
3938
github.com/elastic/go-windows v1.0.1 // indirect
4039
github.com/felixge/httpsnoop v1.0.4 // indirect

exporter/elasticsearchexporter/go.sum

Lines changed: 6 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

exporter/elasticsearchexporter/integrationtest/go.mod

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ require (
4646
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
4747
github.com/ebitengine/purego v0.8.2 // indirect
4848
github.com/elastic/elastic-transport-go/v8 v8.6.0 // indirect
49-
github.com/elastic/go-elasticsearch/v7 v7.17.10 // indirect
5049
github.com/elastic/go-elasticsearch/v8 v8.17.0 // indirect
5150
github.com/elastic/go-grok v0.3.1 // indirect
5251
github.com/elastic/go-structform v0.0.12 // indirect

exporter/elasticsearchexporter/integrationtest/go.sum

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)