Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Type File for Typescript compatibility #32

Open
fieldju opened this issue Apr 19, 2018 · 5 comments
Open

Create Type File for Typescript compatibility #32

fieldju opened this issue Apr 19, 2018 · 5 comments
Assignees

Comments

@fieldju
Copy link
Member

fieldju commented Apr 19, 2018

I think it would be cool to have an official type file either included with this project or available via

npn install @types/measured

I have made the following in my project which is probably almost everything that is needed

/**
 * Everything in this file is sourced from the [measured readme]{@link https://github.com/felixge/node-measured}
 */
declare module 'measured' {
    /**
     * Values that can be read instantly.
     *
     * Gauges take a function as parameter which needs to return their current value.
     */
    export class Gauge {
        constructor(callBack: () => number)

        /**
         * Gauges directly return their currently value.
         */
        public toJSON(): JSON
    }

    /**
     * Things that increment or decrement.
     */
    export class Counter implements IMetric {
        /**
         * @param {CounterProperties} properties
         */
        constructor(properties?: CounterProperties)

        /**
         * Increment the counter by n. Defaults to 1.
         * @param {number} n
         */
        public inc(n?: number): void

        /**
         * Decrement the counter by n. Defaults to 1.
         * @param {number} n
         */
        public dec(n?: number): void

        /**
         * Resets the counter back to count Defaults to 0.
         * @param {number} count
         */
        public reset(count?: number): void

        /**
         * Counters directly return their currently value.
         */
        public toJSON(): JSON
    }

    /**
     * Properties to create a [Counter]{@see Counter} with.
     */
    export class CounterProperties {
        /**
         * count An initial count for the counter. Defaults to 0.
         */
        public count: number
    }

    /**
     * Things that are measured as events / interval. Example:
     */
    export class Meter implements IMetric {
        /**
         * rateUnit The rate unit. Defaults to 1000 (1 sec).
         * tickInterval The interval in which the averages are updated. Defaults to 5000 (5 sec).
         * @param {MeterProperties} properties
         */
        constructor(properties?: MeterProperties)

        /**
         * Register n events as having just occured. Defaults to 1.
         * @param {number} n
         */
        public mark(n: number)

        /**
         * Resets all values. Meters initialized with custom options will be reset to the default settings (patch welcome).
         */
        public reset(): void

        /**
         * Unrefs the backing timer. The meter will not keep the event loop alive. Idempotent.
         */
        public unref(): void

        /**
         * Refs the backing timer again. Idempotent.
         */
        public ref(): void

        /**
         * toJSON Output
         *
         * <li> mean: The average rate since the meter was started.
         * <li> count: The total of all values added to the meter.
         * <li> currentRate: The rate of the meter since the last toJSON() call.
         * <li> 1MinuteRate: The rate of the meter biased towards the last 1 minute.
         * <li> 5MinuteRate: The rate of the meter biased towards the last 5 minutes.
         * <li> 15MinuteRate: The rate of the meter biased towards the last 15 minutes.
         *
         * @return {JSON}
         */
        public toJSON(): JSON
    }

    /**
     * Properties to create a [Meter]{@see Meter} with.
     */
    export class MeterProperties {
        /**
         * The rate unit. Defaults to 1000 (1 sec).
         */
        public rateUnit: number

        /**
         * The interval in which the averages are updated. Defaults to 5000 (5 sec).
         */
        public tickInterval: number
    }

    /**
     * Keeps a resevoir of statistically relevant values biased towards the last 5 minutes to explore their distribution.
     *
     * {@link https://github.com/felixge/node-measured#histogram}
     */
    export class Histogram implements IMetric {
        /**
         * @param {HistogramProperties} properties
         */
        constructor(properties?: HistogramProperties)

        /**
         * Pushes value into the sample. timestamp defaults to Date.now().
         * @param {number} value
         * @param {Date} timestamp
         */
        public update(value: number, timestamp?: Date): void

        /**
         * Whether the histogram contains values.
         * @return {boolean}
         */
        public hasValues(): boolean

        /**
         * Resets all values. Histograms initialized with custom options will be reset to the default settings (patch welcome).
         */
        public reset(): void

        /**
         * toJSON output:
         *
         * <li> min: The lowest observed value.
         * <li> max: The highest observed value.
         * <li> sum: The sum of all observed values.
         * <li> variance: The variance of all observed values.
         * <li> mean: The average of all observed values.
         * <li> stddev: The stddev of all observed values.
         * <li> count: The number of observed values.
         * <li> median: 50% of all values in the resevoir are at or below this value.
         * <li> p75: See median, 75% percentile.
         * <li> p95: See median, 95% percentile.
         * <li> p99: See median, 99% percentile.
         * <li> p999: See median, 99.9% percentile.
         *
         * @return {JSON}
         */
        public toJSON(): JSON
    }

    /**
     * Properties to create a [Histogram]{@see Histogram} with.
     */
    export class HistogramProperties {
        /**
         * The sample resevoir to use. Defaults to an ExponentiallyDecayingSample.
         */
        public sample: object
    }

    /**
     * Timers are a combination of Meters and Histograms. They measure the rate as well as distribution of scalar events.
     * Since they are frequently used for tracking how long certain things take, they expose an API for that:
     *
     * {@see https://github.com/felixge/node-measured#timers}
     */
    export class Timer implements IMetric {
        /**
         * @param {TimerProperties} properties
         */
        constructor(properties?: TimerProperties)

        /**
         * @return {StopWatch} Returns a Stopwatch that has been started.
         */
        public start(): StopWatch

        /**
         *  Updates the internal histogram with value and marks one event on the internal meter.
         * @param {number} value
         */
        public update(value: number)

        /**
         * Resets all values. Timers initialized with custom options will be reset to the default settings.
         */
        public reset(): void

        /**
         * Unrefs the backing timer. The meter will not keep the event loop alive. Idempotent.
         */
        public unref(): void

        /**
         * Refs the backing timer again. Idempotent.
         */
        public ref(): void

        /**
         * toJSON output:
         *
         * <li> meter: {@see Meter} toJSON output docs above.
         * <li> histogram: {@see Histogram} toJSON output docs above.
         *
         * @return {JSON}
         */
        public toJSON(): JSON
    }

    /**
     * Properties to create a [Timer]{@see Timer} with.
     */
    export class TimerProperties {
        /**
         * The internal meter to use. Defaults to a new Meter.
         * {@see Meter}
         */
        public meter: Meter

        /**
         * The internal histogram to use. Defaults to a new Histogram.
         * {@see Histogram}
         */
        public histogram: Histogram
    }

    /**
     * Created by the Timer Metric when start() is called
     */
    export class StopWatch {
        /**
         * Called to mark the end of the timer task
         * @return {number} the total execution time
         */
        public end(): number
    }

    /**
     * Creates a collection that can create and keep track of metrics
     */
    export const createCollection: (name?: string) => Collection

    /**
     * Collection class that keeps track of Metrics that it has created
     *
     * @param {string} name Optional name to use for the collection
     */
    export class Collection {
        constructor(name: string)

        /**
         * {@see https://github.com/felixge/node-measured/blob/master/lib/Collection.js}
         * @return {JSON} JSON object with all the metrics in the collection
         */
        public toJSON(): JSON

        /**
         * Iterates through the metrics in the collection and
         * calls end() in the metric, if the metric has an end() method.
         */
        public end(): void

        /**
         * Creates a new Gauge and registers it with the metrics collection
         *
         * {@see Gauge}
         *
         * @param {() => number} callBack
         * @return {Gauge}
         */
        public guage(callBack: () => number): Gauge

        /**
         * Creates a new Counter and registers it with the metrics collection
         *
         * {@see Counter}
         *
         * @param {CounterProperties} properties optional counter properties.
         * @return {Counter}
         */
        public counter(properties?: CounterProperties): Counter

        /**
         * Creates a new Meter and registers it with the metrics collection
         *
         * {@see Meter}
         *
         * @param {MeterProperties} properties
         * @return {Meter}
         */
        public meter(properties?: MeterProperties): Meter

        /**
         * Creates a new Histogram and registers it with the metrics collection
         *
         * {@see Histogram}
         *
         * @param {HistogramProperties} properties
         * @return {Histogram}
         */
        public histogram(properties?: HistogramProperties): Histogram

        /**
         * Creates a new Timer and registers it with the metrics collection
         *
         * {@see Timer}
         *
         * @param {TimerProperties} properties
         * @return {Timer}
         */
        public timer(properties?: TimerProperties): Timer
    }

    /**
     * All metrics implement toJSON()
     */
    export interface IMetric {
        /**
         * See the toJSON metric of the implementing classes
         * @return {JSON}
         */
        toJSON(): JSON
    }
}

I think a modified version of the above could be included with index.js

Checkout what AWS is doing with their Node SDK
https://github.com/aws/aws-sdk-js

If this is something you are open to I could make a PR.
I think this would benefit all users regardless if they use typescript, as it will add java docs and return types to their IDEs

@fieldju fieldju self-assigned this May 14, 2018
@fieldju fieldju closed this as completed Jun 2, 2018
@gcox
Copy link

gcox commented May 12, 2019

@fieldju Any particular reason why you closed this?

@fieldju
Copy link
Member Author

fieldju commented May 12, 2019

Not particularly, I added bunch of js doc annotations throughout the code base which gives you intelisense and IDE type warnings when using Javascript.

This was enough to meet my needs, since I had been developing this lib for people that don't use typescript.

Although I do have a project in the pipeline that will be typescript and use this lib, so maybe I'll revisit this soon.

Feel free to make a PR or reopen.

@fieldju fieldju reopened this Jun 7, 2019
@fieldju
Copy link
Member Author

fieldju commented Jun 7, 2019

That project that was in the pipeline is here, I will probably do this soon (tm).

@fieldju
Copy link
Member Author

fieldju commented Aug 2, 2019

I last commented on this June 6th, 💯

Update: I am planning on using this library in https://github.com/Nike-Inc/Referee and I will be needed the types for that project and will get it done then. That work is likely to start in the next couple of weeks.

@cmawhorter
Copy link

FWIW, i updated OPs to be measured-core and added actual toJSON return types, and a couple other things

/**
 * Everything in this file is sourced from the [measured readme]{@link https://github.com/felixge/node-measured}
 */
declare module 'measured-core' {
  /**
   * Values that can be read instantly.
   *
   * Gauges take a function as parameter which needs to return their current value.
   */
  export class Gauge implements IMetric {
    getType(): 'Gauge';
    constructor(callback: () => number)

    /**
     * Gauges directly return their currently value.
     */
    public toJSON(): number
  }

  /**
   * Things that increment or decrement.
   */
  export class Counter implements IMetric {
    getType(): 'Counter';
    /**
     * @param properties
     */
    constructor(properties?: CounterProperties)

    /**
     * Increment the counter by n. Defaults to 1.
     * @param n
     */
    public inc(n?: number): void

    /**
     * Decrement the counter by n. Defaults to 1.
     * @param n
     */
    public dec(n?: number): void

    /**
     * Resets the counter back to count Defaults to 0.
     * @param count
     */
    public reset(count?: number): void

    /**
     * Counters directly return their currently value.
     */
    public toJSON(): number
  }

  /**
   * Properties to create a [Counter]{@see Counter} with.
   */
  export class CounterProperties {
    /**
     * count An initial count for the counter. Defaults to 0.
     */
    public count: number
  }

  /**
   * Things that are measured as events / interval. Example:
   */
  export class Meter implements IMetric {
    getType(): 'Meter';
    /**
     * rateUnit The rate unit. Defaults to 1000 (1 sec).
     * tickInterval The interval in which the averages are updated. Defaults to 5000 (5 sec).
     * @param properties
     */
    constructor(properties?: MeterProperties)

    /**
     * Register n events as having just occured. Defaults to 1.
     * @param n
     */
    public mark(n: number): void

    /**
     * Resets all values. Meters initialized with custom options will be reset to the default settings (patch welcome).
     */
    public reset(): void

    /**
     * Unrefs the backing timer. The meter will not keep the event loop alive. Idempotent.
     */
    public unref(): void

    /**
     * Refs the backing timer again. Idempotent.
     */
    public ref(): void

    /**
     * toJSON Output
     *
     * <li> mean: The average rate since the meter was started.
     * <li> count: The total of all values added to the meter.
     * <li> currentRate: The rate of the meter since the last toJSON() call.
     * <li> 1MinuteRate: The rate of the meter biased towards the last 1 minute.
     * <li> 5MinuteRate: The rate of the meter biased towards the last 5 minutes.
     * <li> 15MinuteRate: The rate of the meter biased towards the last 15 minutes.
     *
     * @return
     */
    public toJSON(): MeterData
  }

  export interface MeterData {
    /**
     * The average rate since the meter was started.
     */
    mean: number;
    /**
     * The total of all values added to the meter.
     */
    count: number;
    /**
     * The rate of the meter since the last toJSON() call.
     */
    currentRate: number;
    /**
     * The rate of the meter biased towards the last 1 minute.
     */
    '1MinuteRate': number;
    /**
     * The rate of the meter biased towards the last 5 minutes.
     */
    '5MinuteRate': number;
    /**
     * The rate of the meter biased towards the last 15 minutes.
     */
    '15MinuteRate': number;
  }

  /**
   * Properties to create a [Meter]{@see Meter} with.
   */
  export class MeterProperties {
    /**
     * The rate unit. Defaults to 1000 (1 sec).
     */
    public rateUnit: number

    /**
     * The interval in which the averages are updated. Defaults to 5000 (5 sec).
     */
    public tickInterval: number
  }

  /**
   * Keeps a resevoir of statistically relevant values biased towards the last 5 minutes to explore their distribution.
   *
   * {@link https://github.com/felixge/node-measured#histogram}
   */
  export class Histogram implements IMetric {
    getType(): 'Histogram';
    /**
     * @param properties
     */
    constructor(properties?: HistogramProperties)

    /**
     * Pushes value into the sample. timestamp defaults to Date.now().
     * @param value
     * @param timestamp
     */
    public update(value: number, timestamp?: Date): void

    /**
     * Whether the histogram contains values.
     * @return
     */
    public hasValues(): boolean

    /**
     * Resets all values. Histograms initialized with custom options will be reset to the default settings (patch welcome).
     */
    public reset(): void

    /**
     * toJSON output:
     *
     * <li> min: The lowest observed value.
     * <li> max: The highest observed value.
     * <li> sum: The sum of all observed values.
     * <li> variance: The variance of all observed values.
     * <li> mean: The average of all observed values.
     * <li> stddev: The stddev of all observed values.
     * <li> count: The number of observed values.
     * <li> median: 50% of all values in the resevoir are at or below this value.
     * <li> p75: See median, 75% percentile.
     * <li> p95: See median, 95% percentile.
     * <li> p99: See median, 99% percentile.
     * <li> p999: See median, 99.9% percentile.
     *
     * @return
     */
    public toJSON(): HistogramData
  }

  export interface HistogramData {
    /**
     * The lowest observed value.
     */
    min: number | null;
    /**
     * The highest observed value.
     */
    max: number | null;
    /**
     * The sum of all observed values.
     */
    sum: number | null;
    /**
     * The variance of all observed values.
     */
    variance: number | null;
    /**
     * The average of all observed values.
     */
    mean: number | null;
    /**
     * The stddev of all observed values.
     */
    stddev: number | null;
    /**
     * The number of observed values.
     */
    count: number;
    /**
     * 50% of all values in the resevoir are at or below this value.
     */
    median: number;
    /**
     * See median, 75% percentile.
     */
    p75: number;
    /**
     * See median, 95% percentile.
     */
    p95: number;
    /**
     * See median, 99% percentile.
     */
    p99: number;
    /**
     * See median, 99.9% percentile.
     */
    p999: number;
  }

  /**
   * Properties to create a [Histogram]{@see Histogram} with.
   */
  export class HistogramProperties {
    /**
     * The sample resevoir to use. Defaults to an ExponentiallyDecayingSample.
     */
    public sample: object
  }

  /**
   * Timers are a combination of Meters and Histograms. They measure the rate as well as distribution of scalar events.
   * Since they are frequently used for tracking how long certain things take, they expose an API for that:
   *
   * {@see https://github.com/felixge/node-measured#timers}
   */
  export class Timer implements IMetric {
    getType(): 'Timer';
    /**
     * @param properties
     */
    constructor(properties?: TimerProperties)

    /**
     * @return Returns a Stopwatch that has been started.
     */
    public start(): StopWatch

    /**
     *  Updates the internal histogram with value and marks one event on the internal meter.
     * @param value
     */
    public update(value: number): void

    /**
     * Resets all values. Timers initialized with custom options will be reset to the default settings.
     */
    public reset(): void

    /**
     * Unrefs the backing timer. The meter will not keep the event loop alive. Idempotent.
     */
    public unref(): void

    /**
     * Refs the backing timer again. Idempotent.
     */
    public ref(): void

    /**
     * toJSON output:
     *
     * <li> meter: {@see Meter} toJSON output docs above.
     * <li> histogram: {@see Histogram} toJSON output docs above.
     *
     * @return
     */
    public toJSON(): { meter: MeterData; histogram: HistogramData; }
  }

  /**
   * Properties to create a [Timer]{@see Timer} with.
   */
  export class TimerProperties {
    /**
     * The internal meter to use. Defaults to a new Meter.
     * {@see Meter}
     */
    public meter: Meter

    /**
     * The internal histogram to use. Defaults to a new Histogram.
     * {@see Histogram}
     */
    public histogram: Histogram
  }

  /**
   * Created by the Timer Metric when start() is called
   */
  export class StopWatch {
    /**
     * Called to mark the end of the timer task
     * @return the total execution time
     */
    public end(): number
  }

  /**
   * Creates a collection that can create and keep track of metrics
   */
  export const createCollection: (name?: string) => Collection

  /**
   * Collection class that keeps track of Metrics that it has created
   *
   * @param name Optional name to use for the collection
   */
  export class Collection<TName extends undefined | string = undefined> {
    public name: TName;

    /**
     * Note: This is technically private but you may prefer to use this vs toJSON to iterate metrics.  From my reading of the code, I see no reason not to
     */
    public _metrics: Record<string, IMetric>;

    constructor(name?: TName)

    /**
     * {@see https://github.com/felixge/node-measured/blob/master/lib/Collection.js}
     * @return JSON object with all the metrics in the collection
     */
    public toJSON(): TName extends string ? { [key in TName]: Record<string, unknown> } : Record<string, unknown>

    /**
     * Iterates through the metrics in the collection and
     * calls end() in the metric, if the metric has an end() method.
     */
    public end(): void

    /**
     * Creates a new Gauge and registers it with the metrics collection
     *
     * {@see Gauge}
     *
     * @param callback
     * @return
     */
    public guage(callback: () => number): Gauge

    /**
     * Creates a new Counter and registers it with the metrics collection
     *
     * {@see Counter}
     *
     * @param properties optional counter properties.
     * @return
     */
    public counter(properties?: CounterProperties): Counter

    /**
     * Creates a new Meter and registers it with the metrics collection
     *
     * {@see Meter}
     *
     * @param properties
     * @return
     */
    public meter(properties?: MeterProperties): Meter

    /**
     * Creates a new Histogram and registers it with the metrics collection
     *
     * {@see Histogram}
     *
     * @param properties
     * @return
     */
    public histogram(properties?: HistogramProperties): Histogram

    /**
     * Creates a new Timer and registers it with the metrics collection
     *
     * {@see Timer}
     *
     * @param properties
     * @return
     */
    public timer(properties?: TimerProperties): Timer

    /**
     * register a metric that was created outside the provided convenience methods of this collection
     * @param name The metric name
     * @param metric The {@link IMetric} implementation
     * @example
     * var { Collection, Gauge } = require('measured');
     * const collection = new Collection('node-process-metrics');
     * const gauge = new Gauge(() => {
     *    return process.memoryUsage().heapUsed;
     * });
     * collection.register('node.process.heap_used', gauge);
     */
    public register(name: string, metric: IMetric): void;
  }

  /**
   * All metrics implement toJSON()
   */
  export interface IMetric {
    getType(): string;
    /**
     * See the toJSON metric of the implementing classes
     * @return
     */
    toJSON(): unknown
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants