Skip to content

Instantly share code, notes, and snippets.

@sgratzl
Last active January 25, 2021 09:41
Show Gist options
  • Save sgratzl/87912e985177a47d75e400fbd3d4f4ef to your computer and use it in GitHub Desktop.
Save sgratzl/87912e985177a47d75e400fbd3d4f4ef to your computer and use it in GitHub Desktop.
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