Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

adonis5-prometheus

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

adonis5-prometheus - npm Package Compare versions

Comparing version 0.0.6 to 0.0.7

2

build/adonis-typings/prometheus.d.ts
/// <reference types="@adonisjs/http-server/build/adonis-typings" />
declare module '@ioc:Adonis/Prometheus' {
export * from 'prom-client';
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
export interface PrometheusConfig {

@@ -6,0 +6,0 @@ exposeHttpEndpoint: boolean;

/// <reference types="@adonisjs/application/build/adonis-typings" />
/// <reference types="@adonisjs/http-server/build/adonis-typings" />
declare module '@ioc:Adonis/Prometheus/Middlewares/CollectPerformanceMetrics' {
import { ApplicationContract } from '@ioc:Adonis/Core/Application';
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import type { ApplicationContract } from '@ioc:Adonis/Core/Application';
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
export interface MiddlewareContract {

@@ -7,0 +7,0 @@ new (application: ApplicationContract): {

/// <reference types="@adonisjs/application/build/adonis-typings" />
import { ApplicationContract, IocContract } from '@ioc:Adonis/Core/Application';
import type { ApplicationContract, IocContract } from '@ioc:Adonis/Core/Application';
export default class PrometheusProvider {

@@ -8,4 +8,12 @@ protected app: ApplicationContract;

constructor(app: ApplicationContract);
/**
* Expose metrics on the given endpoint
*/
private exposeMetricsEndpoint;
/**
* Collect system metrics if enabled
*/
private collectSystemMetrics;
register(): void;
private exposeMetrics;
shutdown(): Promise<void>;
}
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {

@@ -23,2 +27,3 @@ if (k2 === undefined) k2 = k;

const prometheus = __importStar(require("prom-client"));
const Metrics_1 = require("../src/Metrics");
class PrometheusProvider {

@@ -29,27 +34,11 @@ constructor(app) {

}
register() {
const Config = this.app.container.resolveBinding('Adonis/Core/Config');
const systemMetrics = Config.get('prometheus.systemMetrics');
if (Config.get('prometheus.systemMetrics').enabled) {
const { enabled, ...params } = systemMetrics;
prometheus.collectDefaultMetrics(params);
/**
* Expose metrics on the given endpoint
*/
exposeMetricsEndpoint(config) {
if (config.exposeHttpEndpoint === false) {
return;
}
if (Config.get('prometheus.exposeHttpEndpoint')) {
this.exposeMetrics(Config.get('prometheus.endpoint'));
}
this.app.container.singleton('Adonis/Prometheus', () => prometheus);
this.app.container.singleton('Adonis/Prometheus/Middlewares/CollectPerformanceMetrics', () => {
const { CollectPerformanceMetrics } = require('../src/CollectPerformanceMetrics');
const { Metrics } = require('../src/Metrics');
const config = this.container.use('Adonis/Core/Config').get('prometheus');
const metrics = new Metrics(config);
const enableUptimeMetric = config.uptimeMetric.enabled;
if (enableUptimeMetric) {
metrics.uptimeMetric.inc(1);
}
return new CollectPerformanceMetrics(metrics, config);
});
}
exposeMetrics(urlPath = '/metrics') {
const router = this.app.container.resolveBinding('Adonis/Core/Route');
const urlPath = config.endpoint || '/metrics';
router.get(urlPath, async ({ response }) => {

@@ -61,4 +50,31 @@ response

}
/**
* Collect system metrics if enabled
*/
collectSystemMetrics(config) {
if (config.systemMetrics.enabled) {
prometheus.collectDefaultMetrics(config.systemMetrics);
}
}
register() {
const promConfig = this.app.container
.resolveBinding('Adonis/Core/Config')
.get('prometheus');
this.collectSystemMetrics(promConfig);
this.exposeMetricsEndpoint(promConfig);
const metrics = new Metrics_1.Metrics(promConfig);
if (promConfig.uptimeMetric.enabled) {
metrics.uptimeMetric.inc(1);
}
this.app.container.singleton('Adonis/Prometheus', () => prometheus);
this.app.container.singleton('Adonis/Prometheus/Middlewares/CollectPerformanceMetrics', () => {
const { CollectPerformanceMetrics } = require('../src/CollectPerformanceMetrics');
return new CollectPerformanceMetrics(metrics, promConfig);
});
}
async shutdown() {
prometheus.register.clear();
}
}
exports.default = PrometheusProvider;
PrometheusProvider.needsApplication = true;
/// <reference types="@adonisjs/http-server/build/adonis-typings" />
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import { PrometheusConfig } from '@ioc:Adonis/Prometheus';
import { Metrics } from './Metrics';
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext';
import type { PrometheusConfig } from '@ioc:Adonis/Prometheus';
import type { Metrics } from './Metrics';
export declare class CollectPerformanceMetrics {

@@ -9,4 +9,2 @@ protected metrics: Metrics;

constructor(metrics: Metrics, config: PrometheusConfig);
handle(ctx: HttpContextContract, next: () => Promise<void>): Promise<void>;
private afterRequest;
/**

@@ -16,2 +14,7 @@ * Check if current route is excluded by the user in the configuration

private isRouteExcluded;
/**
* Called when the request is finished.
*/
private afterRequest;
handle(ctx: HttpContextContract, next: () => Promise<void>): Promise<void>;
}

@@ -9,2 +9,34 @@ "use strict";

}
/**
* Check if current route is excluded by the user in the configuration
*/
isRouteExcluded(ctx) {
const excludedRoutes = this.config.httpMetric.excludedRoutes || [];
if (typeof excludedRoutes === 'function') {
return excludedRoutes(ctx);
}
return excludedRoutes.includes(ctx.route.pattern);
}
/**
* Called when the request is finished.
*/
async afterRequest(statusCode, stopHttpRequestTimer) {
const enableThroughputMetric = this.config.throughputMetric.enabled;
const httpMetricOptions = this.config.httpMetric;
/**
* Track request throughput..
*/
if (enableThroughputMetric)
this.metrics.throughputMetric.inc();
/**
* End HTTP request timer.
*/
if (httpMetricOptions.enabled && stopHttpRequestTimer) {
let statusCodeStr = statusCode.toString();
if (httpMetricOptions.shouldGroupStatusCode) {
statusCodeStr = `${statusCodeStr[0]}xx`;
}
stopHttpRequestTimer({ statusCode: statusCodeStr });
}
}
async handle(ctx, next) {

@@ -19,18 +51,17 @@ const { request, response, route } = ctx;

let stopHttpRequestTimer;
if (httpMetricOptions.enabled) {
if (httpMetricOptions.enabled && !this.isRouteExcluded(ctx)) {
const includeRouteParams = httpMetricOptions.includeRouteParams;
const includeQueryParams = httpMetricOptions.includeQueryParams;
if (!this.isRouteExcluded(ctx)) {
let url = includeRouteParams ? request.url() : route?.pattern;
if (includeQueryParams && request.parsedUrl.query) {
url += `?${request.parsedUrl.query}`;
}
stopHttpRequestTimer = this.metrics.httpMetric.startTimer({
method: request.method(),
url,
});
let url = includeRouteParams ? request.url() : route?.pattern;
if (includeQueryParams && request.parsedUrl.query) {
url += `?${request.parsedUrl.query}`;
}
stopHttpRequestTimer = this.metrics.httpMetric.startTimer({
method: request.method(),
url,
});
}
/**
* Execute request and track metrics for the request.
*
* If the request fails with any error, we have to catch

@@ -48,32 +79,3 @@ * this error, track metrics, then rethrow the error.

}
async afterRequest(statusCode, stopHttpRequestTimer) {
const enableThroughputMetric = this.config.throughputMetric.enabled;
const httpMetricOptions = this.config.httpMetric;
/**
* Track request throughput..
*/
if (enableThroughputMetric)
this.metrics.throughputMetric.inc();
/**
* End HTTP request timer.
*/
if (httpMetricOptions.enabled && stopHttpRequestTimer) {
let statusCodeStr = statusCode.toString();
if (httpMetricOptions.shouldGroupStatusCode) {
statusCodeStr = statusCodeStr[0] + 'xx';
}
stopHttpRequestTimer({ statusCode: statusCodeStr });
}
}
/**
* Check if current route is excluded by the user in the configuration
*/
isRouteExcluded(ctx) {
const excludedRoutes = this.config.httpMetric.excludedRoutes || [];
if (typeof excludedRoutes === 'function') {
return excludedRoutes(ctx);
}
return excludedRoutes.includes(ctx.route.pattern);
}
}
exports.CollectPerformanceMetrics = CollectPerformanceMetrics;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {

@@ -6,0 +10,0 @@ if (k2 === undefined) k2 = k;

{
"name": "adonis5-prometheus",
"version": "0.0.6",
"version": "0.0.7",
"packageManager": "pnpm@7.9.5",
"description": "Prometheus wrapper for Adonis 5",
"main": "build/providers/PrometheusProvider.js",
"typings": "./build/adonis-typings/index.d.ts",
"files": [
"build/adonis-typings",
"build/providers",
"build/src",
"build/templates"
],
"scripts": {
"mrm": "mrm --preset=@adonisjs/mrm-preset",
"pretest": "npm run lint",
"test": "node .bin/test.js",
"lint": "eslint . --ext=.ts",
"clean": "del-cli build",
"copyfiles": "copyfiles \"templates/**/*.txt\" build",
"compile": "npm run lint && npm run clean && tsc",
"build": "npm run compile && npm run copyfiles",
"prepublishOnly": "npm run build",
"format": "prettier --write .",
"release": "np --message=\"🔖 %s\"",
"version": "npm run build",
"sync-labels": "github-label-sync --labels ./node_modules/@adonisjs/mrm-preset/gh-labels.json Julien-R44/adonis5-prometheus"
},
"author": "Julien Ripouteau <julien@ripouteau.com>",
"license": "MIT",
"homepage": "https://github.com/Julien-R44/adonis5-prometheus#readme",
"repository": {

@@ -32,2 +13,5 @@ "type": "git",

},
"bugs": {
"url": "https://github.com/Julien-R44/adonis5-prometheus/issues"
},
"keywords": [

@@ -41,50 +25,48 @@ "adonisjs",

],
"author": "Julien Ripouteau <julien@ripouteau.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/Julien-R44/adonis5-prometheus/issues"
"main": "build/providers/PrometheusProvider.js",
"typings": "./build/adonis-typings/index.d.ts",
"files": [
"build/adonis-typings",
"build/providers",
"build/src",
"build/templates"
],
"peerDependencies": {
"@adonisjs/core": "^5.8.0"
},
"homepage": "https://github.com/Julien-R44/adonis5-prometheus#readme",
"dependencies": {
"prom-client": "^14.0.1"
"@poppinss/dev-utils": "^2.0.3",
"prom-client": "^14.1.0"
},
"devDependencies": {
"@adonisjs/core": "^5.4.2",
"@adonisjs/mrm-preset": "^5.0.2",
"@adonisjs/require-ts": "^2.0.8",
"@types/node": "^17.0.0",
"commitizen": "^4.2.4",
"@adonisjs/core": "^5.8.6",
"@adonisjs/mrm-preset": "^5.0.3",
"@adonisjs/require-ts": "^2.0.12",
"@japa/api-client": "^1.4.1",
"@japa/assert": "^1.3.5",
"@japa/runner": "^2.1.1",
"@japa/spec-reporter": "^1.2.0",
"@julr/eslint-config": "^0.3.2",
"@types/node": "^18.7.14",
"bumpp": "^8.2.1",
"commitizen": "^4.2.5",
"copyfiles": "^2.4.1",
"del-cli": "^4.0.1",
"eslint": "^8.5.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-adonis": "^2.1.0",
"eslint-plugin-prettier": "^4.0.0",
"github-label-sync": "^2.0.2",
"del-cli": "^5.0.0",
"eslint": "^8.23.0",
"github-label-sync": "^2.2.0",
"japa": "^4.0.0",
"mrm": "^3.0.10",
"np": "^7.6.0",
"prettier": "^2.5.1",
"typescript": "^4.5.4"
"mrm": "^4.1.0",
"nodemon": "^2.0.19",
"prettier": "^2.7.1",
"typescript": "^4.8.2"
},
"eslintConfig": {
"extends": [
"plugin:adonis/typescriptPackage",
"prettier"
"ignorePatterns": [
"build"
],
"plugins": [
"prettier"
],
"extends": "@julr",
"rules": {
"prettier/prettier": [
"error",
{
"endOfLine": "auto"
}
]
"@typescript-eslint/no-var-requires": "off"
}
},
"eslintIgnore": [
"build"
],
"prettier": {

@@ -119,3 +101,17 @@ "trailingComma": "es5",

}
}
}
},
"scripts": {
"mrm": "mrm --preset=@adonisjs/mrm-preset",
"test": "nodemon --ignore test-app/ bin/test.ts",
"lint": "eslint .",
"clean": "del-cli build",
"copyfiles": "copyfiles \"templates/**/*.txt\" build",
"compile": "pnpm lint && pnpm clean && tsc",
"build": "pnpm compile && pnpm copyfiles",
"format": "prettier --write .",
"release": "bumpp --commit --push --tag && pnpm publish",
"version": "pnpm build",
"sync-labels": "github-label-sync --labels ./node_modules/@adonisjs/mrm-preset/gh-labels.json Julien-R44/adonis5-prometheus"
},
"readme": "<div align=\"center\">\n <img src=\"https://i.imgur.com/QZf8jrj.png\" width=\"300px\" /> \n <br/>\n <h3>Adonis5-Prometheus</h3>\n <p>Simple Prometheus Wrapper for Adonis</p>\n <a href=\"https://www.npmjs.com/package/adonis5-prometheus\">\n <img src=\"https://img.shields.io/npm/v/adonis5-prometheus.svg?style=for-the-badge&logo=npm\" />\n </a>\n <img src=\"https://img.shields.io/npm/l/adonis5-prometheus?color=blueviolet&style=for-the-badge\" />\n <img src=\"https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript\" />\n</div>\n\n## Installation\n```\nnpm i adonis5-prometheus\nnode ace configure adonis5-prometheus\n```\n\n## Usage\n\nA configuration file has been added in `config/prometheus.ts`.\n\nBy default the system metrics are collected ( `systemMetrics.enabled: true` ), so now you can call the endpoint `{{host}}/metrics` to get the measured metrics.\n\nHere is an example scrape_config to add to prometheus.yml:\n```yaml\nscrape_configs:\n - job_name: my-adonis-app\n static_configs:\n - targets: [my-adonis-app.com]\n scrape_interval: 5s\n```\n\n## Built-in Metrics\nMetrics collected by Adonis5-prometheus middleware\n| Type | Name | Description |\n| --- | --- | --- |\n| Histogram | `adonis_http_request_durations` | Total time each HTTP requests takes. |\n| Gauge | `adonis_uptime_metrics` | Uptime performance of the application (1 = up, 0 = down) |\n| Counter | `adonis_throughput_metrics` | No. of request handled. |\n\nTo enable them, simply register the `CollectPerformanceMetrics` as the first item in the start/kernel.ts:\n```typescript\nServer.middleware.register([\n // Make it first in the list for reliable metrics.\n () => import('@ioc:Adonis/Prometheus/Middlewares/CollectPerformanceMetrics'),\n () => import('@ioc:Adonis/Core/BodyParser'),\n ...\n])\n```\nVerify if the metrics are enabled in the `config/prometheus.ts` file. You can also configure the metrics there.\n\n## Custom Metrics\n```typescript\n// Register your custom metrics in the separate file you want.\nexport const OrderMetric = new Prometheus.Counter({\n name: 'sent_orders',\n help: 'Total Orders Sent',\n})\n\n// OrderController.ts\nimport { OrderMetric } from 'App/Metrics'\n\nexport default class OrderController {\n public async store({ request }: HttpContextContract) {\n const order = await request.validate({ schema: OrderSchema })\n\n // ...\n OrderMetric.inc()\n // ...\n }\n}\n```\nWhen hitting `{{host}}/metrics` you will now get the following:\n```\n# HELP send_orders Total Orders Sent\n# TYPE send_orders counter\nsent_orders 2\n```\n\n## Grafana Dashboard\nA basic ready to use dashboard is available in the `grafana` folder.\n**Grafana 8 is required** to be able to import the dashboard correctly, otherwise you'll have to tinker a bit to make it work.\n![https://i.imgur.com/mD0UMhA.png?1](https://i.imgur.com/mD0UMhA.png?1)\nIt includes :\n- Process CPU usage\n- Event loop lag\n- Node.JS version\n- Requests by second\n- Request volume rate by URL\n- Average response time\n- Response error rate by URL\n\nTo be fully functional, you need to enable `systemMetrics`, `httpMetric` and `throughputMetric` in the `config/prometheus.ts` file.\n\n## Documentation\nThis library is a wrapper for prom-client. The prom-client object can be imported with `import Prometheus from '@ioc:Adonis/Prometheus'`. Check out the [documentation](https://github.com/siimon/prom-client) for more information.\n"
}

@@ -28,5 +28,5 @@ <div align="center">

scrape_configs:
- job_name: 'my-adonis-app'
- job_name: my-adonis-app
static_configs:
- targets: ['my-adonis-app.com']
- targets: [my-adonis-app.com]
scrape_interval: 5s

@@ -84,2 +84,3 @@ ```

A basic ready to use dashboard is available in the `grafana` folder.
**Grafana 8 is required** to be able to import the dashboard correctly, otherwise you'll have to tinker a bit to make it work.
![https://i.imgur.com/mD0UMhA.png?1](https://i.imgur.com/mD0UMhA.png?1)

@@ -99,4 +100,1 @@ It includes :

This library is a wrapper for prom-client. The prom-client object can be imported with `import Prometheus from '@ioc:Adonis/Prometheus'`. Check out the [documentation](https://github.com/siimon/prom-client) for more information.
## Acknowledgments
- [tnkemdilim/adonis-prometheus](https://github.com/tnkemdilim/adonis-prometheus) - At first, I just adapted his library to support Adonis5.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc