-
Notifications
You must be signed in to change notification settings - Fork 825
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add metrics sdk * refactor: based on comments and add Gauge support * fix: add JSDoc comment * fix: pass label values to handle and generate TimeSeries * fix: add MeterConfig and logger option
- Loading branch information
1 parent
502f9e4
commit a025108
Showing
9 changed files
with
658 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/*! | ||
* Copyright 2019, OpenTelemetry Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import * as types from '@opentelemetry/types'; | ||
import { TimeSeries } from './export/types'; | ||
|
||
/** | ||
* CounterHandle allows the SDK to observe/record a single metric event. The | ||
* value of single handle in the `Counter` associated with specified label | ||
* values. | ||
*/ | ||
export class CounterHandle implements types.CounterHandle { | ||
private _data = 0; | ||
|
||
constructor( | ||
private readonly _disabled: boolean, | ||
private readonly _monotonic: boolean, | ||
private readonly _labelValues: string[], | ||
private readonly _logger: types.Logger | ||
) {} | ||
|
||
add(value: number): void { | ||
if (this._disabled) return; | ||
|
||
if (this._monotonic && value < 0) { | ||
this._logger.error('Monotonic counter cannot descend.'); | ||
return; | ||
} | ||
this._data = this._data + value; | ||
} | ||
|
||
/** | ||
* Returns the TimeSeries with one or more Point. | ||
* | ||
* @param timestamp The time at which the counter is recorded. | ||
* @returns The TimeSeries. | ||
*/ | ||
getTimeSeries(timestamp: types.HrTime): TimeSeries { | ||
return { | ||
labelValues: this._labelValues.map(value => ({ value })), | ||
points: [{ value: this._data, timestamp }], | ||
}; | ||
} | ||
} | ||
|
||
/** | ||
* GaugeHandle allows the SDK to observe/record a single metric event. The | ||
* value of single handle in the `Gauge` associated with specified label values. | ||
*/ | ||
export class GaugeHandle implements types.GaugeHandle { | ||
private _data = 0; | ||
|
||
constructor( | ||
private readonly _disabled: boolean, | ||
private readonly _monotonic: boolean, | ||
private readonly _labelValues: string[], | ||
private readonly _logger: types.Logger | ||
) {} | ||
|
||
set(value: number): void { | ||
if (this._disabled) return; | ||
|
||
if (this._monotonic && value < this._data) { | ||
this._logger.error('Monotonic gauge cannot descend.'); | ||
return; | ||
} | ||
this._data = value; | ||
} | ||
|
||
/** | ||
* Returns the TimeSeries with one or more Point. | ||
* | ||
* @param timestamp The time at which the gauge is recorded. | ||
* @returns The TimeSeries. | ||
*/ | ||
getTimeSeries(timestamp: types.HrTime): TimeSeries { | ||
return { | ||
labelValues: this._labelValues.map(value => ({ value })), | ||
points: [{ value: this._data, timestamp }], | ||
}; | ||
} | ||
} | ||
|
||
/** | ||
* MeasureHandle is an implementation of the {@link MeasureHandle} interface. | ||
*/ | ||
export class MeasureHandle implements types.MeasureHandle { | ||
record( | ||
value: number, | ||
distContext?: types.DistributedContext, | ||
spanContext?: types.SpanContext | ||
): void { | ||
// @todo: implement this method. | ||
return; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
/*! | ||
* Copyright 2019, OpenTelemetry Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import * as types from '@opentelemetry/types'; | ||
import { ConsoleLogger } from '@opentelemetry/core'; | ||
import { CounterHandle, GaugeHandle, MeasureHandle } from './Handle'; | ||
import { Metric, CounterMetric, GaugeMetric } from './Metric'; | ||
import { | ||
MetricOptions, | ||
DEFAULT_METRIC_OPTIONS, | ||
DEFAULT_CONFIG, | ||
MeterConfig, | ||
} from './types'; | ||
|
||
/** | ||
* Meter is an implementation of the {@link Meter} interface. | ||
*/ | ||
export class Meter implements types.Meter { | ||
private readonly _logger: types.Logger; | ||
|
||
/** | ||
* Constructs a new Meter instance. | ||
*/ | ||
constructor(config: MeterConfig = DEFAULT_CONFIG) { | ||
this._logger = config.logger || new ConsoleLogger(config.logLevel); | ||
} | ||
|
||
/** | ||
* Creates and returns a new {@link Measure}. | ||
* @param name the name of the metric. | ||
* @param [options] the metric options. | ||
*/ | ||
createMeasure( | ||
name: string, | ||
options?: types.MetricOptions | ||
): Metric<MeasureHandle> { | ||
// @todo: implement this method | ||
throw new Error('not implemented yet'); | ||
} | ||
|
||
/** | ||
* Creates a new counter metric. Generally, this kind of metric when the | ||
* value is a quantity, the sum is of primary interest, and the event count | ||
* and value distribution are not of primary interest. | ||
* @param name the name of the metric. | ||
* @param [options] the metric options. | ||
*/ | ||
createCounter( | ||
name: string, | ||
options?: types.MetricOptions | ||
): Metric<CounterHandle> { | ||
const opt: MetricOptions = { | ||
// Counters are defined as monotonic by default | ||
monotonic: true, | ||
logger: this._logger, | ||
...DEFAULT_METRIC_OPTIONS, | ||
...options, | ||
}; | ||
return new CounterMetric(name, opt); | ||
} | ||
|
||
/** | ||
* Creates a new gauge metric. Generally, this kind of metric should be used | ||
* when the metric cannot be expressed as a sum or because the measurement | ||
* interval is arbitrary. Use this kind of metric when the measurement is not | ||
* a quantity, and the sum and event count are not of interest. | ||
* @param name the name of the metric. | ||
* @param [options] the metric options. | ||
*/ | ||
createGauge( | ||
name: string, | ||
options?: types.MetricOptions | ||
): Metric<GaugeHandle> { | ||
const opt: MetricOptions = { | ||
// Gauges are defined as non-monotonic by default | ||
monotonic: false, | ||
logger: this._logger, | ||
...DEFAULT_METRIC_OPTIONS, | ||
...options, | ||
}; | ||
return new GaugeMetric(name, opt); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/*! | ||
* Copyright 2019, OpenTelemetry Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import * as types from '@opentelemetry/types'; | ||
import { hashLabelValues } from './Utils'; | ||
import { CounterHandle, GaugeHandle } from './Handle'; | ||
import { MetricOptions } from './types'; | ||
|
||
/** This is a SDK implementation of {@link Metric} interface. */ | ||
export abstract class Metric<T> implements types.Metric<T> { | ||
protected readonly _monotonic: boolean; | ||
protected readonly _disabled: boolean; | ||
protected readonly _logger: types.Logger; | ||
private readonly _handles: Map<String, T> = new Map(); | ||
|
||
constructor(name: string, options: MetricOptions) { | ||
this._monotonic = options.monotonic; | ||
this._disabled = options.disabled; | ||
this._logger = options.logger; | ||
} | ||
|
||
/** | ||
* Returns a Handle associated with specified label values. | ||
* It is recommended to keep a reference to the Handle instead of always | ||
* calling this method for each operation. | ||
* @param labelValues the list of label values. | ||
*/ | ||
getHandle(labelValues: string[]): T { | ||
const hash = hashLabelValues(labelValues); | ||
if (this._handles.has(hash)) return this._handles.get(hash)!; | ||
|
||
const handle = this._makeHandle(labelValues); | ||
this._handles.set(hash, handle); | ||
return handle; | ||
} | ||
|
||
/** | ||
* Returns a Handle for a metric with all labels not set. | ||
*/ | ||
getDefaultHandle(): T { | ||
// @todo: implement this method | ||
this._logger.error('not implemented yet'); | ||
throw new Error('not implemented yet'); | ||
} | ||
|
||
/** | ||
* Removes the Handle from the metric, if it is present. | ||
* @param labelValues the list of label values. | ||
*/ | ||
removeHandle(labelValues: string[]): void { | ||
this._handles.delete(hashLabelValues(labelValues)); | ||
} | ||
|
||
/** | ||
* Clears all Handles from the Metric. | ||
*/ | ||
clear(): void { | ||
this._handles.clear(); | ||
} | ||
|
||
setCallback(fn: () => void): void { | ||
// @todo: implement this method | ||
this._logger.error('not implemented yet'); | ||
return; | ||
} | ||
|
||
protected abstract _makeHandle(labelValues: string[]): T; | ||
} | ||
|
||
/** This is a SDK implementation of Counter Metric. */ | ||
export class CounterMetric extends Metric<CounterHandle> { | ||
constructor(name: string, options: MetricOptions) { | ||
super(name, options); | ||
} | ||
protected _makeHandle(labelValues: string[]): CounterHandle { | ||
return new CounterHandle( | ||
this._disabled, | ||
this._monotonic, | ||
labelValues, | ||
this._logger | ||
); | ||
} | ||
} | ||
|
||
/** This is a SDK implementation of Gauge Metric. */ | ||
export class GaugeMetric extends Metric<GaugeHandle> { | ||
constructor(name: string, options: MetricOptions) { | ||
super(name, options); | ||
} | ||
protected _makeHandle(labelValues: string[]): GaugeHandle { | ||
return new GaugeHandle( | ||
this._disabled, | ||
this._monotonic, | ||
labelValues, | ||
this._logger | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/*! | ||
* Copyright 2019, OpenTelemetry Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
const COMMA_SEPARATOR = ','; | ||
|
||
/** | ||
* Returns a string(comma separated) from the list of label values. | ||
* | ||
* @param labelValues The list of the label values. | ||
* @returns The hashed label values string. | ||
*/ | ||
export function hashLabelValues(labelValues: string[]): string { | ||
return labelValues.sort().join(COMMA_SEPARATOR); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.