Недавно мы взглянули на визуализацию наших данных временных рядов из InfluxDB с использованием графической библиотеки plotly.js, которая предлагает более 20 различных типов диаграмм и упаковывает все так аккуратно, что пользователям легко и просто воспроизводить графики. собственного стиля и выбора. Сегодня мы рассмотрим извлечение наших данных из InfluxDB и их отображение с помощью библиотеки Rickshaw, которая, как и plotly.js, также построена на d3.js. Набор инструментов Rickshaw предлагает пользователям возможность создавать собственные интерактивные графики временных рядов, предоставляя пользователям доступ к широкому набору стилей и множеству различных элементов — средствам визуализации, легендам, наведениям и селекторам диапазона — с помощью которых можно строить свои графики.

Прежде чем мы начнем, конечно, вам нужно убедиться, что у вас есть экземпляр InfluxDB, запущенный и работающий на вашем локальном компьютере. Вот отличный сайт для настройки TICK Stack и работы на вашем компьютере — руководство Начало работы на сайте InfluxData предоставляет документацию, которая проведет вас через установку и запуск всех четырех пакетов куча. Вы также можете попробовать поэкспериментировать в режиме песочницы.

Нам нужны данные!

Теперь, чтобы визуализировать наши данные, вам сначала нужно их получить. Для этого сценария я буду запрашивать у InfluxDB через клиентскую библиотеку Node-influx статистику, которую Telegraf уже собирает о моей машине. Вы можете сделать то же самое для своей машины или, если вам захочется, вы можете подключиться и начать отслеживать любое количество собственных приложений. У Telegraf есть ряд плагинов, которые могут переводить ваши данные в линейный протокол (текстовый формат для записи точек в InfluxDB) и отправлять ваши данные прямо в базу данных.

В этом примере я буду использовать Node/Express для настройки файла сервера и запроса InfluxDB для получения данных о среднем использовании процессора. Если у вас установлен и работает полный стек TICK, вы сможете сделать то же самое. После того, как вы установите и потребуете соответствующие зависимости, вы подключитесь к своему локальному экземпляру InfluxDB и конкретной базе данных, которую вы хотите запросить. Вот как выглядит файл моего сервера:

const Influx = require('influx');
const express = require('express');
const path = require('path');
const os = require('os');
const bodyParser = require('body-parser');
const app = express();
const influx = new Influx.InfluxDB('http://127.0.0.1:8086/telegraf');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(express.static(path.join(__dirname, 'public')));
app.set('port', 3000);
influx.getMeasurements()
  .then(names => console.log('My measurement names are: ' + names.join(', ')))
  .then(() => {
    app.listen(app.get('port'), () => {
      console.log(`Listening on ${app.get('port')}.`);
    });
  })
  .catch(error => console.log({ error }));
app.get('/api/v1/usage', (request, response) => {
  influx.query(`
    select mean("usage_user") as "mean_usage_user",
    mean("usage_system") as "mean_usage_system" from cpu
    where time > now() - 1h and
    host = ${Influx.escape.stringLit(os.hostname())}
    group by time(10s)
    limit 100
    `)
    .then(result => response.status(200).json(result))
    .catch(error => response.status(500).json({ error }));
});

Вы заметите, что последний раздел кода имеет конечную точку, которая запрашивает базу данных для среднего использования процессора пользователем.

Визуализация ваших данных

Вам нужно будет настроить структуру файлов html, css и script, чтобы у вас было место для отображения ваших данных в браузере. Вам также потребуется либо установить Rickshaw и d3 в виде пакетов npm, либо добавить уменьшенные версии в заголовок документа. Ознакомьтесь с файлом ReadMe Rickshaw’s GitHub для получения дополнительной информации. Для некоторых более сложных графиков Rickshaw требуются jQuery и jQueryUI, но сегодня мы не будем усложнять. Взгляните на этот файл index.html:

<!DOCTYPE html>
<html>
 <head>
 <meta charset=”utf-8">
 <meta name=”viewport” content=”width=device-width, initial-scale=1.0">
 <meta http-equiv=”X-UA-Compatible” content=”ie=edge”>
 <link type=”text/css” rel=”stylesheet” type=”text/css” href=”styles.css”>
 <link type=”text/css” rel=”stylesheet” href=”rickshaw.min.css”>
 <script src=”d3.layout.min.js”></script>
 <script src=”d3.min.js”></script>
 <script src=”rickshaw.min.js”></script>
 <title>Visualizing Data from InfluxDB with Rickshaw</title>
 </head>
 <body>
 <header>
 <h1 class=”title”>Visualizing Your Time Series Data from InfluxDB with Rickshaw</h1>
 </header>
 <main>
 <div id=”chart-container”>
 <div class=”chart-box”>
 <div id=”y-axis”></div>
 <div id=”chart”></div>
 </div>
 <div class=”legend-box”>
 <div id=”legend”></div>
 <form id=”offset-form” class=”toggler”>
 <input type=”radio” name=”offset” id=”lines” value=”lines” checked>
 <label class=”lines” for=”lines”>lines</label><br>
 <input type=”radio” name=”offset” id=”stack” value=”zero”>
 <label class=”stack” for=”stack”>stack</label>
 </form>
 </div>
 </div>
 </main>
 <script type=”text/javascript” src=”scripts.js”></script>
 </body>
</html>

Как видите, вам нужно определить отдельные контейнеры для диаграммы, оси Y и легенды, а также опциональную возможность переключения для отображения графика в разных форматах. Разделение всех этих компонентов позволяет пользователям создавать собственное форматирование и уникальные визуализации, но также может быть немного сложно настроить все как новичку в графической игре. Я, например, сразу попытался воспроизвести вариант следующего примера и слишком быстро понял, что, наверное, лучше было бы начать сначала с туториалов Рикши.

Я отвлекся, однако. Давайте перейдем к файлу скрипта, где мы можем добавить все функции для рисования данных временного ряда InfluxDB на графике. Скопируйте и вставьте (или напечатайте для развития мышечной памяти!) следующее:

const loadData = () => {
  fetch('/api/v1/usage')
    .then( response => {
      if (response.status !== 200) {
        console.log(response);
      }
      return response;
    })
    .then(response => response.json())
    .then(parsedResponse => {
      const unpackData = (array, key) => {
        return array.map(obj => Object.assign({}, { x: Date.parse(obj['time']), y: obj[key] }))
      };
const palette = new Rickshaw.Color.Palette({ scheme: 'colorwheel' });
      const graph = new Rickshaw.Graph({
        element: document.querySelector('#chart'),
        width: 1200,
        height: 640,
        renderer: 'line',
        series: [
          {
            name: 'Mean User Usage',
            data: unpackData(parsedResponse, 'mean_usage_user'),
            color: palette.color()
          },
          {
            name: 'Mean System Usage',
            data: unpackData(parsedResponse, 'mean_usage_system'),
            color: palette.color()
          },
        ]
      });
const xAxis = new Rickshaw.Graph.Axis.Time({
        graph: graph,
        ticksTreatment: 'glow'
      });
const yAxis = new Rickshaw.Graph.Axis.Y({
        element: document.getElementById('y-axis'),
        graph: graph,
        orientation: 'left',
        tickFormat: Rickshaw.Fixtures.Number.formatKMBT,
      });
      const legend = new Rickshaw.Graph.Legend( {
        element: document.getElementById('legend'),
        graph: graph
      });
      const offsetForm = document.getElementById('offset-form');
      offsetForm.addEventListener('change', function(e) {
        const offsetMode = e.target.value;
if (offsetMode == 'lines') {
                graph.setRenderer('line');
                graph.offset = 'zero';
        } else {
                graph.setRenderer('stack');
                graph.offset = offsetMode;
        }
        graph.render();
      }, false);
return graph.render();
    })
    .catch( error => console.log(error) );
}
document.addEventListener('DOMContentLoaded', loadData);

Помимо того факта, что моя функция «loadData» слишком длинная и не несет единоличной ответственности, здесь определенно многое происходит. Давай покопаемся, а?

Сначала мы делаем вызов выборки, чтобы получить данные из InfluxDB, и, надеюсь, если наш вызов будет успешным, мы сможем затем проанализировать и изменить (распаковать) наши данные, чтобы они соответствовали формату, который требует Rickshaw. У Rickshaw есть несколько цветовых схем, из которых можно выбрать, поэтому после установки нашей цветовой палитры на «colorwheel» мы можем затем создать экземпляр нового графика Rickshaw и вставить отформатированные данные соответствующим образом.

Далее следует создание осей x и y, легенды для обозначения того, какие данные мы просматриваем, и функции переключателя для переключения формата графика между линейным графиком или графиком с накоплением (у Rickshaw есть еще несколько форматов). ). Эти необязательные надстройки, на мой взгляд, вызывают затруднения. В частности, что касается осей x и y, поскольку это график временных рядов, для меня наиболее целесообразно, чтобы они присутствовали по умолчанию, а не что-то, что нужно добавить в качестве запоздалой мысли (а затем стилизовать и расположить). более того!). Чтобы получить список возможных расширений, я бы зашел на страницу GitHub Rickshaw и потратил некоторое время на эксперименты.

Конечный продукт

Если вы перезапустите свой сервер в этот момент и перейдете к порту 3000, вы должны увидеть график особой красоты и формы. Если это выглядит не так круто, как показано ниже, не забудьте добавить немного стиля CSS, чтобы оживить его и сделать эффектнее!

Спасибо за чтение и не стесняйтесь проверить исходный код на GitHub или связаться с Twitter @mschae16, если у вас есть какие-либо вопросы. Удачной графики!

Первоначально опубликовано на www.influxdata.com 5 января 2018 г.