-
Notifications
You must be signed in to change notification settings - Fork 0
/
openSumoResultInXRay.js
136 lines (117 loc) · 4.07 KB
/
openSumoResultInXRay.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
try {
const attributeToExpressionMap = {
correlationId: {
buildFilter: (value) => `annotation.correlationId="${value}"`
}
}
const region = 'us-east-1';
const timeAttributeName = 'time';
function buildXRayLink(attributeConfig, attributeValue, time) {
const hourBefore = new Date(time - 60 * 60 * 1000);
const hourAfter = new Date(time + 60 * 60 * 1000);
const query = {
filter: attributeConfig.buildFilter(attributeValue),
timeRange: `${hourBefore.toISOString()}~${hourAfter.toISOString()}`
};
const params = new URLSearchParams(query);
return `https://console.aws.amazon.com/xray/home?region=${region}#/traces?${params.toString()}`;
}
function hasClassName(classname) {
return `contains(concat(" ",normalize-space(@class)," ")," ${classname} ")`;
}
function attributeContainerExpression(attributeName) {
return `./*[${hasClassName("obj-container")} and
./*[${hasClassName("prop")} and
./*[${hasClassName("key")} and
text()="${attributeName}"]
]
]`;
}
function attributeRecordExpression (attributeName) {
return `//*[${hasClassName("obj")} and
${attributeContainerExpression(attributeName)}
and
${attributeContainerExpression(timeAttributeName)}
]`;
}
function extractResultAttributeValue(container, attributeName) {
const extractExpression = `
${attributeContainerExpression(attributeName)}
/*[${hasClassName("qval")}]/span/text() `;
return JSON.parse(
document.evaluate(
extractExpression,
container,
null,
XPathResult.STRING_TYPE,
null
).stringValue
);
}
function getAttributeValueNode(container, attributeName) {
const extractExpression = `
${attributeContainerExpression(attributeName)}
/*[${hasClassName("qval")}]`;
return document
.evaluate(extractExpression, container, null, XPathResult.ANY_TYPE, null)
.iterateNext();
}
function addLinksForAttribute(attributeName, attributeConfig) {
const recordsWithAttribute = document.evaluate(
attributeRecordExpression(attributeName),
document,
null,
XPathResult.UNORDERED_NODE_ITERATOR_TYPE,
null
);
const records = [];
let matchingRecord = recordsWithAttribute.iterateNext();
while (matchingRecord) {
records.push(matchingRecord);
matchingRecord = recordsWithAttribute.iterateNext();
}
for (const record of records) {
const attributeValue = extractResultAttributeValue(
record,
attributeName
);
const time = Date.parse(extractResultAttributeValue(record, timeAttributeName));
const labelNode = getAttributeValueNode(record, attributeName);
const existingXRayLinks = labelNode.querySelectorAll(".xray-link");
for (const oldLink of existingXRayLinks) {
oldLink.remove();
}
const xrayLinkElement = document.createElement("a");
xrayLinkElement.className = "xray-link";
xrayLinkElement.href = buildXRayLink(attributeConfig, attributeValue, time);
xrayLinkElement.appendChild(document.createTextNode("(Open in X-Ray)"));
labelNode.appendChild(xrayLinkElement);
}
}
function addLinksToDocument () {
const configEntries = Object.entries(attributeToExpressionMap);
for (const [attributeName, attributeConfig] of configEntries) {
addLinksForAttribute(attributeName, attributeConfig);
}
}
addLinksToDocument();
let pendingLinks;
const observer = new MutationObserver(function(mutation) {
if (pendingLinks) {
clearTimeout(pendingLinks);
pendingLinks = null;
}
pendingLinks = setTimeout(function() {
pendingLinks = null;
observer.disconnect();
try {
addLinksToDocument();
} finally {
observer.observe(document.body, { childList: true, subtree: true });
}
}, 100);
});
observer.observe(document.body, { childList: true, subtree: true });
} catch (e) {
console.error("Failure in extension", e);
}