node.jscurlhttpsprometheus

Understand Prometheus HTTP API result type


I get a big difference when I invoke HTTP API :

1/ via a bash/curl call

2/ via a nodejs/https GET call

Any help appreciated

Thanks

1/

Here is the invocation via bash+curl :

#!/bin/bash
APIKEY="xxx-xxx"

curl https://<server>/prometheus-api/query \
-H "x-api-key: $APIKEY" \
-H "content-type: application/x-www-form-urlencoded" \
--data-urlencode \
query='ifHCInOctets{instance="MYROUTER.xxx"} and ifHCInOctets{ifName=~"et-1/1/1"}'

Here is the result : resultType is "vector" and result "value" is a number as string, 16 digits (??help)

$ jq '.' result
{
  "status": "success",
  "data": {
    "resultType": "vector",
    "result": [
      {
        "metric": {
          "__name__": "ifHCInOctets",
          "ifAlias": "--- Lien vers ...",
          "ifDescr": "et-1/1/1",
          "ifIndex": "682",
          "ifName": "et-1/1/1",
          "instance": "MYROUTER.xxx",
          "job": "ifmibsnmp"
        },
        "value": [
          1725001024.046,
          "1975177966081341"
        ]
      }
    ]
  }
}

2/

Now here is the invocation via nodejs+https :

var request = '/prometheus-api/query?query=\"ifHCInOctets{instance=\'MYROUTER.xxx\'} and ifHCInOctets{ifName=~\'et-1/1/1\'}\"'

  var erequest = encodeURI(request)

  var options = {
      host:host,
      port: 443,
      method: "GET",
      path: erequest,
      headers: {
        'x-api-key': 'xxxxx',
        'content-type': 'application/x-www-form-urlencoded',
      },
      rejectUnauthorized: false,
  }
  https.get(options,function(resp) {
    resp.setEncoding('utf8');
    console.log('statusCode',resp.statusCode)
    if(resp.statusCode!=200) {
      console.log('-----------------')
    }
    //console.log('headers:', resp.headers);
    let data = '';
    resp.on('data',function(chunk) {
      data += chunk;
    });
    resp.on('end', () => {
      exec.emit('data',data)
    });
  }).on('error', (err) => {
    console.log('Error: ' + err.message);
  });

Here is the result when invoked via nodejs+https : resultType is "string" and result[1] is NaN

{ statusCode 200
data {
  status: 'success',
  data: {
    resultType: 'string',
    result: [
      1725001330.179,
      "ifHCInOctets{instance='MYROUTER.xxx'} and ifHCInOctets{ifName=~'et-1/1/1'}"
    ]
  }
}

Solution

  • The problem is that you are writing your query as a query string instead of the body of your request.

    Try seeing the difference between the request made with curl vs the one made with nodejs. I used a simple server to print out the header/body from the requests.

    debug-server.js

    const server = http.createServer((req, res) => {
        const { rawHeaders, httpVersion, method, socket, url } = req;
        const { remoteAddress, remoteFamily } = socket;
    
        let body = '';
        req.on('data', (chunk) => {
            body += chunk;
        });
        req.on('end', () => {
            const data = JSON.stringify({
                timestamp: Date.now(),
                rawHeaders,
                httpVersion,
                method,
                remoteAddress,
                remoteFamily,
                url,
                body
            }, null, 4);
            console.info('---------------');
            console.info(data);
            res.end(data);
        });
    
    });
    
    console.info('App started');
    server.listen(3000);
    

    response via Nodejs

    {
        "timestamp": 1725632661944,
        "rawHeaders": [
            "content-type",
            "application/x-www-form-urlencoded",
            "Host",
            "localhost:3000",
            "Connection",
            "keep-alive"
        ],
        "httpVersion": "1.1",
        "method": "GET",
        "remoteAddress": "::1",
        "remoteFamily": "IPv6",
        "url": "/api/v1/query?query=%22ifHCInOctets%7Benv='test'%7D%20and%20ifHCInOctets%7BifName=~'et-1/1/1'%7D%22",
        "body": ""
    }
    
    **response via curl**
    
    ```json
    {
        "timestamp": 1725632707931,
        "rawHeaders": [
            "Host",
            "localhost:3000",
            "User-Agent",
            "curl/7.87.0",
            "Accept",
            "*/*",
            "content-type",
            "application/x-www-form-urlencoded",
            "Content-Length",
            "91"
        ],
        "httpVersion": "1.1",
        "method": "POST",
        "remoteAddress": "::ffff:127.0.0.1",
        "remoteFamily": "IPv6",
        "url": "/api/v1/query",
        "body": "query=ifHCInOctets%7Benv%3D%22test%22%7D+and+ifHCInOctets%7BifName%3D~%22et-1%2F1%2F1%22%7D"
    }
    
    

    I also suggest you use form-data when sending form data.