Last active
January 25, 2021 09:41
-
-
Save sgratzl/87912e985177a47d75e400fbd3d4f4ef to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
async function executeQuery(query) { | |
function sendJSON(url, body) { | |
return fetch(url, { | |
method: 'POST', | |
body: JSON.stringify(body), | |
credentials: 'same-origin', | |
headers: { | |
'kbn-version': '7.10.1', | |
'Content-Type': 'application/json' | |
} | |
}).then((r) => r.json()) | |
} | |
const url = `https://${location.hostname}/internal/search/ese`; | |
const body = { | |
params: { | |
index: "filebeat-*", | |
body: query, | |
preference: 1611562116356, | |
} | |
}; | |
const r = await sendJSON(url, body); | |
if (r.isPartial || r.isRunning) { | |
return (await sendJSON(`${url}/${r.id}`, body)).rawResponse; | |
} else { | |
return r.rawResponse; | |
} | |
} | |
function injectButton(onOpen) { | |
const parent = document.querySelector('.euiHeaderLinks__list'); | |
let button = parent.querySelector(`[data-test-subj="runCustomQuery"]`); | |
if (!button) { | |
parent.insertAdjacentHTML('beforeend', `<button class="euiButtonEmpty euiButtonEmpty--primary euiButtonEmpty--xSmall euiHeaderLink" type="button" data-test-subj="runCustomQuery"><span class="euiButtonContent euiButtonEmpty__content"><span class="euiButtonEmpty__text">Custom Query</span></span></button>`); | |
button = parent.querySelector(`[data-test-subj="runCustomQuery"]`); | |
} | |
button.onclick = onOpen; | |
} | |
function createUI() { | |
const old = document.querySelector('#custom-query'); | |
if (old) { | |
old.remove(); | |
} | |
const parent = document.querySelector('.app-wrapper'); | |
parent.style.position = 'relative'; | |
parent.firstElementChild.style.display = 'none'; | |
parent.insertAdjacentHTML('beforeend', `<div class="euiFlexGroup" style="z-index: 100; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: white" id="custom-query"> | |
<div class="euiFlexGroup euiFlexItem euiFlexGroup--directionColumn"> | |
<header style="display: flex; align-items: center"> | |
<h3 style="flex-grow: 1; margin-left: 1em;">Query</h3> | |
<button class="euiButton euiButton--primary euiSuperUpdateButton euiButton--fill" type="button"><span class="euiButtonContent euiButton__content"><span class="euiButton__text euiSuperUpdateButton__text">Execute</span></span></button> | |
</header> | |
<textarea id="tx-source" class="euiFlexItem"> | |
{ | |
size: 10, | |
//aggs: { | |
// 2: { | |
// date_histogram: { field: "@timestamp", fixed_interval: "30s", time_zone: "Europe/Berlin", min_doc_count: 1 }, | |
// }, | |
//}, | |
_source: ["url.original"], | |
query: { | |
bool: { | |
must: [], | |
filter: [ | |
{ match_all: {} }, | |
{ | |
range: { | |
"@timestamp": { | |
gte: "2021-01-25T07:56:17.530Z", | |
lte: "2021-01-25T08:11:17.531Z", | |
format: "strict_date_optional_time", | |
}, | |
}, | |
}, | |
], | |
should: [], | |
must_not: [], | |
}, | |
}, | |
} | |
</textarea> | |
</div> | |
<div class="euiFlexGroup euiFlexItem euiFlexGroup--directionColumn"> | |
<header style="display: flex; align-items: center"> | |
<h3 style="flex-grow: 1; margin-left: 1em;">Result</h3> | |
<button class="euiButton euiSuperUpdateButton clear-button euiButton--fill" type="button"><span class="euiButtonContent euiButton__content"><span class="euiButton__text euiSuperUpdateButton__text">Clear</span></span></button> | |
</header> | |
<textarea id="tx-output" readonly class="euiFlexItem"></textarea> | |
</div> | |
</div>`); | |
const sEditor = ace.edit("tx-source"); | |
// sEditor.setTheme("ace/theme/monokai"); | |
sEditor.session.setMode('ace/mode/json'); | |
const oEditor = ace.edit("tx-output"); | |
oEditor.session.setMode('ace/mode/json'); | |
oEditor.setReadOnly(true); | |
// sEditor.setTheme("ace/theme/monokai"); | |
const root = parent.querySelector('#custom-query'); | |
root.querySelectorAll('.ace_editor').forEach((d) => d.classList.add('euiFlexItem')); | |
sEditor.resize(); | |
oEditor.resize(); | |
const executeButton = root.querySelector('.euiButton'); | |
executeButton.addEventListener('click', () => { | |
const query = sEditor.getValue(); | |
try { | |
const parsed = (new Function(`return ${query};`))(); | |
executeQuery(parsed).then((r) => { | |
oEditor.setValue(JSON.stringify(r, null, 2), 0); | |
}).catch((e) => { | |
oEditor.setValue(`Error executing query:\n\n${e.toString()}`, 0); | |
}); | |
} catch (e) { | |
oEditor.setValue(`Error parsing query:\n\n${e.toString()}`, 0); | |
} | |
}); | |
const clearButton = root.querySelector('.clear-button'); | |
clearButton.addEventListener('click', () => { | |
oEditor.setValue('', 0); | |
}); | |
return { | |
destroy: () => { | |
sEditor.destroy(); | |
oEditor.destroy(); | |
root.remove(); | |
parent.firstElementChild.style.display = ''; | |
} | |
} | |
} | |
let customUI = null; | |
injectButton(() => { | |
if (customUI) { | |
customUI.destroy(); | |
customUI = null; | |
} else { | |
customUI = createUI(); | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment