0.0.2 • Published 3 years ago

@mists/nestjs-metrics v0.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

NestJs Metrics Module

HitCount Contributions welcome TravisCI JSCPD

Sonarcloud Status SonarCloud Coverage SonarCloud Bugs SonarCloud Vulnerabilities

Donate to this project using Patreon Donate to this project using Paypal

What's measured improves - Peter Drucker

@mists/nestjs-metrics desires to be a collection of metric modules adapted for the implementation and usage of metrics within NodeJs projects.

Getting Started

Prerequisites / Dependencies

Depends on the following modules:

Installation

npm install -S @mists/nestjs-metrics
# yarn add @mists/nestjs-metrics

Development

git clone https://github.com/mists-aside/nestjs-metrics your_project
cd your_project
rm -rf .git
git init
git add remote origin https://url/to/your/project/repository
git add .
git commit -am "init"
git push origin master
npm run change:language -- javascript # to use javascript
# or
# npm run change:language -- typescript # to use typescript
npm install
# yarn install
# pnpm install

Requirements

Testing

Run unit tests using npm run test.

Testing is currently set to use unittest.

Single Tests

Run single unit tests file, by calling make test:single -- test/path/to/file.test.js

make test:single -- test/path/to/index.test.js

Deployment

Please check release-it for making releases to npmjs.com or any other repository tool, then run:

npm run release

Documentation

API

For a better understanding of the API, the the following API documentation.

Metrics

Counter

Counters are used for counting events. They can only grow, never decrease or reset.

Reflected by

Gauge

Gauges are used for counting events (with the possibility of decreasing or resetting a value as well) and for timing them

Reflected by

Histogram

Histograms are similar to Gauge, but used for tracking sized and frequency of events

Reflected by

  • PromClient.Histogram
  • StatsD does not know the concept of summary, so we emulated it using the StatsDClient.histogram methods.

Summary

Summaries are similar to Histogram, but used to calculate percentiles of observed values

Reflected by

  • PromClient.Summary
  • on the side of statsd, to support compatibility (not sure if it's good or bad, yet), the same methods as for Histogram

Registering Module

Using (sync) register() method:

@Module({
  imports: [MetricsModule.register({/* ... */})],
})
export class AppModule {}

Using async registerAsync() method:

import { Module } from "@nestjs/common";
import { MetricsModule } from "@mists/nestjs-metrics";

@Injectable()
export class StatsOptionsService implements StatsOptionsFactory {
  createStatsOptions(): StatsOptions {
    return new Promise(resolve => ({
      /* see the MetricsModule::register() options */
    }));
  }
}

@Module({
  imports: [MetricsModule.registerAsync({
    useClass: StatsOptionsService,
    inject: [StatsOptionsService],
  })],
})
export class AppModule {}

Registering Metrics

You will need to create a metric provider first. This will be done using the makeMetricProvider method.

See more details about MetricsModuleOptions before you continue.

import { Module } from "@nestjs/common";
import { MetricsModule, MetricsController, Counter,  } from "@mists/nestjs-metrics";

@Module({
  controllers: [MetricsController],
  imports: [MetricsModule.register({/* ... */})],
  providers: [
    makeMetricProvider(Metrics.Counter, 'metrics_injector', {})
  ],
})
export class AppModule {}

Then, inject your new metric in the controller class like this:

@Controller('/route')
export class MetricsController {
  constructor(@InjectMetric('metrics_injector') protected counter: Counter) {}

  @Get()
  public yourMetricMethod(): string {
    // ...
    this.counter.inc();
    // ...
  }
}

Registering Metrics Controller

The Metrics controller used currently by Prometheus only

import { Module } from "@nestjs/common";
import { MetricsModule, MetricsController } from "@mists/nestjs-metrics";

@Module({
  controllers: [MetricsController],
  imports: [MetricsModule.register({
    prometheus: {
      route: '/metrics',
      // ...
    }
  })],
})
export class AppModule {}

Metric Decorators

Do not rely on decorators only since they have a very limited scope.

Decorators do not require providers, as they have their own mechanism of instantiation, based on the one that creates the providers.

First step is to create a decorator using the default created wrappers:

import { Controller, Get } from "@nestjs/common";
import { generateMetricDecorator, metricIncrementWrapper } from '@mists/nestjs-metrics';


const Increment = generateMetricDecorator(Metrics.Counter, 'metrics_counter_decorator', metricIncrementWrapper, genericOptions);
const GaugeIncrement = generateMetricDecorator(
  Metrics.Gauge,
  'metrics_gauge_decorator',
  metricGaugeIncrementWrapper,
  genericOptions,
);
const GaugeDecrement = generateMetricDecorator(
  Metrics.Gauge,
  'metrics_gauge_decorator',
  metricGaugeDecrementWrapper,
  genericOptions,
);
const Gauge = generateMetricDecorator(Metrics.Gauge, 'metrics_gauge_decorator', metricGaugeSetWrapper, genericOptions);
const GaugeTiming = generateMetricDecorator(Metrics.Gauge, 'metrics_gauge_decorator', metricTimingWrapper, genericOptions);
const HistogramObserve = generateMetricDecorator(
  Metrics.Histogram,
  'metrics_histogram_decorator',
  metricObserveWrapper,
  genericOptions,
);
const HistogramTiming = generateMetricDecorator(
  Metrics.Histogram,
  'metrics_histogram_decorator',
  metricTimingWrapper,
  genericOptions,
);
const SummaryObserve = generateMetricDecorator(Metrics.Summary, 'metrics_summary_decorator', metricObserveWrapper, genericOptions);
const SummaryTiming = generateMetricDecorator(Metrics.Summary, 'metrics_summary_decorator', metricTimingWrapper, genericOptions);


const IncrementHttpCalls = generateMetricDecorator(
  Metrics.Counter,
  'metric_http_calls',
  metricIncrementWrapper
);

Or by defining your own metric wrapper:

export const customMetricWrapper: MetricWrapper = (
  metricArgs: MetricNumericArgs,
  metric: any,
  oldMethod: GenericMethod,
  target: any,
  propertyKey: string | symbol,
  descriptor: PropertyDescriptor,
): GenericMethod => (...args: any[]): any => {
  (metric as Gauge).inc(...metricArgs);
  return oldMethod.call(target, ...args);
};

const CustomIncrementHttpCalls = generateMetricDecorator(
  Metrics.Gauge,
  'metric_http_calls_custom',
  customMetricWrapper
);

Then apply the decorator on a controller method:

@Controller('/test')
class CustomController {
  @Get()
  @IncrementHttpCalls()
  @CustomIncrementHttpCalls(1, { serverId: 'server_1' })
  testMethod() {}
}

Authors

Issues / Support

Add a set of links to the issues page/website, so people can know where to add issues/bugs or ask for support.

License

(If the package is public, add licence) This project is licensed under the MIT License - see the LICENSE.md file for details