Giter Club home page Giter Club logo

prometheus-query-js's Introduction

Welcome to prometheus-query ๐Ÿ‘‹

NPM version jsDelivr Downloads License: MIT

A Javascript client for Prometheus query API.

โœจ Features

  • Thin & minimal low-level HTTP client to interact with Prometheus's API
  • Works both on the browser and node.js
  • UMD compatible, you can use it with any module loader
  • Supports query and admin APIs

โš ๏ธ This library does not export metrics. Please use prom-client instead.

For building shiny Charts, you may like this chartjs plugin: samber/chartjs-plugin-datasource-prometheus.

๐Ÿš€ Install

NodeJS

npm install prometheus-query

Upgrade from v2 to v3

  • prometheus-query-js has been recoded into Typescript.
  • Type definitions.
  • API update:
    • PrometheusQuery is not the default export anymore.
    • PrometheusQuery has been renamed as PrometheusDriver.
    • See examples

Browser

<script src="https://cdn.jsdelivr.net/npm/prometheus-query/dist/prometheus-query.umd.min.js"></script>

<script type="application/javacript">
	const prom = new Prometheus.PrometheusDriver(...);
</script>

๐Ÿ’ก Quick start

import { PrometheusDriver } from 'prometheus-query';

const prom = new PrometheusDriver({
    endpoint: "https://prometheus.demo.do.prometheus.io",
    baseURL: "/api/v1" // default value
});

Instant query

// last `up` value
const q = 'up{instance="demo.do.prometheus.io:9090",job="node"}';
prom.instantQuery(q)
    .then((res) => {
        const series = res.result;
        series.forEach((serie) => {
            console.log("Serie:", serie.metric.toString());
            console.log("Time:", serie.value.time);
            console.log("Value:", serie.value.value);
        });
    })
    .catch(console.error);

Output:

Serie: up{instance="prometheus.demo.do.prometheus.io:9100", job="node"}
Time: Sun Feb 16 2020 18:33:59 GMT+0100 (Central European Standard Time)
Value: 1

Range query

// up during past 24h
const q = 'up';
const start = new Date().getTime() - 24 * 60 * 60 * 1000;
const end = new Date();
const step = 6 * 60 * 60; // 1 point every 6 hours

prom.rangeQuery(q, start, end, step)
    .then((res) => {
        const series = res.result;
        series.forEach((serie) => {
            console.log("Serie:", serie.metric.toString());
            console.log("Values:\n" + serie.values.join('\n'));
        });
    })
    .catch(console.error);

Output:

Serie: up{instance="prometheus.demo.do.prometheus.io:9090", job="prometheus"}
Values:
Sat Feb 15 2020 18:21:47 GMT+0100 (Central European Standard Time): 1
Sun Feb 16 2020 00:21:47 GMT+0100 (Central European Standard Time): 1
Sun Feb 16 2020 06:21:47 GMT+0100 (Central European Standard Time): 1
Sun Feb 16 2020 12:21:47 GMT+0100 (Central European Standard Time): 1
Sun Feb 16 2020 18:21:47 GMT+0100 (Central European Standard Time): 1

Serie: up{instance="prometheus.demo.do.prometheus.io:9093", job="alertmanager"}
Values:
Sat Feb 15 2020 18:21:47 GMT+0100 (Central European Standard Time): 1
Sun Feb 16 2020 00:21:47 GMT+0100 (Central European Standard Time): 1
Sun Feb 16 2020 06:21:47 GMT+0100 (Central European Standard Time): 1
Sun Feb 16 2020 12:21:47 GMT+0100 (Central European Standard Time): 1
Sun Feb 16 2020 18:21:47 GMT+0100 (Central European Standard Time): 1

Serie: up{instance="prometheus.demo.do.prometheus.io:9100", job="node"}
Values:
Sat Feb 15 2020 18:20:51 GMT+0100 (Central European Standard Time): 1
Sun Feb 16 2020 00:20:51 GMT+0100 (Central European Standard Time): 1
Sun Feb 16 2020 06:20:51 GMT+0100 (Central European Standard Time): 1
Sun Feb 16 2020 12:20:51 GMT+0100 (Central European Standard Time): 1
Sun Feb 16 2020 18:20:51 GMT+0100 (Central European Standard Time): 1

List series matching query

const match = 'up';
const start = new Date().getTime() - 24 * 60 * 60 * 1000;
const end = new Date();

prom.series(match, start, end)
    .then((res) => {
        console.log('Series:');
        console.log(res.join('\n'));
    })
    .catch(console.error);

Output:

up{instance="demo.do.prometheus.io:9090", job="prometheus"}
up{instance="demo.do.prometheus.io:9093", job="alertmanager"}
up{instance="demo.do.prometheus.io:9100", job="node"}

List all active alerts

prom.alerts()
    .then(console.log)
    .catch(console.error);

Output:

[
  Alert {
    activeAt: 2019-11-14T20:04:36.629Z,
    annotations: {},
    labels: { alertname: 'ExampleAlertAlwaysFiring', job: 'alertmanager' },
    state: 'firing',
    value: 1
  },
  Alert {
    activeAt: 2019-11-14T20:04:36.629Z,
    annotations: {},
    labels: { alertname: 'ExampleAlertAlwaysFiring', job: 'node' },
    state: 'firing',
    value: 1
  },
  Alert {
    activeAt: 2019-11-14T20:04:36.629Z,
    annotations: {},
    labels: { alertname: 'ExampleAlertAlwaysFiring', job: 'prometheus' },
    state: 'firing',
    value: 1
  },
  Alert {
    activeAt: 2019-11-14T20:04:36.629Z,
    annotations: {},
    labels: { alertname: 'ExampleAlertAlwaysFiring', job: 'pushgateway' },
    state: 'firing',
    value: 1
  }
]

Authenticated query

Using basic auth:

new PrometheusDriver({
    endpoint: "https://prometheus.demo.do.prometheus.io",
    auth: {
        username: 'foo',
        password: 'bar'
    }
});

Using cookies:

new PrometheusDriver({
    endpoint: "https://prometheus.demo.do.prometheus.io",
    withCredentials: true
});

Proxy

new PrometheusDriver({
    endpoint: "https://prometheus.demo.do.prometheus.io",
    proxy: {
        host: 'proxy.acme.com',
        port: 8080
    }
});

Hook HTTP requests and responses

new PrometheusDriver({
    endpoint: "https://prometheus.demo.do.prometheus.io",
    proxy: {
        host: 'proxy.acme.com',
        port: 8080
    },
    requestInterceptor: {
        onFulfilled: (config: AxiosRequestConfig) => {
            return config;
        },
        onRejected: (error: any) => {
            return Promise.reject(error.message);
        }
    },
    responseInterceptor: {
        onFulfilled: (res: AxiosResponse) => {
            return res;
        },
        onRejected: (error: any) => {
            return Promise.reject(error.message);
        }
    }
});

๐Ÿ” Security advisory

If you open a Prometheus instance on Internet, it would be a good idea to block some routes.

Start by blocking /api/v1/admin. I'm pretty sure allowing only /api/v1/query and /api/v1/query_range will match your needs.

Also don't use Prometheus as a multitenant timeseries database!

At your own risk... ๐Ÿ˜˜

๐Ÿค Contributing

The Prometheus Query client is open source and contributions from the community (you!) are welcome.

There are many ways to contribute: writing code, documentation, reporting issues...

How-to

Author

๐Ÿ‘ค Samuel Berthe

๐Ÿ’ซ Show your support

Give a โญ๏ธ if this project helped you!

support us

๐Ÿ“ License

Copyright ยฉ 2020 Samuel Berthe.

This project is MIT licensed.

prometheus-query-js's People

Contributors

dependabot[bot] avatar gameram avatar lawcha avatar magnusvojbacke avatar meringu avatar nschrader avatar samber avatar tredondo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

prometheus-query-js's Issues

link github on npm

hey thanks for the repo. ๐Ÿ‘
Would be nice if you could link this github repo on npm as it is not easily found.

Getting unexpected_error when trying to query Prometheus

I just spent some time trying to figure why I cannot use this library to query my Prometheus instance.
Look like for newest Prometheus version (I'm running 2.25.2), the gzip encoding is required.
This is what worked for me:

const promDriver = new PrometheusDriver({
  endpoint: "http://localhost:9090",
  baseURL: "/api/v1",
  headers: {
    'Accept-Encoding': 'gzip'
  },
  warningHook: (x => console.log(x))
});

This issue is more for future people who might face the same issue - maybe worth adding something on the readme?

Incompatible with node v17

Library works perfectly with node v16.14.2 but returns this error in v17.8.0.

Unknown error {
  status: 'error',
  errorType: 'unexpected_error',
  error: 'unexpected http error'
}

Errors of Prometheus are not handled

My problem

I execute the query "sensor_1 @ 1234567" , resulting in the following request:

GET /query?query=sensor_1+%40+123456&time=1647448589.845

If I look to the raw response that Prometheus gives me, this is that I obtain:

{
   "status":"error",
   "errorType":"bad_data",
   "error":"@ modifier is disabled"
}

However, in my Angular project, the prometheus-query library does not seem to handle the case where there is an error as above (see screenshot below).

image

Question

I think this is a problem of the library itself, as I said. Can someone confirm this and tell me how I can resolve this ? Thank you.

Does this package support Request interceptor?

Hi,

Thanks to this project & your contribution! When I introduce this package to our product, I find that we have some QueryString needed when calling Prometheus.

Just want to know, if this package supports Request Interceptor?

alerts() returns undefined for state

First, thanks for the library, this is great!

I noticed when pulling prom.alerts() that our alert state is always coming back undefined (rather than 'firing' or 'pending').

I'm not confident enough to try a patch and PR but I think this is a mixed array call:

ResponseType[obj['state']],

You may have intended for that to reference TargetState?

export type TargetState = 'active' | 'dropped' | 'any';

and if so TargetState should also include 'firing' and 'pending'

cheers!

Refused to set unsafe header "Accept-Encoding"

Hi,

I am using your https://github.com/samber/chartjs-plugin-datasource-prometheus and I keep seeing these console error messages:

Refused to set unsafe header "Accept-Encoding"
(anonymous) @ prometheus-query.umd.js:7
u @ prometheus-query.umd.js:7
(anonymous) @ prometheus-query.umd.js:7
x @ prometheus-query.umd.js:7
N @ prometheus-query.umd.js:7
Promise.then (async)
C.request @ prometheus-query.umd.js:7
(anonymous) @ prometheus-query.umd.js:7
request @ prometheus-query.umd.js:7
rangeQuery @ prometheus-query.umd.js:7
(anonymous) @ prometheus-query.umd.js:7
executeQueries @ prometheus-query.umd.js:7
beforeUpdate @ prometheus-query.umd.js:7
notify @ Chart.min.js:7
update @ Chart.min.js:7
afterInit @ prometheus-query.umd.js:7
notify @ Chart.min.js:7
initialize @ Chart.min.js:7
construct @ Chart.min.js:7
Qe @ Chart.min.js:7
(anonymous) @ chart.html:16

Could this have been introduced by #11 ?

Would it be possible to allow /not/ setting this variable (or default to not setting it?)

unexpected http error

Curl ok, postman ok but this library return

{
    "error": {
        "status": "error",
        "errorType": "unexpected_error",
        "error": "unexpected http error"
    },
    "status": "success"
}

What the F.U.C.K was this guyโ€™s problem?

How to set the rate interval in the PROMQL similar to $__rate_interval by grafana.

I am trying to fetch the different metrics using PROMQL and make my custom dashboard similar to grafana. But I am not sure how to dynamically set rate interval and step in query range using the given time range.

I am using HTTP API provided by the Prometheus.

> const rateInterval = "5m"; **//need to make this dynamic according to the given time range.**
> const queryRangeList = {
>   load15: `node_load15`,
>   cpuUsage: `sum by(instance) (irate(node_cpu_seconds_total{instance="localhost:9100",job="node", mode="system"}[${rateInterval}])) / on(instance) group_left sum by (instance)((irate(node_cpu_seconds_total{instance="localhost:9100",job="node"}[${rateInterval}])))`,
>   memoryUsage: `node_memory_MemTotal_bytes{instance="localhost:9100",job="node"} - node_memory_MemFree_bytes{instance="localhost:9100",job="node"} - (node_memory_Cached_bytes{instance="localhost:9100",job="node"} + node_memory_Buffers_bytes{instance="localhost:9100",job="node"} + node_memory_SReclaimable_bytes{instance="localhost:9100",job="node"})`,
> };
> 
> module.exports = {
>   queryRangeList,
> }

Add more details to `unexpected client error` error handling

I'm getting unexpected client error when running instantQuery.

But I don't know what to do. The error doesn't happen for all resources but happens all the time for the same resources but as the error is not detailed I can't understand what is happening. Is it possible improve this code below to expose more details?

            throw {
                status: 'error',
                errorType: 'client_error',
                error: 'unexpected client error',
            };

Typescript support?

Hey
Can you please publish types package? It will be really helpful for typescript users :)

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.