Skip to content

Commit c222631

Browse files
author
Hendrik Muhs
authored
forward audits to logs (#52394)
audit messages are stored in the notifications index, so audit information is lost for integration tests. This change forwards audit messages to logs, so they can help to debug issues. relates: #51627
1 parent a7ddbcf commit c222631

File tree

2 files changed

+138
-57
lines changed

2 files changed

+138
-57
lines changed

x-pack/plugin/transform/qa/multi-node-tests/src/test/java/org/elasticsearch/xpack/transform/integration/TransformIntegTestCase.java

Lines changed: 99 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66

77
package org.elasticsearch.xpack.transform.integration;
88

9+
import org.apache.logging.log4j.Level;
910
import org.elasticsearch.action.admin.cluster.node.tasks.list.ListTasksRequest;
1011
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
1112
import org.elasticsearch.action.bulk.BulkRequest;
1213
import org.elasticsearch.action.bulk.BulkResponse;
1314
import org.elasticsearch.action.index.IndexRequest;
15+
import org.elasticsearch.action.search.SearchRequest;
16+
import org.elasticsearch.action.search.SearchResponse;
1417
import org.elasticsearch.client.RequestOptions;
1518
import org.elasticsearch.client.RestHighLevelClient;
1619
import org.elasticsearch.client.core.AcknowledgedResponse;
@@ -48,12 +51,17 @@
4851
import org.elasticsearch.common.xcontent.XContentHelper;
4952
import org.elasticsearch.common.xcontent.XContentParser;
5053
import org.elasticsearch.common.xcontent.XContentType;
54+
import org.elasticsearch.index.query.MatchAllQueryBuilder;
5155
import org.elasticsearch.index.query.QueryBuilder;
5256
import org.elasticsearch.index.query.QueryBuilders;
57+
import org.elasticsearch.search.SearchHit;
5358
import org.elasticsearch.search.SearchModule;
5459
import org.elasticsearch.search.aggregations.AggregatorFactories;
5560
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
61+
import org.elasticsearch.search.builder.SearchSourceBuilder;
62+
import org.elasticsearch.search.sort.SortOrder;
5663
import org.elasticsearch.test.rest.ESRestTestCase;
64+
import org.joda.time.Instant;
5765

5866
import java.io.IOException;
5967
import java.nio.charset.StandardCharsets;
@@ -62,6 +70,7 @@
6270
import java.util.Collections;
6371
import java.util.HashMap;
6472
import java.util.List;
73+
import java.util.Locale;
6574
import java.util.Map;
6675
import java.util.concurrent.TimeUnit;
6776

@@ -73,10 +82,36 @@ abstract class TransformIntegTestCase extends ESRestTestCase {
7382
private Map<String, TransformConfig> transformConfigs = new HashMap<>();
7483

7584
protected void cleanUp() throws IOException {
85+
logAudits();
7686
cleanUpTransforms();
7787
waitForPendingTasks();
7888
}
7989

90+
private void logAudits() throws IOException {
91+
RestHighLevelClient restClient = new TestRestHighLevelClient();
92+
93+
// using '*' to make this lenient and do not fail if the audit index does not exist
94+
SearchRequest searchRequest = new SearchRequest(".transform-notifications-*");
95+
searchRequest.source(new SearchSourceBuilder().query(new MatchAllQueryBuilder()).size(100).sort("timestamp", SortOrder.ASC));
96+
97+
restClient.indices().refresh(new RefreshRequest(searchRequest.indices()), RequestOptions.DEFAULT);
98+
99+
SearchResponse searchResponse = restClient.search(searchRequest, RequestOptions.DEFAULT);
100+
101+
for (SearchHit hit : searchResponse.getHits()) {
102+
Map<String, Object> source = hit.getSourceAsMap();
103+
String level = (String) source.getOrDefault("level", "info");
104+
logger.log(
105+
Level.getLevel(level.toUpperCase(Locale.ROOT)),
106+
"Transform audit: [{}] [{}] [{}] [{}]",
107+
Instant.ofEpochMilli((long) source.getOrDefault("timestamp", 0)),
108+
source.getOrDefault("transform_id", "n/a"),
109+
source.getOrDefault("message", "n/a"),
110+
source.getOrDefault("node_name", "n/a")
111+
);
112+
}
113+
}
114+
80115
protected void cleanUpTransforms() throws IOException {
81116
for (TransformConfig config : transformConfigs.values()) {
82117
stopTransform(config.getId());
@@ -89,10 +124,8 @@ protected StopTransformResponse stopTransform(String id) throws IOException {
89124
return stopTransform(id, true, null, false);
90125
}
91126

92-
protected StopTransformResponse stopTransform(String id,
93-
boolean waitForCompletion,
94-
TimeValue timeout,
95-
boolean waitForCheckpoint) throws IOException {
127+
protected StopTransformResponse stopTransform(String id, boolean waitForCompletion, TimeValue timeout, boolean waitForCheckpoint)
128+
throws IOException {
96129
RestHighLevelClient restClient = new TestRestHighLevelClient();
97130
return restClient.transform()
98131
.stopTransform(new StopTransformRequest(id, waitForCompletion, timeout, waitForCheckpoint), RequestOptions.DEFAULT);
@@ -105,8 +138,7 @@ protected StartTransformResponse startTransform(String id, RequestOptions option
105138

106139
protected AcknowledgedResponse deleteTransform(String id) throws IOException {
107140
RestHighLevelClient restClient = new TestRestHighLevelClient();
108-
AcknowledgedResponse response =
109-
restClient.transform().deleteTransform(new DeleteTransformRequest(id), RequestOptions.DEFAULT);
141+
AcknowledgedResponse response = restClient.transform().deleteTransform(new DeleteTransformRequest(id), RequestOptions.DEFAULT);
110142
if (response.isAcknowledged()) {
111143
transformConfigs.remove(id);
112144
}
@@ -118,8 +150,7 @@ protected AcknowledgedResponse putTransform(TransformConfig config, RequestOptio
118150
throw new IllegalArgumentException("transform [" + config.getId() + "] is already registered");
119151
}
120152
RestHighLevelClient restClient = new TestRestHighLevelClient();
121-
AcknowledgedResponse response =
122-
restClient.transform().putTransform(new PutTransformRequest(config), options);
153+
AcknowledgedResponse response = restClient.transform().putTransform(new PutTransformRequest(config), options);
123154
if (response.isAcknowledged()) {
124155
transformConfigs.put(config.getId(), config);
125156
}
@@ -141,30 +172,33 @@ protected void waitUntilCheckpoint(String id, long checkpoint) throws Exception
141172
}
142173

143174
protected void waitUntilCheckpoint(String id, long checkpoint, TimeValue waitTime) throws Exception {
144-
assertBusy(() ->
145-
assertEquals(checkpoint, getTransformStats(id)
146-
.getTransformsStats()
147-
.get(0)
148-
.getCheckpointingInfo()
149-
.getLast()
150-
.getCheckpoint()),
175+
assertBusy(
176+
() -> assertEquals(
177+
checkpoint,
178+
getTransformStats(id).getTransformsStats().get(0).getCheckpointingInfo().getLast().getCheckpoint()
179+
),
151180
waitTime.getMillis(),
152-
TimeUnit.MILLISECONDS);
181+
TimeUnit.MILLISECONDS
182+
);
153183
}
154184

155-
protected DateHistogramGroupSource createDateHistogramGroupSourceWithFixedInterval(String field,
156-
DateHistogramInterval interval,
157-
ZoneId zone) {
185+
protected DateHistogramGroupSource createDateHistogramGroupSourceWithFixedInterval(
186+
String field,
187+
DateHistogramInterval interval,
188+
ZoneId zone
189+
) {
158190
DateHistogramGroupSource.Builder builder = DateHistogramGroupSource.builder()
159191
.setField(field)
160192
.setInterval(new DateHistogramGroupSource.FixedInterval(interval))
161193
.setTimeZone(zone);
162194
return builder.build();
163195
}
164196

165-
protected DateHistogramGroupSource createDateHistogramGroupSourceWithCalendarInterval(String field,
166-
DateHistogramInterval interval,
167-
ZoneId zone) {
197+
protected DateHistogramGroupSource createDateHistogramGroupSourceWithCalendarInterval(
198+
String field,
199+
DateHistogramInterval interval,
200+
ZoneId zone
201+
) {
168202
DateHistogramGroupSource.Builder builder = DateHistogramGroupSource.builder()
169203
.setField(field)
170204
.setInterval(new DateHistogramGroupSource.CalendarInterval(interval))
@@ -188,35 +222,38 @@ protected AggregationConfig createAggConfig(AggregatorFactories.Builder aggregat
188222
return new AggregationConfig(aggregations);
189223
}
190224

191-
protected PivotConfig createPivotConfig(Map<String, SingleGroupSource> groups,
192-
AggregatorFactories.Builder aggregations) throws Exception {
225+
protected PivotConfig createPivotConfig(Map<String, SingleGroupSource> groups, AggregatorFactories.Builder aggregations)
226+
throws Exception {
193227
return createPivotConfig(groups, aggregations, null);
194228
}
195229

196-
protected PivotConfig createPivotConfig(Map<String, SingleGroupSource> groups,
197-
AggregatorFactories.Builder aggregations,
198-
Integer size) throws Exception {
230+
protected PivotConfig createPivotConfig(Map<String, SingleGroupSource> groups, AggregatorFactories.Builder aggregations, Integer size)
231+
throws Exception {
199232
PivotConfig.Builder builder = PivotConfig.builder()
200233
.setGroups(createGroupConfig(groups))
201234
.setAggregationConfig(createAggConfig(aggregations))
202235
.setMaxPageSearchSize(size);
203236
return builder.build();
204237
}
205238

206-
protected TransformConfig createTransformConfig(String id,
207-
Map<String, SingleGroupSource> groups,
208-
AggregatorFactories.Builder aggregations,
209-
String destinationIndex,
210-
String... sourceIndices) throws Exception {
239+
protected TransformConfig createTransformConfig(
240+
String id,
241+
Map<String, SingleGroupSource> groups,
242+
AggregatorFactories.Builder aggregations,
243+
String destinationIndex,
244+
String... sourceIndices
245+
) throws Exception {
211246
return createTransformConfig(id, groups, aggregations, destinationIndex, QueryBuilders.matchAllQuery(), sourceIndices);
212247
}
213248

214-
protected TransformConfig.Builder createTransformConfigBuilder(String id,
215-
Map<String, SingleGroupSource> groups,
216-
AggregatorFactories.Builder aggregations,
217-
String destinationIndex,
218-
QueryBuilder queryBuilder,
219-
String... sourceIndices) throws Exception {
249+
protected TransformConfig.Builder createTransformConfigBuilder(
250+
String id,
251+
Map<String, SingleGroupSource> groups,
252+
AggregatorFactories.Builder aggregations,
253+
String destinationIndex,
254+
QueryBuilder queryBuilder,
255+
String... sourceIndices
256+
) throws Exception {
220257
return TransformConfig.builder()
221258
.setId(id)
222259
.setSource(SourceConfig.builder().setIndex(sourceIndices).setQueryConfig(createQueryConfig(queryBuilder)).build())
@@ -226,12 +263,14 @@ protected TransformConfig.Builder createTransformConfigBuilder(String id,
226263
.setDescription("Test transform config id: " + id);
227264
}
228265

229-
protected TransformConfig createTransformConfig(String id,
230-
Map<String, SingleGroupSource> groups,
231-
AggregatorFactories.Builder aggregations,
232-
String destinationIndex,
233-
QueryBuilder queryBuilder,
234-
String... sourceIndices) throws Exception {
266+
protected TransformConfig createTransformConfig(
267+
String id,
268+
Map<String, SingleGroupSource> groups,
269+
AggregatorFactories.Builder aggregations,
270+
String destinationIndex,
271+
QueryBuilder queryBuilder,
272+
String... sourceIndices
273+
) throws Exception {
235274
return createTransformConfigBuilder(id, groups, aggregations, destinationIndex, queryBuilder, sourceIndices).build();
236275
}
237276

@@ -272,8 +311,8 @@ protected void createReviewsIndex(String indexName, int numDocs) throws Exceptio
272311
.endObject();
273312
}
274313
builder.endObject();
275-
CreateIndexResponse response =
276-
restClient.indices().create(new CreateIndexRequest(indexName).mapping(builder), RequestOptions.DEFAULT);
314+
CreateIndexResponse response = restClient.indices()
315+
.create(new CreateIndexRequest(indexName).mapping(builder), RequestOptions.DEFAULT);
277316
assertThat(response.isAcknowledged(), is(true));
278317
}
279318

@@ -320,10 +359,14 @@ protected void createReviewsIndex(String indexName, int numDocs) throws Exceptio
320359

321360
protected Map<String, Object> toLazy(ToXContent parsedObject) throws Exception {
322361
BytesReference bytes = XContentHelper.toXContent(parsedObject, XContentType.JSON, false);
323-
try(XContentParser parser = XContentHelper.createParser(xContentRegistry(),
324-
DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
325-
bytes,
326-
XContentType.JSON)) {
362+
try (
363+
XContentParser parser = XContentHelper.createParser(
364+
xContentRegistry(),
365+
DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
366+
bytes,
367+
XContentType.JSON
368+
)
369+
) {
327370
return parser.mapOrdered();
328371
}
329372
}
@@ -349,16 +392,15 @@ protected NamedXContentRegistry xContentRegistry() {
349392

350393
@Override
351394
protected Settings restClientSettings() {
352-
final String token = "Basic " +
353-
Base64.getEncoder().encodeToString(("x_pack_rest_user:x-pack-test-password").getBytes(StandardCharsets.UTF_8));
354-
return Settings.builder()
355-
.put(ThreadContext.PREFIX + ".Authorization", token)
356-
.build();
395+
final String token = "Basic "
396+
+ Base64.getEncoder().encodeToString(("x_pack_rest_user:x-pack-test-password").getBytes(StandardCharsets.UTF_8));
397+
return Settings.builder().put(ThreadContext.PREFIX + ".Authorization", token).build();
357398
}
358399

359400
protected static class TestRestHighLevelClient extends RestHighLevelClient {
360-
private static final List<NamedXContentRegistry.Entry> X_CONTENT_ENTRIES =
361-
new SearchModule(Settings.EMPTY, Collections.emptyList()).getNamedXContents();
401+
private static final List<NamedXContentRegistry.Entry> X_CONTENT_ENTRIES = new SearchModule(Settings.EMPTY, Collections.emptyList())
402+
.getNamedXContents();
403+
362404
TestRestHighLevelClient() {
363405
super(client(), restClient -> {}, X_CONTENT_ENTRIES);
364406
}

x-pack/plugin/transform/qa/single-node-tests/src/test/java/org/elasticsearch/xpack/transform/integration/TransformRestTestCase.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.apache.http.HttpHost;
1010
import org.apache.http.entity.ContentType;
1111
import org.apache.http.entity.StringEntity;
12+
import org.apache.logging.log4j.Level;
1213
import org.elasticsearch.client.Request;
1314
import org.elasticsearch.client.RequestOptions;
1415
import org.elasticsearch.client.Response;
@@ -24,6 +25,7 @@
2425
import org.elasticsearch.test.rest.ESRestTestCase;
2526
import org.elasticsearch.xpack.core.transform.TransformField;
2627
import org.elasticsearch.xpack.core.transform.transforms.persistence.TransformInternalIndexConstants;
28+
import org.joda.time.Instant;
2729
import org.junit.After;
2830
import org.junit.AfterClass;
2931
import org.junit.BeforeClass;
@@ -32,6 +34,7 @@
3234
import java.util.Arrays;
3335
import java.util.Collections;
3436
import java.util.List;
37+
import java.util.Locale;
3538
import java.util.Map;
3639
import java.util.concurrent.TimeUnit;
3740
import java.util.stream.Collectors;
@@ -364,6 +367,7 @@ protected static void deleteTransform(String transformId) throws IOException {
364367

365368
@After
366369
public void waitForTransform() throws Exception {
370+
logAudits();
367371
if (preserveClusterUponCompletion() == false) {
368372
ensureNoInitializingShards();
369373
wipeTransforms();
@@ -468,4 +472,39 @@ protected void assertOnePivotValue(String query, double expected) throws IOExcep
468472
protected static String getTransformEndpoint() {
469473
return useDeprecatedEndpoints ? TransformField.REST_BASE_PATH_TRANSFORMS_DEPRECATED : TransformField.REST_BASE_PATH_TRANSFORMS;
470474
}
475+
476+
@SuppressWarnings("unchecked")
477+
private void logAudits() throws IOException {
478+
logger.info("writing audit messages to the log");
479+
Request searchRequest = new Request("GET", TransformInternalIndexConstants.AUDIT_INDEX + "/_search?ignore_unavailable=true");
480+
searchRequest.setJsonEntity(
481+
"{ \"size\": 100,"
482+
+ " \"sort\": ["
483+
+ " {"
484+
+ " \"timestamp\": {"
485+
+ " \"order\": \"asc\""
486+
+ " }"
487+
+ " }"
488+
+ " ] }"
489+
);
490+
491+
refreshIndex(TransformInternalIndexConstants.AUDIT_INDEX_PATTERN);
492+
493+
Response searchResponse = client().performRequest(searchRequest);
494+
Map<String, Object> searchResult = entityAsMap(searchResponse);
495+
List<Map<String, Object>> searchHits = (List<Map<String, Object>>) XContentMapValues.extractValue("hits.hits", searchResult);
496+
497+
for (Map<String, Object> hit : searchHits) {
498+
Map<String, Object> source = (Map<String, Object>) XContentMapValues.extractValue("_source", hit);
499+
String level = (String) source.getOrDefault("level", "info");
500+
logger.log(
501+
Level.getLevel(level.toUpperCase(Locale.ROOT)),
502+
"Transform audit: [{}] [{}] [{}] [{}]",
503+
Instant.ofEpochMilli((long) source.getOrDefault("timestamp", 0)),
504+
source.getOrDefault("transform_id", "n/a"),
505+
source.getOrDefault("message", "n/a"),
506+
source.getOrDefault("node_name", "n/a")
507+
);
508+
}
509+
}
471510
}

0 commit comments

Comments
 (0)