使用Rickshaw从InfluxDB可视化您的时序数据
作者:Margo Schaedel / 用例,开发者,产品,公司
2018年1月5日
导航到
最近,我们研究了使用图形库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需要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轴和图例定义单独的容器,并添加一个可选的切换功能,以便以不同格式渲染图形。所有这些组件的分离允许用户创建自定义格式和独特的可视化效果,但对于初学者来说,设置所有这些可能有些棘手。以我为例,我试图立即重现以下示例的版本,但很快意识到,最好是从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]。祝您图形制作愉快!