使用Rickshaw从InfluxDB可视化您的时序数据

导航到

最近,我们研究了使用图形库plotly.js(请参见相关文章)来可视化从InfluxDB中获取的时序数据,它提供了超过20种不同的图表类型,并且将所有功能整合得非常整齐,使用户能够轻松地复制自己风格的图表。今天,我们将探讨如何从InfluxDB中提取数据,并使用Rickshaw库来显示数据,这个库与plotly.js类似,也是基于d3.js构建的。Rickshaw工具箱为用户提供了创建自定义交互式时序图表的能力,使用户能够访问各种样式和多种不同元素——渲染器、图例、悬停和范围选择器——以构建自己的图表。

开始之前,当然需要确保您在本地计算机上有一个正在运行的InfluxDB实例。这里有一个很好的网站可以设置并运行您的TICK堆栈——名为“入门”的指南,提供了文档,可以帮助您安装并运行堆栈中的所有四个包。您还可以在沙箱模式下进行实验。

我们需要数据!

为了可视化数据,您首先需要获取一些数据。在这个场景中,我将通过Node-influx客户端库查询InfluxDB中关于我机器的统计信息,这些信息已经被Telegraf收集。您可以在自己的机器上做同样的事情,或者如果您有心情,可以连接并开始监控任何数量的应用程序。Telegraf有几个插件可以将数据转换为行协议(写入InfluxDB的基于文本的格式)并将数据直接发送到数据库。

在这个例子中,我将使用Node/Express来设置服务器文件并查询InfluxDB以获取平均CPU使用率的数据。如果您已安装并运行了完整的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 }));
});

您会注意到代码的最后部分有一个端点,用于查询数据库的平均CPU用户使用率。

数据可视化

您需要设置HTML、CSS和脚本文件结构,以便在浏览器中显示您的数据。您还需要安装Rickshaw和d3作为npm包,或者将压缩版本添加到文档的头部。请查看Rickshaw的GitHub ReadMe获取更多信息。对于一些更复杂的图表,Rickshaw需要jQueryjQueryUI,但我们将保持今天的简单性。请查看这个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轴和图例定义单独的容器,并添加一个可选的切换功能,以便以不同格式渲染图形。所有这些组件的分离允许用户创建自定义格式和独特的可视化效果,但对于初学者来说,设置所有这些可能有些棘手。以我为例,我试图立即重现以下示例的版本,但很快意识到,最好是从Rickshaw的教程开始。

<figcaption> 慢慢来,才能跑得快!</figcaption>

然而,我不太擅长这个。让我们转到脚本文件,我们可以在其中添加所有功能,以将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”函数非常长,而且没有单一职责之外,这里确实有很多事情要做。我们来深入了解一下,好吗?

我们首先进行一次fetch调用,从InfluxDB获取数据,并希望我们的调用成功后,我们可以解析和突变(解包)我们的数据,以符合Rickshaw所需的格式。Rickshaw有几个颜色方案可供选择,因此我们在将调色板设置为“colorwheel”之后,可以实例化一个新的Rickshaw图形,并相应地插入格式化的数据。

接下来是创建x轴和y轴、表示我们所查看的数据的图例以及切换功能,以在折线图和堆叠图(Rickshaw还有更多格式)之间切换。在我看来,这些可选的附加组件有些棘手。特别是在x轴和y轴方面,因为这是一个时间序列图,我认为它们应该默认存在,而不是作为事后想到的附加项(然后还要在上面进行样式和定位)!要查看可能的扩展列表,我建议您访问Rickshaw的GitHub页面并花些时间进行实验。

最终产品

如果您此时重新启动服务器并导航到端口3000,您应该会看到一个美丽而精致的图形。如果它看起来不如下面的图形那么出色,别忘了添加一些CSS风格让它更加生动!

<figcaption> 图形的可能性!</figcaption>

感谢阅读,您可以随时在GitHub上查看源代码,或者如果您有任何问题,请给我发邮件至[email protected]。祝您图形制作愉快!