Skip to content

Commit 8a2724a

Browse files
authored
metricbeat: add integration TestIndexTotalFieldsLimitNotReached (#41698)
The new integration test TestIndexTotalFieldsLimitNotReached ensures events with at least 500 new dynamically mapped fields can be ingested.
1 parent 88b0f16 commit 8a2724a

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
2+
// or more contributor license agreements. Licensed under the Elastic License;
3+
// you may not use this file except in compliance with the Elastic License.
4+
5+
//go:build integration
6+
7+
package integration
8+
9+
import (
10+
"bytes"
11+
"context"
12+
"encoding/json"
13+
"fmt"
14+
"io"
15+
"net/http"
16+
"strings"
17+
"testing"
18+
"time"
19+
20+
"github.com/stretchr/testify/assert"
21+
"github.com/stretchr/testify/require"
22+
23+
"github.com/elastic/beats/v7/libbeat/tests/integration"
24+
"github.com/elastic/beats/v7/libbeat/version"
25+
)
26+
27+
func TestIndexTotalFieldsLimitNotReached(t *testing.T) {
28+
cfg := `
29+
metricbeat:
30+
logging:
31+
level: debug
32+
metricbeat.config.modules:
33+
path: ${path.config}/modules.d/*.yml
34+
reload.enabled: false
35+
`
36+
metricbeat := integration.NewBeat(t, "metricbeat", "../../metricbeat.test")
37+
metricbeat.WriteConfigFile(cfg)
38+
esURL := integration.GetESURL(t, "http")
39+
kURL, _ := integration.GetKibana(t)
40+
41+
ver, _, _ := strings.Cut(version.GetDefaultVersion(), "-")
42+
index := "metricbeat-" + ver
43+
44+
dataStreamURL, err := integration.FormatDatastreamURL(t, esURL, index)
45+
require.NoError(t, err)
46+
templateURL, err := integration.FormatIndexTemplateURL(t, esURL, index)
47+
require.NoError(t, err)
48+
policyURL, err := integration.FormatPolicyURL(t, esURL, index)
49+
cleanUpES := func() {
50+
_, _, err := integration.HttpDo(t, http.MethodDelete, dataStreamURL)
51+
require.NoErrorf(t, err, "cleanup failed: could not remove datastream %s", index)
52+
_, _, err = integration.HttpDo(t, http.MethodDelete, templateURL)
53+
require.NoErrorf(t, err, "cleanup failed: could not remove index template %s", index)
54+
_, _, err = integration.HttpDo(t, http.MethodDelete, policyURL)
55+
require.NoErrorf(t, err, "cleanup failed: could not remove ilm policy %s", index)
56+
}
57+
// ensure no datastream/index template/ilm policy is set before running the test
58+
cleanUpES()
59+
t.Cleanup(cleanUpES)
60+
61+
metricbeat.Start("setup",
62+
"--index-management",
63+
"-E", "setup.kibana.protocol=http",
64+
"-E", "setup.kibana.host="+kURL.Hostname(),
65+
"-E", "setup.kibana.port="+kURL.Port(),
66+
"-E", "output.elasticsearch.protocol=http",
67+
"-E", "output.elasticsearch.hosts=['"+esURL.String()+"']")
68+
procState, err := metricbeat.Process.Wait()
69+
require.NoError(t, err, "metricbeat setup failed")
70+
require.Equalf(t, 0, procState.ExitCode(),
71+
"metricbeat setup failed: incorrect exit code: %d", procState.ExitCode())
72+
73+
// generate an event with dynamically mapped fields
74+
fields := map[string]string{}
75+
totalFields := 500
76+
for i := range totalFields {
77+
fields[fmt.Sprintf("a-label-%d", i)] = fmt.Sprintf("some-value-%d", i)
78+
}
79+
event, err := json.Marshal(map[string]any{
80+
"@timestamp": time.Now().Format(time.RFC3339),
81+
// 'kubernetes.labels.*' is a dynamically mapped field
82+
"kubernetes.labels": fields,
83+
})
84+
require.NoError(t, err, "could not marshal event to send to ES")
85+
86+
endpoint := fmt.Sprintf("%s/%s/_doc", esURL.String(), index)
87+
88+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
89+
defer cancel()
90+
91+
r, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint, bytes.NewBuffer(event))
92+
require.NoError(t, err, "could not create request to send event to ES")
93+
r.Header.Set("Content-Type", "application/json")
94+
95+
resp, err := http.DefaultClient.Do(r)
96+
require.NoError(t, err, "could not send request to send event to ES")
97+
defer resp.Body.Close()
98+
99+
failuremsg := fmt.Sprintf("failed to ingest events with %d new fields. If this test fails it likely means the current `index.mapping.total_fields.limit` for metricbeat index (%s) is close to be reached. Check the logs to see why the event was not ingested", totalFields, index)
100+
if !assert.Equal(t, http.StatusCreated, resp.StatusCode, failuremsg) {
101+
t.Logf("event sent: %s", string(event))
102+
103+
respBody, err := io.ReadAll(resp.Body)
104+
require.NoError(t, err, "could not read response body")
105+
t.Logf("ES ingest event reponse: %s", string(respBody))
106+
}
107+
}

0 commit comments

Comments
 (0)