Если в своей работе вы используете систему сбора, анализа и обработки машинных данных Splunk, то рано или поздно вы столкнетесь с проблемой визуализации этих данных и, скорее всего, инструментов, доступных из коробки, вам будет недостаточно. Вы захотите гибкости в вопросах построения и визуализации UI любой сложности, при этом с возможностью использования доступных от сообщества библиотек и фреймворков.
В этой статье я поделюсь своим опытом создания дашбордов в Splunk, которые будут отвечать любым требованиям к сложности UI и значительно расширят набор доступных к использованию инструментов.
Предыстория
В свое время, столкнувшись именно с такой задачей, я начал поиск ее решения. Использование доступных мне на тот момент технологий, а именно node.js и react, в совокупности с пониманием, что это даст мне возможность построить нужную мне логику обработки данных, гибко визуализировать и интерпретировать их в любом виде, выстраивая интерфейс любой сложности, предопределило направление моего поиска.
Я начал свой ресёрч с тематических ресурсов и форумов, искал решения интеграции standalone react приложения в систему. Все это не дало особых результатов, форумы Splunk сообщества лишь ограничивались предположениями, что это сделать конечно же можно, но готовых решений не было.
Довольно быстро я понял, что придется искать способ интеграции системы с react приложением самостоятельно и при этом, одним из ключевых требований была необходимость осуществлять запросы непосредственно из react приложения к движку Splunk с его гибким и довольно мощным языком запросов SPL. И решение было найдено.
Решение
Когда мы создаем кастомные dashboard в Splunk мы должны структурировать наш проект в соответствии с требованиями системы.
Точкой входа в приложение может являться файл index.js в папке соответствующего Splunk приложения по относительному пути
appserver/static
О чем необходимо сообщить в инициализирующем xml файле на этапе создании дашборда, например:
<dashboard script="index.js" stylesheet='app.css' theme="dark" hideEdit="true">
<label>React</label>
<row>
<panel>
<html>
<div id="root"/>
</html>
</panel>
</row>
</dashboard>
Соответствующий файл входа в приложение должен использовать модульную систему AMD (Asynchronous Module Definition), он, собственно, и подгружается в систему с помощью использования небезизвестной библиотеки require.js, предоставляемой из недр Splunk.
Когда происходит загрузка index.js файла, в вызове require передаются необходимые для работы нашего приложения зависимости, а именно те ключевые Splunk библиотеки, которые и позволят нам осуществлять SPL запросы прямо из нашего приложения, и, что важно, само наше собранное в результирующий бандл react приложение.
Пример кода index.js может выглядеть следующим образом:
require([
"splunkjs/mvc/searchmanager",
// require our bundle js file
"/static/app/reactapp/dist/index_bundle.js",
], function (SearchManager, ReactApp) {
// Start our React.js application and pass props into it
ReactApp.start({
SearchManager,
});
});
SearchManager в нашем случае это именно та зависимость, которая позволит нам делать SPL запросы приямо из нашего react приложения, а ReactApp — это объект, экспортируемый из нашего приложения с единственным методом start, задача которого примонтировать и запустить наше приложение.
Реализация этой части приложения проста и не затейлива:
const React = require('react');
const ReactDOM = require('react-dom');
const App = require('./components/App').default;
module.exports = {
start: function (props) {
ReactDOM.render(
<App props={props} />,
document.getElementById('root')
);
}
};
Именно здесь мы пробрасываем в качестве пропсов наш SearchManager (и возможно другие зависимости, если подключили их на предыдущем этапе) дальше в приложение.
На данном этапе важно правильно настроить наш webpack.config.js файл, указать, что итоговый бандл должнен представлять собой AMD модуль и настроить соответствующие лоадеры для корректной генерации результирующей сборки.
Пример настроек можно посмотреть здесь.
Ну а дальше все просто. Пишем наше react приложение, как мы привыкли это делать, используя любые доступные инструменты.
Предварительно конечно необходимо получить сами данные, которые мы собираемся визуализировать, и сделать это можно с помощью SearchManager, который мы заблаговременно доставили до нашего приложения.
Выглядеть это может примерно так:
componentDidMount() {
const newSearch = new this.state.searchManager({
id: "new_search",
earliest_time: "-2d@d",
latest_time: "now",
preview: false,
cache: false,
search: `index="someone_indexer"` // SPL query
});
const search = newSearch.data("preview", {
count: 0,
output_mode: "json_rows"
});
search.on("data", () => {
this.setState({ searchResult: search.data().rows });
});
}
В качестве заключения
Подобный подход позволяет довольно гибко решать задачи, связанные с необходимостью визуализации различных метрик и машинных логов, при этом ни сколько не ограничивая себя стандартными инструментами, предоставляемыми Splunk из коробки.
Появляется возможность проектировать UI любой сложности, подключать, например, роутинг или менеджер управления состоянием приложения (aka Redux).
Проект с примером настройки приложения и полным кодом можно посмотреть по ссылке.