aboutsummaryrefslogtreecommitdiffstats
path: root/client/js/app/src/app/pages/querybuilder/TransformVespaTrace.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'client/js/app/src/app/pages/querybuilder/TransformVespaTrace.jsx')
-rw-r--r--client/js/app/src/app/pages/querybuilder/TransformVespaTrace.jsx345
1 files changed, 345 insertions, 0 deletions
diff --git a/client/js/app/src/app/pages/querybuilder/TransformVespaTrace.jsx b/client/js/app/src/app/pages/querybuilder/TransformVespaTrace.jsx
new file mode 100644
index 00000000000..a6981b8a521
--- /dev/null
+++ b/client/js/app/src/app/pages/querybuilder/TransformVespaTrace.jsx
@@ -0,0 +1,345 @@
+let traceID = '';
+let processes = {};
+let output = {};
+let traceStartTimestamp = 0;
+let topSpanId = '';
+let parentID = '';
+
+// Generates a random hex string of size "size"
+const genRanHex = (size) =>
+ [...Array(size)]
+ .map(() => Math.floor(Math.random() * 16).toString(16))
+ .join('');
+
+export default function transform(trace) {
+ traceID = genRanHex(32);
+ output = { data: [{ traceID: traceID, spans: [], processes: {} }] };
+ let data = output['data'][0]['spans'];
+ processes = output['data'][0]['processes'];
+ processes.p0 = { serviceName: 'Query', tags: [] };
+ let temp = trace['trace']['children'];
+ let spans = findChildren(temp);
+ traceStartTimestamp = findTraceStartTime(spans);
+ topSpanId = genRanHex(16);
+ let topSpanFirstHalf = createNewSpan(traceStartTimestamp)[0];
+ data.push(topSpanFirstHalf);
+
+ const retrieved = findLogsAndChildren(spans, topSpanFirstHalf);
+ const logs = retrieved['logs'];
+ const children = retrieved['children'];
+ traverseLogs(logs);
+ createChildren(children);
+
+ return output;
+}
+
+function findLogsAndChildren(spans, topSpanFirstHalf) {
+ let logs = [];
+ let children = [];
+ let data = output['data'][0]['spans'];
+ //let hitQuery = false;
+ //let topSpanSecondHalf = createNewSpan();
+ //let secondHalfDuration = 0;
+ //output['data'][0]['spans'].push(topSpanSecondHalf);
+ //let firstHitSecondHalf = true;
+ for (let i = 0; i < spans.length - 1; i++) {
+ if (spans[i].hasOwnProperty('children')) {
+ let a = spans[i]['timestamp'];
+ topSpanFirstHalf = createNewSpan(traceStartTimestamp + a);
+ //firstHitSecondHalf = true;
+ //topSpanSecondHalf = createNewSpan();
+ //output['data'][0]['spans'].push(topSpanSecondHalf);
+ let log = [];
+ for (let x of spans[i]['children']) {
+ if (Array.isArray(x['message'])) {
+ if (log.length > 0) {
+ // finished moving down the search chain
+ // create a new array for holding the logs that represent moving up the search chain
+ logs.push(log);
+ log = [];
+ }
+ //hitQuery = true;
+ children.push(x['message']);
+ } else {
+ // only add logs with a timestamp
+ if (x.hasOwnProperty('timestamp')) {
+ log.push(x);
+ }
+ }
+ }
+ logs.push(log);
+ } else if (
+ spans[i].hasOwnProperty('message') &&
+ spans[i].hasOwnProperty('timestamp')
+ ) {
+ let span = createNewSpan(0, 0, 'p0', spans[i]['message'], [
+ {
+ refType: 'CHILD_OF',
+ traceID: traceID,
+ spanID: topSpanFirstHalf['spanID'],
+ },
+ ])[0];
+ data.push(span);
+ span['startTime'] = traceStartTimestamp + spans[i]['timestamp'] * 1000;
+ let duration;
+ if (i === spans.length - 1) {
+ duration = 1;
+ } else {
+ duration = (spans[i + 1]['timestamp'] - spans[i]['timestamp']) * 1000;
+ duration = duration === 0 ? 1 : duration;
+ }
+ topSpanFirstHalf['duration'] = topSpanFirstHalf['duration'] + duration;
+ span['duration'] = duration;
+ // if (hitQuery) {
+ // if (firstHitSecondHalf) {
+ // secondHalfDuration = span['timestamp'] * 1000;
+ // topSpanSecondHalf['startTime'] =
+ // traceStartTimestamp + secondHalfDuration;
+ // firstHitSecondHalf = false;
+ // }
+ // topSpanSecondHalf['duration'] =
+ // span['timestamp'] * 1000 - secondHalfDuration;
+ // topSpanSecondHalf['logs'].push({
+ // timestamp: traceStartTimestamp + span['timestamp'] * 1000,
+ // fields: [{ key: 'message', type: 'string', value: span['message'] }],
+ // });
+ // } else {
+ // topSpanFirstHalf['duration'] = span['timestamp'] * 1000;
+ // topSpanFirstHalf['logs'].push({
+ // timestamp: traceStartTimestamp + span['timestamp'] * 1000,
+ // fields: [{ key: 'message', type: 'string', value: span['message'] }],
+ // });
+ // }
+ }
+ }
+ return { logs: logs, children: children };
+}
+
+function traverseLogs(logs) {
+ let first = true;
+ let data = output['data'][0]['spans'];
+ for (let log of logs) {
+ let logStartTimestamp = traceStartTimestamp + log[0]['timestamp'] * 1000;
+ let logDuration =
+ (log[log.length - 1]['timestamp'] - log[0]['timestamp']) * 1000;
+ if (logDuration === 0) {
+ logDuration = 1;
+ }
+ let spanID = genRanHex(16);
+ if (first) {
+ parentID = spanID;
+ first = false;
+ }
+ let temp = createNewSpan(
+ logStartTimestamp,
+ logDuration,
+ 'p0',
+ 'test'
+ //[{ refType: 'CHILD_OF', traceID: traceID, spanID: topSpanId }]
+ );
+ let childSpan = temp[0];
+ let childSpanID = temp[1];
+ data.push(childSpan);
+ for (let i = 0; i < log.length - 1; i++) {
+ if (log[i].hasOwnProperty('message')) {
+ let logPointStart = traceStartTimestamp + log[i]['timestamp'] * 1000;
+ let logPointDuration;
+ if (i > log.length - 1) {
+ logPointDuration = 1;
+ } else {
+ logPointDuration =
+ (log[i + 1]['timestamp'] - log[i]['timestamp']) * 1000;
+ logPointDuration = logPointDuration === 0 ? 1 : logPointDuration;
+ }
+ let logSpan = createNewSpan(
+ logPointStart,
+ logPointDuration,
+ 'p0',
+ log[i]['message'],
+ [{ refType: 'CHILD_OF', traceID: traceID, spanID: childSpanID }]
+ )[0];
+ data.push(logSpan);
+ // childSpan['logs'].push({
+ // timestamp: traceStartTimestamp + log[i]['timestamp'] * 1000,
+ // fields: [
+ // { key: 'message', type: 'string', value: log[i]['message'] },
+ // ],
+ // });
+ }
+ }
+ }
+}
+
+function createChildren(children) {
+ for (let i = 0; i < children.length; i++) {
+ let child = children[i][0];
+ let processKey = `p${i + 1}`;
+ processes[processKey] = { serviceName: `Span${i}`, tags: [] };
+ let spanID = genRanHex(16);
+ let data = output['data'][0]['spans'];
+ let startTimestamp = Date.parse(child['start_time']) * 1000;
+ let newSpan = {
+ traceID: traceID,
+ spanID: spanID,
+ operationName: `query${i}`,
+ startTime: startTimestamp,
+ duration: child['duration_ms'] * 1000,
+ references: [{ refType: 'CHILD_OF', traceID: traceID, spanID: parentID }],
+ tags: [],
+ logs: [],
+ processID: processKey,
+ };
+ data.push(newSpan);
+ let traces = child['traces'];
+ for (let k = 0; k < traces.length; k++) {
+ let trace = traces[k];
+ let traceTimestamp = trace['timestamp_ms'];
+ let events;
+ let firstEvent;
+ let duration;
+ if (trace['tag'] === 'query_execution') {
+ events = trace['threads'][0]['traces'];
+ firstEvent = events[0];
+ duration = (traceTimestamp - firstEvent['timestamp_ms']) * 1000;
+ } else if (trace['tag'] === 'query_execution_plan') {
+ events = [];
+ let nextTrace = traces[k + 1];
+ firstEvent = trace;
+ // query execution plan has no events, duration must therefore be found using the next trace
+ if (nextTrace['tag'] === 'query_execution') {
+ duration =
+ (nextTrace['threads'][0]['traces'][0]['timestamp_ms'] -
+ traceTimestamp) *
+ 1000;
+ } else {
+ duration = (nextTrace['timestamp_ms'] - traceTimestamp) * 1000;
+ }
+ } else {
+ events = trace['traces'];
+ firstEvent = events[0];
+ duration = (traceTimestamp - firstEvent['timestamp_ms']) * 1000;
+ }
+ let childSpanID = genRanHex(16);
+ let childSpan = {
+ traceID: traceID,
+ spanID: childSpanID,
+ operationName: trace['tag'],
+ startTime: startTimestamp + firstEvent['timestamp_ms'] * 1000,
+ duration: duration,
+ references: [{ refType: 'CHILD_OF', traceID: traceID, spanID: spanID }],
+ tags: [],
+ logs: [],
+ processID: processKey,
+ };
+ data.push(childSpan);
+ if (events.length > 0) {
+ for (let j = 0; j < events.length; j++) {
+ let event = events[j];
+ let eventID = genRanHex(16);
+ let eventStart = event['timestamp_ms'];
+ let operationName;
+ if (event.hasOwnProperty('event')) {
+ operationName = event['event'];
+ if (
+ operationName === 'Complete query setup' ||
+ operationName === 'MatchThread::run Done'
+ ) {
+ duration = (traceTimestamp - eventStart) * 1000;
+ } else {
+ duration = (events[j + 1]['timestamp_ms'] - eventStart) * 1000;
+ }
+ } else {
+ operationName = event['tag'];
+ duration = (events[j + 1]['timestamp_ms'] - eventStart) * 1000;
+ }
+ let eventSpan = {
+ traceID: traceID,
+ spanID: eventID,
+ operationName: operationName,
+ startTime: startTimestamp + eventStart * 1000,
+ duration: duration,
+ references: [
+ { refType: 'CHILD_OF', traceID: traceID, spanID: childSpanID },
+ ],
+ tags: [],
+ logs: [],
+ processID: processKey,
+ };
+ data.push(eventSpan);
+ }
+ }
+ }
+ }
+}
+
+function findChildren(traces) {
+ for (let trace of traces) {
+ if (trace.hasOwnProperty('children')) {
+ return trace['children'];
+ }
+ }
+}
+
+// Get an estimated start time by using the start time of the query and subtracting the current run time
+function getTraceStartTime(trace) {
+ if (Array.isArray(trace['message'])) {
+ let timestamp = Date.parse(trace['message'][0]['start_time']) * 1000;
+ let currentTimestamp = trace['timestamp'] * 1000;
+ return timestamp - currentTimestamp;
+ }
+}
+
+function findTraceStartTime(spans) {
+ let startTime = 0;
+ for (let span of spans) {
+ if (span.hasOwnProperty('children')) {
+ startTime = findTraceStartTime(span['children']);
+ } else if (span.hasOwnProperty('message')) {
+ if (Array.isArray(span['message'])) {
+ return getTraceStartTime(span);
+ }
+ }
+ if (startTime !== 0) {
+ return startTime;
+ }
+ }
+ return startTime;
+}
+
+//TODO: remove if not needed later
+function findDuration(spans) {
+ let notFound = true;
+ let duration = 0;
+ let i = spans.length - 1;
+ while (notFound && i >= 0) {
+ if (spans[i].hasOwnProperty('timestamp')) {
+ duration = spans[i]['timestamp'];
+ notFound = false;
+ } else {
+ i--;
+ }
+ }
+ return duration;
+}
+
+function createNewSpan(
+ startTime = 0,
+ duration = 0,
+ processID = 'p0',
+ operationName = 'Complete',
+ references = []
+) {
+ let spanID = genRanHex(16);
+ let newSpan = {
+ traceID: traceID,
+ spanID: spanID,
+ operationName: operationName,
+ startTime: startTime,
+ duration: duration,
+ references: references,
+ tags: [],
+ logs: [],
+ processID: processID,
+ };
+ return [newSpan, spanID];
+}