尝试使用OpenTelemetry在Node.js上进行指标收集

首先

由于之前已经使用Node.js(JavaScript)进行了OpenTelemetry的跟踪数据收集,所以这次我想总结一下关于收集计数器值等度量数据的情况。

有关OpenTelemetry的概述和跟踪数据收集的文章请参阅此处。

尝试一下

architecture.png

执行环境

    • MacOS X

 

    • node: v13.8.0

 

    • npm: v7.5.3

 

    • express: v4.17.1

 

    OpenTelemetry: v0.18

1. 创建样本配置

首先创建一个基本的示例应用程序。
示例的内容是,当访问URL时,会返回红色、蓝色或黄色中的一种,这是一个简单的逻辑。

1.1 创建样本

在项目中安装Express。

$ npm install express

创建应用程序(app.js)。

'use strict';

const express = require('express');
const app = express();
const PORT = process.env.PORT || '8080';

app.use(function(req, res, next) {
  // ランダムで色を選ぶ
  const color = ['red', 'blue', 'blue', 'yellow', 'yellow', 'yellow'];
  res.locals.color = color[Math.floor(Math.random() * color.length)];
  next();
});

app.get('/', (req, res, next) => {
  res.send(res.locals.color);
  next();
});

app.listen(parseInt(PORT, 10), () => {
  console.log(`Listening for requests on http://localhost:${PORT}`);
});

1.2 确认样本的操作

运行样本后,会开始接受来自客户端的请求,并在localhost:8080上等待。

$ node app.js
Listening for requests on http://localhost:8080

从另一个终端访问示例的URL。

$ curl localhost:8080
red

如上所述,将返回红色、蓝色或黄色中的任一种颜色。

2. Prometheus的启动

作为度量收集的准备工作,我们将构建一个Prometheus来对度量数据进行图形化。这次我们将使用Docker容器版本。

在容器启动之前,首先创建prometheus.yml文件。

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'opentelemetry'
    static_configs:
      - targets: 
        - 'host.docker.internal:9464'

targets 是 Prometheus 中收集度量数据的地方。
本次将作为主机,但从容器的角度来看,主机不是 localhost,而是 host.docker.internal(localhost 是指容器)。
需要注意的是,host.docker.internal 在 Linux 上无法使用(但在 Mac 和 Windows 上可以),因此在 Linux 环境中,请将其替换为主机的 IP 地址。

docker run \
    -d \
    -p 9090:9090 \
    -v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml \
    prom/prometheus

访问 localhost:9090,若出现 Prometheus 的图形界面,则表示启动成功。

prometheus1.png

3. OpenTelemetry的集成

现在,我们将在之前制作的示例中,集成OpenTelemetry进行指标数据收集。

3.1 安装软件包

$ npm install @opentelemetry/metrics @opentelemetry/exporter-prometheus

创建3.2 monitoring.js

我会创建一个将计数器逻辑嵌入样本中的方法。

'use strict';

const { MeterProvider } = require('@opentelemetry/metrics');
const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');

const prometheusPort = PrometheusExporter.DEFAULT_OPTIONS.port
const prometheusEndpoint = PrometheusExporter.DEFAULT_OPTIONS.endpoint
const exporter = new PrometheusExporter(
  {
    startServer: true,
  },
  () => {
    console.log(
      `prometheus scrape endpoint: http://localhost:${prometheusPort}${prometheusEndpoint}`,
    );
  },
);

const meter = new MeterProvider({
  exporter,
  interval: 1000,
}).getMeter('color-meter');

const colorCount = meter.createCounter('colors', {
  description: 'Count each color'
});

// 色ごとにCounterを生成する
const redCounter = colorCount.bind({ color: 'red'});
const blueCounter = colorCount.bind({ color: 'blue'});
const yellowCounter = colorCount.bind({ color: 'yellow'});

module.exports.countColorRequests = () => {
  return (req, res, next) => {
    switch (res.locals.color) {
      case 'red':
        redCounter.add(1);
        break;
      case 'blue':
        blueCounter.add(1);
        break;
      case 'yellow':
        yellowCounter.add(1);
        break;
    }
    next();
  };
};

使用 `meter.createCounter()` 来创建计数器。
传入的字符串参数将会作为指标数据表的表名。

为了将每个已归还颜色的计数器值绘制成图表,我们将在以下示例中使用meter.createCounter()创建计数器,并将标签绑定到该计数器,从而创建三个颜色的计数器。
在这里指定的color: ‘red’相当于图表的系列名称。

const redCounter = colorCount.bind({ color: 'red'});

将样品集成

将刚刚创建的monitoring.js文件集成到示例中。

'use strict';

const express = require('express');
const app = express();
const PORT = process.env.PORT || '8080';

+ const { countColorRequests } = require("./monitoring");

app.use(function(req, res, next) {
  // ランダムで色を選ぶ
  const color = ['red', 'blue', 'blue', 'yellow', 'yellow', 'yellow'];
  res.locals.color = color[Math.floor(Math.random() * color.length)];
  next();
});

+ app.use(countColorRequests());

app.get('/', (req, res, next) => {
  res.send(res.locals.color);
  next();
});

app.listen(parseInt(PORT, 10), () => {
  console.log(`Listening for requests on http://localhost:${PORT}`);
});

在使用Math.random()方法选择颜色后,调用countColorRequests()函数,并对选定的颜色计数器进行递增操作。

3.4 动作确认

和第一章类似,会启动示例。一旦启动,除了等待localhost:8080的请求外,还会等待来自Prometheus的指标数据获取(Pull)在localhost:9464/metrics上。

$ node app.js 
Listening for requests on http://localhost:8080
prometheus scrape endpoint: http://localhost:9464/metrics

我将连续100次发送样本请求,并增加计数器的值。

$ for var in `seq 100`; do curl localhost:8080; done

您可以通过访问localhost:9464/metrics来查看计数器值。(Prometheus定期收集此信息)

$ curl http://localhost:9464/metrics
# HELP colors Count each color
# TYPE colors counter
colors{color="red"} 14 1615214799584
colors{color="blue"} 32 1615214799558
colors{color="yellow"} 54 1615214799597

那么,我将在Prometheus中尝试进行图表展示。

选择Graph选项卡,将“colors”输入到文本框中,点击执行按钮。
然后,将输出一个类似下图的图表,可以确认计数器值的增加情况。

prometheus.png

最后

不使用OpenTelemetry也可以通过各种方法来实现度量收集,但如果要收集用户应用程序的自定义度量指标,OpenTelemetry似乎能够发挥其优势。

关于OpenTelemetry,如果还有其他有趣的功能,我想尝试一下。

广告
将在 10 秒后关闭
bannerAds