feat(search): deserialize and surface attributes in detail service and OpenSearch indexing (Task 4)
DetailService deserializes attributes JSON from ExecutionRecord/ProcessorRecord and passes them to ExecutionDetail and ProcessorNode constructors. ExecutionDocument and ProcessorDoc carry attributes as a JSON string. SearchIndexer passes attributes when building documents. OpenSearchIndex includes attributes in indexed maps and deserializes them when constructing ExecutionSummary from search hits. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,11 +2,16 @@ package com.cameleer3.server.core.detail;
|
||||
|
||||
import com.cameleer3.server.core.storage.ExecutionStore;
|
||||
import com.cameleer3.server.core.storage.ExecutionStore.ProcessorRecord;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class DetailService {
|
||||
|
||||
private static final ObjectMapper JSON = new ObjectMapper();
|
||||
private static final TypeReference<Map<String, String>> STR_MAP = new TypeReference<>() {};
|
||||
|
||||
private final ExecutionStore executionStore;
|
||||
|
||||
public DetailService(ExecutionStore executionStore) {
|
||||
@@ -27,7 +32,8 @@ public class DetailService {
|
||||
exec.errorMessage(), exec.errorStacktrace(),
|
||||
exec.diagramContentHash(), roots,
|
||||
exec.inputBody(), exec.outputBody(),
|
||||
exec.inputHeaders(), exec.outputHeaders()
|
||||
exec.inputHeaders(), exec.outputHeaders(),
|
||||
parseAttributes(exec.attributes())
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -41,7 +47,8 @@ public class DetailService {
|
||||
p.processorId(), p.processorType(), p.status(),
|
||||
p.startTime(), p.endTime(),
|
||||
p.durationMs() != null ? p.durationMs() : 0L,
|
||||
p.diagramNodeId(), p.errorMessage(), p.errorStacktrace()
|
||||
p.diagramNodeId(), p.errorMessage(), p.errorStacktrace(),
|
||||
parseAttributes(p.attributes())
|
||||
));
|
||||
}
|
||||
|
||||
@@ -61,4 +68,13 @@ public class DetailService {
|
||||
}
|
||||
return roots;
|
||||
}
|
||||
|
||||
private static Map<String, String> parseAttributes(String json) {
|
||||
if (json == null || json.isBlank()) return null;
|
||||
try {
|
||||
return JSON.readValue(json, STR_MAP);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,14 +70,16 @@ public class SearchIndexer implements SearchIndexerStats {
|
||||
p.processorId(), p.processorType(), p.status(),
|
||||
p.errorMessage(), p.errorStacktrace(),
|
||||
p.inputBody(), p.outputBody(),
|
||||
p.inputHeaders(), p.outputHeaders()))
|
||||
p.inputHeaders(), p.outputHeaders(),
|
||||
p.attributes()))
|
||||
.toList();
|
||||
|
||||
searchIndex.index(new ExecutionDocument(
|
||||
exec.executionId(), exec.routeId(), exec.agentId(), exec.applicationName(),
|
||||
exec.status(), exec.correlationId(), exec.exchangeId(),
|
||||
exec.startTime(), exec.endTime(), exec.durationMs(),
|
||||
exec.errorMessage(), exec.errorStacktrace(), processorDocs));
|
||||
exec.errorMessage(), exec.errorStacktrace(), processorDocs,
|
||||
exec.attributes()));
|
||||
|
||||
indexedCount.incrementAndGet();
|
||||
lastIndexedAt = Instant.now();
|
||||
|
||||
@@ -8,12 +8,14 @@ public record ExecutionDocument(
|
||||
String status, String correlationId, String exchangeId,
|
||||
Instant startTime, Instant endTime, Long durationMs,
|
||||
String errorMessage, String errorStacktrace,
|
||||
List<ProcessorDoc> processors
|
||||
List<ProcessorDoc> processors,
|
||||
String attributes
|
||||
) {
|
||||
public record ProcessorDoc(
|
||||
String processorId, String processorType, String status,
|
||||
String errorMessage, String errorStacktrace,
|
||||
String inputBody, String outputBody,
|
||||
String inputHeaders, String outputHeaders
|
||||
String inputHeaders, String outputHeaders,
|
||||
String attributes
|
||||
) {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user