Code coverage report for node/src/apm/prometheus/metric.ts

Statements: 13.33% (2 / 15)      Branches: 0% (0 / 7)      Functions: 0% (0 / 4)      Lines: 14.29% (2 / 14)      Ignored: none     

All files » node/src/apm/prometheus/ » metric.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68    1                                                       1                                                                          
import {Aggregator, Registry} from 'prom-client';
import {Tags} from '@btilford/ts-base-core';
import * as os from 'os';
 
 
export type PromOptions = {
  registry?: Registry[];
  aggregator?: Aggregator;
  help: string;
  tags?: Tags;
  /**
   * `prom-client` requires configuring the tags that will be used before calling collection methods.
   * You can provide names for tags that can't be set until the method invocation here.
   */
  additionalTagNames?: string[];
  prefix?: string;
  suffix?: string;
}
 
function cleanMetricName(name: string): string {
  const result = name.replace(/\./g, ':') // prometheus namespaces on `:` instead of `.`
    .replace(/((?!:)\W)/g, '_') // convert anything left thats not a word to `_`
    .replace(/(__+|::+)/g, '_') // convert >= double  `__` or `::` to single
    .replace(/(^[:_]|[:_]$)/g, ''); // trim leading trailing word separators
 
  // use the regex from their site to verify
  console.assert(result.match(/[:A-Z_a-z][\w:]*/), 'Invalid metric name! %s', result);
  return result;
}
 
export class PromMetric {
  readonly tags: Tags;
  protected readonly options: PromOptions;
  protected readonly supportedLabels: Set<string>;
  readonly name: string;
 
  constructor(
    name: string,
    tags: Tags,
    options: PromOptions) {
    this.options = { ...options };
    this.tags = {
      pid: `${process.pid}`,
      NODE_ENV: process.env.NODE_ENV || 'not set',
      host: os.hostname(),
      os: os.type(),
      platform: os.platform(),
 
      ...options.tags,
      ...tags
    };
    this.name = cleanMetricName([options.prefix, name, options.suffix].filter(part => part).join(':'));
 
    this.supportedLabels = new Set([...(this.options.additionalTagNames || []), ...Object.keys(this.tags)])
  }
 
  filterTags(tags: Tags = {}): Tags {
    const result: Tags = {};
    for (const entry of Object.entries(tags)) {
      if (this.supportedLabels.has(entry[0])) {
        result[entry[0]] = entry[1];
      }
    }
    return result;
  }
}