【问题标题】:Node.js: Is there a way to mock the prometheus pushgateway server?Node.js:有没有办法模拟 prometheus pushgateway 服务器?
【发布时间】:2020-11-25 21:15:17
【问题描述】:

我正在使用node.jsprom-client 尝试将不同的自定义指标推送到Prometheus Pushgateway 服务器。

代码正在运行,现在我正在编写该功能的测试代码。我想知道是否有办法模拟 Prometheus Pushgateway 服务器?

我曾尝试使用普通的 express API 服务器(如下所示)

const express = require('express');
const bodyParser = require('body-parser');

const app = express();

let data = null;

// ROUTES FOR OUR API
// =============================================================================
const router = express.Router();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

router.get('/', (req, res) => {
  console.log("pushgateway server: get to '/' received");
  res.json(data);
});

router.post('/', (req, res) => {
  console.log("pushgateway server: post to '/' received");
  console.log(req.body);
  data = req.body;
  res.send('POST request to the homepage');
})

app.use(router);

// API JSON BASED ERRORS
// =============================================================================
app.use((err, req, res, next) => {
  if (req.xhr) {
    console.error(err);
    res.status(500).send({ err: 'Something failed!' });
  } else {
    next(err);
  }
});
app.use((err, req, res, next) => { // eslint-disable-line
  console.error(err);
  res.status(500).send({ err: err.message });
});

// START THE SERVER
// =============================================================================
const port = 9876;
const server = app.listen(port, '0.0.0.0');
console.log(`Prometheus Pushgateway Mock Server is listening on port ${port}`);

// SHUTDOWN HANDLING
// =============================================================================

// Nodemon Signal Handling
process.once('SIGUSR2', () => {
  console.log('Received kill signal, attempting gracefully close');
  server.close(() => {
    console.log('Closed out remaining connections');
    process.kill(process.pid, 'SIGUSR2');
  });
  setTimeout(() => {
    console.error('Timeout, forcefully shutting down');
    process.kill(process.pid, 'SIGUSR2');
  }, 3000);
});

module.exports = server;

但它不起作用——当我在我的测试代码上调用gateway.pushAdd() 时,服务器没有收到任何发布消息。

谁能给我一些关于如何做到这一点的提示(模拟 prometheus pushgateway 服务器)?

【问题讨论】:

    标签: node.js prometheus prometheus-pushgateway prom-client


    【解决方案1】:

    有不同的选项可以模拟第三方 http 服务器。这里有 3 个:

    免责声明:我是 stubborn 背后的维护者。

    Nock 和 Dyson 是最受欢迎的,它们各有利弊。 Stubborn 是较新的,并试图涵盖 Nock 和 Dyson 的一些限制。

    您可以查看我写的 reddit post first comment 以比较这 3 种解决方案。

    【讨论】:

    • 感谢@bambou 的推荐,下次遇到类似问题再试试。
    【解决方案2】:

    所以我通过创建一个简单的http服务器解决了这个问题。

    以下是服务器的代码:

    const http = require('http');
    
    const body = [];
    let text = null;
    let path = null;
    
    function createServer(port) {
      return http.createServer()
        .on('request', (req, res) => {
          if (req.method === 'POST' || req.method === 'PUT') {
            path = req.url;
            req.on('data', (chunk) => {
              body.push(chunk);
            }).on('end', () => {
              text = Buffer.concat(body).toString();
              res.end(`${req.method} success`);
            }).on('error', (err) => {
              console.error(err);
            });
          } else if (req.method === 'GET') {
            res.end(JSON.stringify({ path, text }));
          } else if (req.method === 'DELETE') {
            path = null;
            text = null;
            res.end('DELETE success');
          }
        }).on('error', (err) => {
          console.log(`Server error: ${err}`);
        })
        .listen(port, '0.0.0.0');
    }
    
    module.exports = (createServer);
    

    服务器接受 POST/PUT/DELETE/GET 请求,处理网关的 pushAdd()/push()/delete() 函数来处理度量数据,以及检查模拟 pushgateway 上的推送数据.

    另外,将request.url和推送到服务器的文本数据保存下来,传递给测试程序进行验证。

    以下是其中一个测试用例(使用Mocha+Chai):

    describe('Check adding custom push count metric', () => {
      it('Check connection: should return - network status: 200, result contains custom count metric string', async () => {
        metricInstance = promMetric.createCustomPushMetric({
          name: 'test_counter',
          help: 'Used to test the pushgateway for custom counter metrics',
          type: 'counter',
          jobName: 'custom-metric-pushgateway-counter',
          groupings: { key: 'test', type: 'customMetric' },
        });
        await promMetric.addPushMetric(metricInstance, 0.879);
        await sleep(500);
        const result = await chai.request(mockPgwServer).get('/');
        expect(result).to.have.status(200);
        const json = JSON.parse(result.text);
        expect(json.path).to.equal('/metrics/job/custom-metric-pushgateway-counter/key/test/type/customMetric');
        expect(json.text).to.match(/# HELP Push_gateway_test_test_counter Used to test the pushgateway for custom counter metrics/);
        expect(json.text).to.match(/# TYPE Push_gateway_test_test_counter counter/);
        expect(json.text).to.match(/Push_gateway_test_test_counter 0.879/);
      });
    });
    

    从客户端发布度量标准时存储在服务器中的“路径”和“文本”在查询和验证时发送回客户端。

    【讨论】: