feat: Complete zCode CLI X with Telegram bot integration

- Add full Telegram bot functionality with Z.AI API integration
- Implement 4 tools: Bash, FileEdit, WebSearch, Git
- Add 3 agents: Code Reviewer, Architect, DevOps Engineer
- Add 6 skills for common coding tasks
- Add systemd service file for 24/7 operation
- Add nginx configuration for HTTPS webhook
- Add comprehensive documentation
- Implement WebSocket server for real-time updates
- Add logging system with Winston
- Add environment validation

🤖 zCode CLI X - Agentic coder with Z.AI + Telegram integration
This commit is contained in:
admin
2026-05-05 09:01:26 +00:00
Unverified
parent 4a7035dd92
commit 875c7f9b91
24688 changed files with 3224957 additions and 221 deletions

View File

@@ -0,0 +1,76 @@
import type { Aggregator } from '../aggregator';
import { SumAggregator, DropAggregator, LastValueAggregator, HistogramAggregator, ExponentialHistogramAggregator } from '../aggregator';
import type { Accumulation } from '../aggregator/types';
import type { InstrumentDescriptor } from '../InstrumentDescriptor';
import type { Maybe } from '../utils';
/**
* Configures how measurements are combined into metrics for views.
*
* Aggregation provides a set of built-in aggregations via static methods.
*/
export interface Aggregation {
createAggregator(instrument: InstrumentDescriptor): Aggregator<Maybe<Accumulation>>;
}
/**
* The default drop aggregation.
*/
export declare class DropAggregation implements Aggregation {
private static DEFAULT_INSTANCE;
createAggregator(_instrument: InstrumentDescriptor): DropAggregator;
}
/**
* The default sum aggregation.
*/
export declare class SumAggregation implements Aggregation {
private static MONOTONIC_INSTANCE;
private static NON_MONOTONIC_INSTANCE;
createAggregator(instrument: InstrumentDescriptor): SumAggregator;
}
/**
* The default last value aggregation.
*/
export declare class LastValueAggregation implements Aggregation {
private static DEFAULT_INSTANCE;
createAggregator(_instrument: InstrumentDescriptor): LastValueAggregator;
}
/**
* The default histogram aggregation.
*/
export declare class HistogramAggregation implements Aggregation {
private static DEFAULT_INSTANCE;
createAggregator(_instrument: InstrumentDescriptor): HistogramAggregator;
}
/**
* The explicit bucket histogram aggregation.
*/
export declare class ExplicitBucketHistogramAggregation implements Aggregation {
private _boundaries;
private readonly _recordMinMax;
/**
* @param boundaries the bucket boundaries of the histogram aggregation
* @param _recordMinMax If set to true, min and max will be recorded. Otherwise, min and max will not be recorded.
*/
constructor(boundaries: number[], recordMinMax?: boolean);
createAggregator(_instrument: InstrumentDescriptor): HistogramAggregator;
}
export declare class ExponentialHistogramAggregation implements Aggregation {
private readonly _maxSize;
private readonly _recordMinMax;
constructor(maxSize?: number, recordMinMax?: boolean);
createAggregator(_instrument: InstrumentDescriptor): ExponentialHistogramAggregator;
}
/**
* The default aggregation.
*/
export declare class DefaultAggregation implements Aggregation {
private _resolve;
createAggregator(instrument: InstrumentDescriptor): Aggregator<Maybe<Accumulation>>;
}
export declare const DROP_AGGREGATION: DropAggregation;
export declare const SUM_AGGREGATION: SumAggregation;
export declare const LAST_VALUE_AGGREGATION: LastValueAggregation;
export declare const HISTOGRAM_AGGREGATION: HistogramAggregation;
export declare const EXPONENTIAL_HISTOGRAM_AGGREGATION: ExponentialHistogramAggregation;
export declare const DEFAULT_AGGREGATION: DefaultAggregation;
//# sourceMappingURL=Aggregation.d.ts.map

View File

@@ -0,0 +1,139 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import * as api from '@opentelemetry/api';
import { SumAggregator, DropAggregator, LastValueAggregator, HistogramAggregator, ExponentialHistogramAggregator, } from '../aggregator';
import { InstrumentType } from '../export/MetricData';
/**
* The default drop aggregation.
*/
class DropAggregation {
static DEFAULT_INSTANCE = new DropAggregator();
createAggregator(_instrument) {
return DropAggregation.DEFAULT_INSTANCE;
}
}
export { DropAggregation };
/**
* The default sum aggregation.
*/
class SumAggregation {
static MONOTONIC_INSTANCE = new SumAggregator(true);
static NON_MONOTONIC_INSTANCE = new SumAggregator(false);
createAggregator(instrument) {
switch (instrument.type) {
case InstrumentType.COUNTER:
case InstrumentType.OBSERVABLE_COUNTER:
case InstrumentType.HISTOGRAM: {
return SumAggregation.MONOTONIC_INSTANCE;
}
default: {
return SumAggregation.NON_MONOTONIC_INSTANCE;
}
}
}
}
export { SumAggregation };
/**
* The default last value aggregation.
*/
class LastValueAggregation {
static DEFAULT_INSTANCE = new LastValueAggregator();
createAggregator(_instrument) {
return LastValueAggregation.DEFAULT_INSTANCE;
}
}
export { LastValueAggregation };
/**
* The default histogram aggregation.
*/
class HistogramAggregation {
static DEFAULT_INSTANCE = new HistogramAggregator([0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000], true);
createAggregator(_instrument) {
return HistogramAggregation.DEFAULT_INSTANCE;
}
}
export { HistogramAggregation };
/**
* The explicit bucket histogram aggregation.
*/
export class ExplicitBucketHistogramAggregation {
_boundaries;
_recordMinMax;
/**
* @param boundaries the bucket boundaries of the histogram aggregation
* @param _recordMinMax If set to true, min and max will be recorded. Otherwise, min and max will not be recorded.
*/
constructor(boundaries, recordMinMax = true) {
if (boundaries == null) {
throw new Error('ExplicitBucketHistogramAggregation should be created with explicit boundaries, if a single bucket histogram is required, please pass an empty array');
}
// Copy the boundaries array for modification.
boundaries = boundaries.concat();
// We need to an ordered set to be able to correctly compute count for each
// boundary since we'll iterate on each in order.
boundaries = boundaries.sort((a, b) => a - b);
// Remove all Infinity from the boundaries.
const minusInfinityIndex = boundaries.lastIndexOf(-Infinity);
let infinityIndex = boundaries.indexOf(Infinity);
if (infinityIndex === -1) {
infinityIndex = undefined;
}
this._boundaries = boundaries.slice(minusInfinityIndex + 1, infinityIndex);
this._recordMinMax = recordMinMax;
}
createAggregator(_instrument) {
return new HistogramAggregator(this._boundaries, this._recordMinMax);
}
}
export class ExponentialHistogramAggregation {
_maxSize;
_recordMinMax;
constructor(maxSize = 160, recordMinMax = true) {
this._maxSize = maxSize;
this._recordMinMax = recordMinMax;
}
createAggregator(_instrument) {
return new ExponentialHistogramAggregator(this._maxSize, this._recordMinMax);
}
}
/**
* The default aggregation.
*/
export class DefaultAggregation {
_resolve(instrument) {
// cast to unknown to disable complaints on the (unreachable) fallback.
switch (instrument.type) {
case InstrumentType.COUNTER:
case InstrumentType.UP_DOWN_COUNTER:
case InstrumentType.OBSERVABLE_COUNTER:
case InstrumentType.OBSERVABLE_UP_DOWN_COUNTER: {
return SUM_AGGREGATION;
}
case InstrumentType.GAUGE:
case InstrumentType.OBSERVABLE_GAUGE: {
return LAST_VALUE_AGGREGATION;
}
case InstrumentType.HISTOGRAM: {
if (instrument.advice.explicitBucketBoundaries) {
return new ExplicitBucketHistogramAggregation(instrument.advice.explicitBucketBoundaries);
}
return HISTOGRAM_AGGREGATION;
}
}
api.diag.warn(`Unable to recognize instrument type: ${instrument.type}`);
return DROP_AGGREGATION;
}
createAggregator(instrument) {
return this._resolve(instrument).createAggregator(instrument);
}
}
export const DROP_AGGREGATION = new DropAggregation();
export const SUM_AGGREGATION = new SumAggregation();
export const LAST_VALUE_AGGREGATION = new LastValueAggregation();
export const HISTOGRAM_AGGREGATION = new HistogramAggregation();
export const EXPONENTIAL_HISTOGRAM_AGGREGATION = new ExponentialHistogramAggregation();
export const DEFAULT_AGGREGATION = new DefaultAggregation();
//# sourceMappingURL=Aggregation.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,38 @@
import type { Aggregation } from './Aggregation';
export declare enum AggregationType {
DEFAULT = 0,
DROP = 1,
SUM = 2,
LAST_VALUE = 3,
EXPLICIT_BUCKET_HISTOGRAM = 4,
EXPONENTIAL_HISTOGRAM = 5
}
export type SumAggregationOption = {
type: AggregationType.SUM;
};
export type LastValueAggregationOption = {
type: AggregationType.LAST_VALUE;
};
export type DropAggregationOption = {
type: AggregationType.DROP;
};
export type DefaultAggregationOption = {
type: AggregationType.DEFAULT;
};
export type HistogramAggregationOption = {
type: AggregationType.EXPLICIT_BUCKET_HISTOGRAM;
options?: {
recordMinMax?: boolean;
boundaries: number[];
};
};
export type ExponentialHistogramAggregationOption = {
type: AggregationType.EXPONENTIAL_HISTOGRAM;
options?: {
recordMinMax?: boolean;
maxSize?: number;
};
};
export type AggregationOption = ExponentialHistogramAggregationOption | HistogramAggregationOption | SumAggregationOption | DropAggregationOption | DefaultAggregationOption | LastValueAggregationOption;
export declare function toAggregation(option: AggregationOption): Aggregation;
//# sourceMappingURL=AggregationOption.d.ts.map

View File

@@ -0,0 +1,38 @@
import { DEFAULT_AGGREGATION, DROP_AGGREGATION, ExplicitBucketHistogramAggregation, ExponentialHistogramAggregation, HISTOGRAM_AGGREGATION, LAST_VALUE_AGGREGATION, SUM_AGGREGATION, } from './Aggregation';
export var AggregationType;
(function (AggregationType) {
AggregationType[AggregationType["DEFAULT"] = 0] = "DEFAULT";
AggregationType[AggregationType["DROP"] = 1] = "DROP";
AggregationType[AggregationType["SUM"] = 2] = "SUM";
AggregationType[AggregationType["LAST_VALUE"] = 3] = "LAST_VALUE";
AggregationType[AggregationType["EXPLICIT_BUCKET_HISTOGRAM"] = 4] = "EXPLICIT_BUCKET_HISTOGRAM";
AggregationType[AggregationType["EXPONENTIAL_HISTOGRAM"] = 5] = "EXPONENTIAL_HISTOGRAM";
})(AggregationType || (AggregationType = {}));
export function toAggregation(option) {
switch (option.type) {
case AggregationType.DEFAULT:
return DEFAULT_AGGREGATION;
case AggregationType.DROP:
return DROP_AGGREGATION;
case AggregationType.SUM:
return SUM_AGGREGATION;
case AggregationType.LAST_VALUE:
return LAST_VALUE_AGGREGATION;
case AggregationType.EXPONENTIAL_HISTOGRAM: {
const expOption = option;
return new ExponentialHistogramAggregation(expOption.options?.maxSize, expOption.options?.recordMinMax);
}
case AggregationType.EXPLICIT_BUCKET_HISTOGRAM: {
const expOption = option;
if (expOption.options == null) {
return HISTOGRAM_AGGREGATION;
}
else {
return new ExplicitBucketHistogramAggregation(expOption.options?.boundaries, expOption.options?.recordMinMax);
}
}
default:
throw new Error('Unsupported Aggregation');
}
}
//# sourceMappingURL=AggregationOption.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"AggregationOption.js","sourceRoot":"","sources":["../../../src/view/AggregationOption.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,kCAAkC,EAClC,+BAA+B,EAC/B,qBAAqB,EACrB,sBAAsB,EACtB,eAAe,GAChB,MAAM,eAAe,CAAC;AAEvB,MAAM,CAAN,IAAY,eAOX;AAPD,WAAY,eAAe;IACzB,2DAAW,CAAA;IACX,qDAAQ,CAAA;IACR,mDAAO,CAAA;IACP,iEAAc,CAAA;IACd,+FAA6B,CAAA;IAC7B,uFAAyB,CAAA;AAC3B,CAAC,EAPW,eAAe,KAAf,eAAe,QAO1B;AA0CD,MAAM,UAAU,aAAa,CAAC,MAAyB;IACrD,QAAQ,MAAM,CAAC,IAAI,EAAE;QACnB,KAAK,eAAe,CAAC,OAAO;YAC1B,OAAO,mBAAmB,CAAC;QAC7B,KAAK,eAAe,CAAC,IAAI;YACvB,OAAO,gBAAgB,CAAC;QAC1B,KAAK,eAAe,CAAC,GAAG;YACtB,OAAO,eAAe,CAAC;QACzB,KAAK,eAAe,CAAC,UAAU;YAC7B,OAAO,sBAAsB,CAAC;QAChC,KAAK,eAAe,CAAC,qBAAqB,CAAC,CAAC;YAC1C,MAAM,SAAS,GAAG,MAA+C,CAAC;YAClE,OAAO,IAAI,+BAA+B,CACxC,SAAS,CAAC,OAAO,EAAE,OAAO,EAC1B,SAAS,CAAC,OAAO,EAAE,YAAY,CAChC,CAAC;SACH;QACD,KAAK,eAAe,CAAC,yBAAyB,CAAC,CAAC;YAC9C,MAAM,SAAS,GAAG,MAAoC,CAAC;YACvD,IAAI,SAAS,CAAC,OAAO,IAAI,IAAI,EAAE;gBAC7B,OAAO,qBAAqB,CAAC;aAC9B;iBAAM;gBACL,OAAO,IAAI,kCAAkC,CAC3C,SAAS,CAAC,OAAO,EAAE,UAAU,EAC7B,SAAS,CAAC,OAAO,EAAE,YAAY,CAChC,CAAC;aACH;SACF;QACD;YACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;KAC9C;AACH,CAAC","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Aggregation } from './Aggregation';\nimport {\n DEFAULT_AGGREGATION,\n DROP_AGGREGATION,\n ExplicitBucketHistogramAggregation,\n ExponentialHistogramAggregation,\n HISTOGRAM_AGGREGATION,\n LAST_VALUE_AGGREGATION,\n SUM_AGGREGATION,\n} from './Aggregation';\n\nexport enum AggregationType {\n DEFAULT = 0,\n DROP = 1,\n SUM = 2,\n LAST_VALUE = 3,\n EXPLICIT_BUCKET_HISTOGRAM = 4,\n EXPONENTIAL_HISTOGRAM = 5,\n}\n\nexport type SumAggregationOption = {\n type: AggregationType.SUM;\n};\n\nexport type LastValueAggregationOption = {\n type: AggregationType.LAST_VALUE;\n};\n\nexport type DropAggregationOption = {\n type: AggregationType.DROP;\n};\n\nexport type DefaultAggregationOption = {\n type: AggregationType.DEFAULT;\n};\n\nexport type HistogramAggregationOption = {\n type: AggregationType.EXPLICIT_BUCKET_HISTOGRAM;\n options?: {\n recordMinMax?: boolean;\n boundaries: number[];\n };\n};\n\nexport type ExponentialHistogramAggregationOption = {\n type: AggregationType.EXPONENTIAL_HISTOGRAM;\n options?: {\n recordMinMax?: boolean;\n maxSize?: number;\n };\n};\n\nexport type AggregationOption =\n | ExponentialHistogramAggregationOption\n | HistogramAggregationOption\n | SumAggregationOption\n | DropAggregationOption\n | DefaultAggregationOption\n | LastValueAggregationOption;\n\nexport function toAggregation(option: AggregationOption): Aggregation {\n switch (option.type) {\n case AggregationType.DEFAULT:\n return DEFAULT_AGGREGATION;\n case AggregationType.DROP:\n return DROP_AGGREGATION;\n case AggregationType.SUM:\n return SUM_AGGREGATION;\n case AggregationType.LAST_VALUE:\n return LAST_VALUE_AGGREGATION;\n case AggregationType.EXPONENTIAL_HISTOGRAM: {\n const expOption = option as ExponentialHistogramAggregationOption;\n return new ExponentialHistogramAggregation(\n expOption.options?.maxSize,\n expOption.options?.recordMinMax\n );\n }\n case AggregationType.EXPLICIT_BUCKET_HISTOGRAM: {\n const expOption = option as HistogramAggregationOption;\n if (expOption.options == null) {\n return HISTOGRAM_AGGREGATION;\n } else {\n return new ExplicitBucketHistogramAggregation(\n expOption.options?.boundaries,\n expOption.options?.recordMinMax\n );\n }\n }\n default:\n throw new Error('Unsupported Aggregation');\n }\n}\n"]}

View File

@@ -0,0 +1,40 @@
import type { Context, Attributes } from '@opentelemetry/api';
/**
* The {@link AttributesProcessor} is responsible for customizing which
* attribute(s) are to be reported as metrics dimension(s) and adding
* additional dimension(s) from the {@link Context}.
*/
export interface IAttributesProcessor {
/**
* Process the metric instrument attributes.
*
* @param incoming The metric instrument attributes.
* @param context The active context when the instrument is synchronous.
* `undefined` otherwise.
*/
process: (incoming: Attributes, context?: Context) => Attributes;
}
/**
* @internal
*
* Create an {@link IAttributesProcessor} that acts as a simple pass-through for attributes.
*/
export declare function createNoopAttributesProcessor(): IAttributesProcessor;
/**
* @internal
*
* Create an {@link IAttributesProcessor} that applies all processors from the provided list in order.
*
* @param processors Processors to apply in order.
*/
export declare function createMultiAttributesProcessor(processors: IAttributesProcessor[]): IAttributesProcessor;
/**
* Create an {@link IAttributesProcessor} that filters by allowed attribute names and drops any names that are not in the
* allow list.
*/
export declare function createAllowListAttributesProcessor(attributeAllowList: string[]): IAttributesProcessor;
/**
* Create an {@link IAttributesProcessor} that drops attributes based on the names provided in the deny list
*/
export declare function createDenyListAttributesProcessor(attributeDenyList: string[]): IAttributesProcessor;
//# sourceMappingURL=AttributesProcessor.d.ts.map

View File

@@ -0,0 +1,85 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
class NoopAttributesProcessor {
process(incoming, _context) {
return incoming;
}
}
class MultiAttributesProcessor {
_processors;
constructor(processors) {
this._processors = processors;
}
process(incoming, context) {
let filteredAttributes = incoming;
for (const processor of this._processors) {
filteredAttributes = processor.process(filteredAttributes, context);
}
return filteredAttributes;
}
}
class AllowListProcessor {
_allowedAttributeNames;
constructor(allowedAttributeNames) {
this._allowedAttributeNames = allowedAttributeNames;
}
process(incoming, _context) {
const filteredAttributes = {};
Object.keys(incoming).forEach(attributeName => {
if (this._allowedAttributeNames.includes(attributeName)) {
filteredAttributes[attributeName] = incoming[attributeName];
}
});
return filteredAttributes;
}
}
class DenyListProcessor {
_deniedAttributeNames;
constructor(deniedAttributeNames) {
this._deniedAttributeNames = deniedAttributeNames;
}
process(incoming, _context) {
const filteredAttributes = {};
Object.keys(incoming).forEach(attributeName => {
if (!this._deniedAttributeNames.includes(attributeName)) {
filteredAttributes[attributeName] = incoming[attributeName];
}
});
return filteredAttributes;
}
}
/**
* @internal
*
* Create an {@link IAttributesProcessor} that acts as a simple pass-through for attributes.
*/
export function createNoopAttributesProcessor() {
return NOOP;
}
/**
* @internal
*
* Create an {@link IAttributesProcessor} that applies all processors from the provided list in order.
*
* @param processors Processors to apply in order.
*/
export function createMultiAttributesProcessor(processors) {
return new MultiAttributesProcessor(processors);
}
/**
* Create an {@link IAttributesProcessor} that filters by allowed attribute names and drops any names that are not in the
* allow list.
*/
export function createAllowListAttributesProcessor(attributeAllowList) {
return new AllowListProcessor(attributeAllowList);
}
/**
* Create an {@link IAttributesProcessor} that drops attributes based on the names provided in the deny list
*/
export function createDenyListAttributesProcessor(attributeDenyList) {
return new DenyListProcessor(attributeDenyList);
}
const NOOP = new NoopAttributesProcessor();
//# sourceMappingURL=AttributesProcessor.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,17 @@
import type { Predicate } from './Predicate';
import type { InstrumentType } from '../export/MetricData';
export interface InstrumentSelectorCriteria {
name?: string;
type?: InstrumentType;
unit?: string;
}
export declare class InstrumentSelector {
private _nameFilter;
private _type?;
private _unitFilter;
constructor(criteria?: InstrumentSelectorCriteria);
getType(): InstrumentType | undefined;
getNameFilter(): Predicate;
getUnitFilter(): Predicate;
}
//# sourceMappingURL=InstrumentSelector.d.ts.map

View File

@@ -0,0 +1,25 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { ExactPredicate, PatternPredicate } from './Predicate';
export class InstrumentSelector {
_nameFilter;
_type;
_unitFilter;
constructor(criteria) {
this._nameFilter = new PatternPredicate(criteria?.name ?? '*');
this._type = criteria?.type;
this._unitFilter = new ExactPredicate(criteria?.unit);
}
getType() {
return this._type;
}
getNameFilter() {
return this._nameFilter;
}
getUnitFilter() {
return this._unitFilter;
}
}
//# sourceMappingURL=InstrumentSelector.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"InstrumentSelector.js","sourceRoot":"","sources":["../../../src/view/InstrumentSelector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAS/D,MAAM,OAAO,kBAAkB;IACrB,WAAW,CAAY;IACvB,KAAK,CAAkB;IACvB,WAAW,CAAY;IAE/B,YAAY,QAAqC;QAC/C,IAAI,CAAC,WAAW,GAAG,IAAI,gBAAgB,CAAC,QAAQ,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,GAAG,QAAQ,EAAE,IAAI,CAAC;QAC5B,IAAI,CAAC,WAAW,GAAG,IAAI,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACxD,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;CACF","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Predicate } from './Predicate';\nimport { ExactPredicate, PatternPredicate } from './Predicate';\nimport type { InstrumentType } from '../export/MetricData';\n\nexport interface InstrumentSelectorCriteria {\n name?: string;\n type?: InstrumentType;\n unit?: string;\n}\n\nexport class InstrumentSelector {\n private _nameFilter: Predicate;\n private _type?: InstrumentType;\n private _unitFilter: Predicate;\n\n constructor(criteria?: InstrumentSelectorCriteria) {\n this._nameFilter = new PatternPredicate(criteria?.name ?? '*');\n this._type = criteria?.type;\n this._unitFilter = new ExactPredicate(criteria?.unit);\n }\n\n getType() {\n return this._type;\n }\n\n getNameFilter() {\n return this._nameFilter;\n }\n\n getUnitFilter() {\n return this._unitFilter;\n }\n}\n"]}

View File

@@ -0,0 +1,19 @@
import type { Predicate } from './Predicate';
export interface MeterSelectorCriteria {
name?: string;
version?: string;
schemaUrl?: string;
}
export declare class MeterSelector {
private _nameFilter;
private _versionFilter;
private _schemaUrlFilter;
constructor(criteria?: MeterSelectorCriteria);
getNameFilter(): Predicate;
/**
* TODO: semver filter? no spec yet.
*/
getVersionFilter(): Predicate;
getSchemaUrlFilter(): Predicate;
}
//# sourceMappingURL=MeterSelector.d.ts.map

View File

@@ -0,0 +1,28 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { ExactPredicate } from './Predicate';
export class MeterSelector {
_nameFilter;
_versionFilter;
_schemaUrlFilter;
constructor(criteria) {
this._nameFilter = new ExactPredicate(criteria?.name);
this._versionFilter = new ExactPredicate(criteria?.version);
this._schemaUrlFilter = new ExactPredicate(criteria?.schemaUrl);
}
getNameFilter() {
return this._nameFilter;
}
/**
* TODO: semver filter? no spec yet.
*/
getVersionFilter() {
return this._versionFilter;
}
getSchemaUrlFilter() {
return this._schemaUrlFilter;
}
}
//# sourceMappingURL=MeterSelector.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"MeterSelector.js","sourceRoot":"","sources":["../../../src/view/MeterSelector.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAQ7C,MAAM,OAAO,aAAa;IAChB,WAAW,CAAY;IACvB,cAAc,CAAY;IAC1B,gBAAgB,CAAY;IAEpC,YAAY,QAAgC;QAC1C,IAAI,CAAC,WAAW,GAAG,IAAI,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,cAAc,GAAG,IAAI,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5D,IAAI,CAAC,gBAAgB,GAAG,IAAI,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAClE,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,kBAAkB;QAChB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;CACF","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Predicate } from './Predicate';\nimport { ExactPredicate } from './Predicate';\n\nexport interface MeterSelectorCriteria {\n name?: string;\n version?: string;\n schemaUrl?: string;\n}\n\nexport class MeterSelector {\n private _nameFilter: Predicate;\n private _versionFilter: Predicate;\n private _schemaUrlFilter: Predicate;\n\n constructor(criteria?: MeterSelectorCriteria) {\n this._nameFilter = new ExactPredicate(criteria?.name);\n this._versionFilter = new ExactPredicate(criteria?.version);\n this._schemaUrlFilter = new ExactPredicate(criteria?.schemaUrl);\n }\n\n getNameFilter() {\n return this._nameFilter;\n }\n\n /**\n * TODO: semver filter? no spec yet.\n */\n getVersionFilter() {\n return this._versionFilter;\n }\n\n getSchemaUrlFilter() {\n return this._schemaUrlFilter;\n }\n}\n"]}

View File

@@ -0,0 +1,21 @@
export interface Predicate {
match(str: string): boolean;
}
/**
* Wildcard pattern predicate, supports patterns like `*`, `foo*`, `*bar`.
*/
export declare class PatternPredicate implements Predicate {
private _matchAll;
private _regexp;
constructor(pattern: string);
match(str: string): boolean;
static escapePattern(pattern: string): string;
static hasWildcard(pattern: string): boolean;
}
export declare class ExactPredicate implements Predicate {
private _matchAll;
private _pattern?;
constructor(pattern?: string);
match(str: string): boolean;
}
//# sourceMappingURL=Predicate.d.ts.map

View File

@@ -0,0 +1,55 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
// https://tc39.es/proposal-regex-escaping
// escape ^ $ \ . + ? ( ) [ ] { } |
// do not need to escape * as we interpret it as wildcard
const ESCAPE = /[\^$\\.+?()[\]{}|]/g;
/**
* Wildcard pattern predicate, supports patterns like `*`, `foo*`, `*bar`.
*/
export class PatternPredicate {
_matchAll;
_regexp;
constructor(pattern) {
if (pattern === '*') {
this._matchAll = true;
this._regexp = /.*/;
}
else {
this._matchAll = false;
this._regexp = new RegExp(PatternPredicate.escapePattern(pattern));
}
}
match(str) {
if (this._matchAll) {
return true;
}
return this._regexp.test(str);
}
static escapePattern(pattern) {
return `^${pattern.replace(ESCAPE, '\\$&').replace('*', '.*')}$`;
}
static hasWildcard(pattern) {
return pattern.includes('*');
}
}
export class ExactPredicate {
_matchAll;
_pattern;
constructor(pattern) {
this._matchAll = pattern === undefined;
this._pattern = pattern;
}
match(str) {
if (this._matchAll) {
return true;
}
if (str === this._pattern) {
return true;
}
return false;
}
}
//# sourceMappingURL=Predicate.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"Predicate.js","sourceRoot":"","sources":["../../../src/view/Predicate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,0CAA0C;AAC1C,oCAAoC;AACpC,yDAAyD;AACzD,MAAM,MAAM,GAAG,qBAAqB,CAAC;AAMrC;;GAEG;AACH,MAAM,OAAO,gBAAgB;IACnB,SAAS,CAAU;IACnB,OAAO,CAAS;IAExB,YAAY,OAAe;QACzB,IAAI,OAAO,KAAK,GAAG,EAAE;YACnB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;SACrB;aAAM;YACL,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;YACvB,IAAI,CAAC,OAAO,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;SACpE;IACH,CAAC;IAED,KAAK,CAAC,GAAW;QACf,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB,OAAO,IAAI,CAAC;SACb;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,CAAC,aAAa,CAAC,OAAe;QAClC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC;IACnE,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,OAAe;QAChC,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,cAAc;IACjB,SAAS,CAAU;IACnB,QAAQ,CAAU;IAE1B,YAAY,OAAgB;QAC1B,IAAI,CAAC,SAAS,GAAG,OAAO,KAAK,SAAS,CAAC;QACvC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED,KAAK,CAAC,GAAW;QACf,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB,OAAO,IAAI,CAAC;SACb;QACD,IAAI,GAAG,KAAK,IAAI,CAAC,QAAQ,EAAE;YACzB,OAAO,IAAI,CAAC;SACb;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\n// https://tc39.es/proposal-regex-escaping\n// escape ^ $ \\ . + ? ( ) [ ] { } |\n// do not need to escape * as we interpret it as wildcard\nconst ESCAPE = /[\\^$\\\\.+?()[\\]{}|]/g;\n\nexport interface Predicate {\n match(str: string): boolean;\n}\n\n/**\n * Wildcard pattern predicate, supports patterns like `*`, `foo*`, `*bar`.\n */\nexport class PatternPredicate implements Predicate {\n private _matchAll: boolean;\n private _regexp: RegExp;\n\n constructor(pattern: string) {\n if (pattern === '*') {\n this._matchAll = true;\n this._regexp = /.*/;\n } else {\n this._matchAll = false;\n this._regexp = new RegExp(PatternPredicate.escapePattern(pattern));\n }\n }\n\n match(str: string): boolean {\n if (this._matchAll) {\n return true;\n }\n\n return this._regexp.test(str);\n }\n\n static escapePattern(pattern: string): string {\n return `^${pattern.replace(ESCAPE, '\\\\$&').replace('*', '.*')}$`;\n }\n\n static hasWildcard(pattern: string): boolean {\n return pattern.includes('*');\n }\n}\n\nexport class ExactPredicate implements Predicate {\n private _matchAll: boolean;\n private _pattern?: string;\n\n constructor(pattern?: string) {\n this._matchAll = pattern === undefined;\n this._pattern = pattern;\n }\n\n match(str: string): boolean {\n if (this._matchAll) {\n return true;\n }\n if (str === this._pattern) {\n return true;\n }\n return false;\n }\n}\n"]}

View File

@@ -0,0 +1,8 @@
import type { InstrumentDescriptor } from '../InstrumentDescriptor';
export declare function getIncompatibilityDetails(existing: InstrumentDescriptor, otherDescriptor: InstrumentDescriptor): string;
export declare function getValueTypeConflictResolutionRecipe(existing: InstrumentDescriptor, otherDescriptor: InstrumentDescriptor): string;
export declare function getUnitConflictResolutionRecipe(existing: InstrumentDescriptor, otherDescriptor: InstrumentDescriptor): string;
export declare function getTypeConflictResolutionRecipe(existing: InstrumentDescriptor, otherDescriptor: InstrumentDescriptor): string;
export declare function getDescriptionResolutionRecipe(existing: InstrumentDescriptor, otherDescriptor: InstrumentDescriptor): string;
export declare function getConflictResolutionRecipe(existing: InstrumentDescriptor, otherDescriptor: InstrumentDescriptor): string;
//# sourceMappingURL=RegistrationConflicts.d.ts.map

View File

@@ -0,0 +1,65 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
export function getIncompatibilityDetails(existing, otherDescriptor) {
let incompatibility = '';
if (existing.unit !== otherDescriptor.unit) {
incompatibility += `\t- Unit '${existing.unit}' does not match '${otherDescriptor.unit}'\n`;
}
if (existing.type !== otherDescriptor.type) {
incompatibility += `\t- Type '${existing.type}' does not match '${otherDescriptor.type}'\n`;
}
if (existing.valueType !== otherDescriptor.valueType) {
incompatibility += `\t- Value Type '${existing.valueType}' does not match '${otherDescriptor.valueType}'\n`;
}
if (existing.description !== otherDescriptor.description) {
incompatibility += `\t- Description '${existing.description}' does not match '${otherDescriptor.description}'\n`;
}
return incompatibility;
}
export function getValueTypeConflictResolutionRecipe(existing, otherDescriptor) {
return `\t- use valueType '${existing.valueType}' on instrument creation or use an instrument name other than '${otherDescriptor.name}'`;
}
export function getUnitConflictResolutionRecipe(existing, otherDescriptor) {
return `\t- use unit '${existing.unit}' on instrument creation or use an instrument name other than '${otherDescriptor.name}'`;
}
export function getTypeConflictResolutionRecipe(existing, otherDescriptor) {
const selector = {
name: otherDescriptor.name,
type: otherDescriptor.type,
unit: otherDescriptor.unit,
};
const selectorString = JSON.stringify(selector);
return `\t- create a new view with a name other than '${existing.name}' and InstrumentSelector '${selectorString}'`;
}
export function getDescriptionResolutionRecipe(existing, otherDescriptor) {
const selector = {
name: otherDescriptor.name,
type: otherDescriptor.type,
unit: otherDescriptor.unit,
};
const selectorString = JSON.stringify(selector);
return `\t- create a new view with a name other than '${existing.name}' and InstrumentSelector '${selectorString}'
\t- OR - create a new view with the name ${existing.name} and description '${existing.description}' and InstrumentSelector ${selectorString}
\t- OR - create a new view with the name ${otherDescriptor.name} and description '${existing.description}' and InstrumentSelector ${selectorString}`;
}
export function getConflictResolutionRecipe(existing, otherDescriptor) {
// Conflicts that cannot be solved via views.
if (existing.valueType !== otherDescriptor.valueType) {
return getValueTypeConflictResolutionRecipe(existing, otherDescriptor);
}
if (existing.unit !== otherDescriptor.unit) {
return getUnitConflictResolutionRecipe(existing, otherDescriptor);
}
// Conflicts that can be solved via views.
if (existing.type !== otherDescriptor.type) {
// this will automatically solve possible description conflicts.
return getTypeConflictResolutionRecipe(existing, otherDescriptor);
}
if (existing.description !== otherDescriptor.description) {
return getDescriptionResolutionRecipe(existing, otherDescriptor);
}
return '';
}
//# sourceMappingURL=RegistrationConflicts.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,180 @@
import type { IAttributesProcessor } from './AttributesProcessor';
import { InstrumentSelector } from './InstrumentSelector';
import { MeterSelector } from './MeterSelector';
import type { Aggregation } from './Aggregation';
import type { AggregationOption } from './AggregationOption';
import type { InstrumentType } from '../export/MetricData';
export type ViewOptions = {
/**
* Alters the metric stream:
* This will be used as the name of the metrics stream.
* If not provided, the original Instrument name will be used.
*/
name?: string;
/**
* Alters the metric stream:
* This will be used as the description of the metrics stream.
* If not provided, the original Instrument description will be used by default.
*
* @example <caption>changes the description of all selected instruments to 'sample description'</caption>
* description: 'sample description'
*/
description?: string;
/**
* Alters the metric stream:
* If provided, the attributes will be modified as defined by the processors in the list. Processors are applied
* in the order they're provided.
* If not provided, all attribute keys will be used by default.
*
* @example <caption>drops all attributes with top-level keys except for 'myAttr' and 'myOtherAttr'</caption>
* attributesProcessors: [createAllowListProcessor(['myAttr', 'myOtherAttr'])]
* @example <caption>drops all attributes</caption>
* attributesProcessors: [createAllowListProcessor([])]
* @example <caption>allows all attributes except for 'myAttr'</caption>
* attributesProcessors: [createDenyListProcessor(['myAttr']]
*/
attributesProcessors?: IAttributesProcessor[];
/**
* Alters the metric stream:
* Alters the Aggregation of the metric stream.
*
* @example <caption>changes the aggregation of the selected instrument(s) to ExplicitBucketHistogramAggregation</caption>
* aggregation: { type: AggregationType.EXPLICIT_BUCKET_HISTOGRAM, options: { boundaries: [1, 10, 100] } }
* @example <caption>changes the aggregation of the selected instrument(s) to LastValueAggregation</caption>
* aggregation: { type: AggregationType.LAST_VALUE, options: { boundaries: [1, 10, 100] } }
*/
aggregation?: AggregationOption;
/**
* Alters the metric stream:
* Sets a limit on the number of unique attribute combinations (cardinality) that can be aggregated.
* If not provided, the default limit will be used.
*
* @example <caption>sets the cardinality limit to 1000</caption>
* aggregationCardinalityLimit: 1000
*/
aggregationCardinalityLimit?: number;
/**
* Instrument selection criteria:
* The original type of the Instrument(s).
*
* @example <caption>selects all counters</caption>
* instrumentType: InstrumentType.COUNTER
* @example <caption>selects all histograms</caption>
* instrumentType: InstrumentType.HISTOGRAM
*/
instrumentType?: InstrumentType;
/**
* Instrument selection criteria:
* Original name of the Instrument(s) with wildcard support.
*
* @example <caption>select all instruments</caption>
* instrumentName: '*'
* @example <caption>select all instruments starting with 'my.instruments.'</caption>
* instrumentName: 'my.instruments.*'
* @example <caption>select all instruments named 'my.instrument.requests' exactly</caption>
* instrumentName: 'my.instruments.requests'
*/
instrumentName?: string;
/**
* Instrument selection criteria:
* The unit of the Instrument(s).
*
* @example <caption>select all instruments with unit 'ms'</caption>
* instrumentUnit: 'ms'
*/
instrumentUnit?: string;
/**
* Instrument selection criteria:
* The name of the Meter. No wildcard support, name must match the meter exactly.
*
* @example <caption>select all meters named 'example.component.app' exactly</caption>
* meterName: 'example.component.app'
*/
meterName?: string;
/**
* Instrument selection criteria:
* The version of the Meter. No wildcard support, version must match exactly.
*
* @example
* meterVersion: '1.0.1'
*/
meterVersion?: string;
/**
* Instrument selection criteria:
* The schema URL of the Meter. No wildcard support, schema URL must match exactly.
*
* @example <caption>Select all meters with schema URL 'https://example.com/schema' exactly.</caption>
* meterSchemaUrl: 'https://example.com/schema'
*/
meterSchemaUrl?: string;
};
/**
* Can be passed to a {@link MeterProvider} to select instruments and alter their metric stream.
*/
export declare class View {
readonly name?: string;
readonly description?: string;
readonly aggregation: Aggregation;
readonly attributesProcessor: IAttributesProcessor;
readonly instrumentSelector: InstrumentSelector;
readonly meterSelector: MeterSelector;
readonly aggregationCardinalityLimit?: number;
/**
* Create a new {@link View} instance.
*
* Parameters can be categorized as two types:
* Instrument selection criteria: Used to describe the instrument(s) this view will be applied to.
* Will be treated as additive (the Instrument has to meet all the provided criteria to be selected).
*
* Metric stream altering: Alter the metric stream of instruments selected by instrument selection criteria.
*
* @param viewOptions {@link ViewOptions} for altering the metric stream and instrument selection.
* @param viewOptions.name
* Alters the metric stream:
* This will be used as the name of the metrics stream.
* If not provided, the original Instrument name will be used.
* @param viewOptions.description
* Alters the metric stream:
* This will be used as the description of the metrics stream.
* If not provided, the original Instrument description will be used by default.
* @param viewOptions.attributesProcessors
* Alters the metric stream:
* If provided, the attributes will be modified as defined by the added processors.
* If not provided, all attribute keys will be used by default.
* @param viewOptions.aggregationCardinalityLimit
* Alters the metric stream:
* Sets a limit on the number of unique attribute combinations (cardinality) that can be aggregated.
* If not provided, the default limit of 2000 will be used.
* @param viewOptions.aggregation
* Alters the metric stream:
* Alters the {@link Aggregation} of the metric stream.
* @param viewOptions.instrumentName
* Instrument selection criteria:
* Original name of the Instrument(s) with wildcard support.
* @param viewOptions.instrumentType
* Instrument selection criteria:
* The original type of the Instrument(s).
* @param viewOptions.instrumentUnit
* Instrument selection criteria:
* The unit of the Instrument(s).
* @param viewOptions.meterName
* Instrument selection criteria:
* The name of the Meter. No wildcard support, name must match the meter exactly.
* @param viewOptions.meterVersion
* Instrument selection criteria:
* The version of the Meter. No wildcard support, version must match exactly.
* @param viewOptions.meterSchemaUrl
* Instrument selection criteria:
* The schema URL of the Meter. No wildcard support, schema URL must match exactly.
*
* @example
* // Create a view that changes the Instrument 'my.instrument' to use to an
* // ExplicitBucketHistogramAggregation with the boundaries [20, 30, 40]
* new View({
* aggregation: new ExplicitBucketHistogramAggregation([20, 30, 40]),
* instrumentName: 'my.instrument'
* })
*/
constructor(viewOptions: ViewOptions);
}
//# sourceMappingURL=View.d.ts.map

View File

@@ -0,0 +1,124 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import { PatternPredicate } from './Predicate';
import { createMultiAttributesProcessor, createNoopAttributesProcessor, } from './AttributesProcessor';
import { InstrumentSelector } from './InstrumentSelector';
import { MeterSelector } from './MeterSelector';
import { AggregationType, toAggregation } from './AggregationOption';
function isSelectorNotProvided(options) {
return (options.instrumentName == null &&
options.instrumentType == null &&
options.instrumentUnit == null &&
options.meterName == null &&
options.meterVersion == null &&
options.meterSchemaUrl == null);
}
function validateViewOptions(viewOptions) {
// If no criteria is provided, the SDK SHOULD treat it as an error.
// It is recommended that the SDK implementations fail fast.
if (isSelectorNotProvided(viewOptions)) {
throw new Error('Cannot create view with no selector arguments supplied');
}
// the SDK SHOULD NOT allow Views with a specified name to be declared with instrument selectors that
// may select more than one instrument (e.g. wild card instrument name) in the same Meter.
if (viewOptions.name != null &&
(viewOptions?.instrumentName == null ||
PatternPredicate.hasWildcard(viewOptions.instrumentName))) {
throw new Error('Views with a specified name must be declared with an instrument selector that selects at most one instrument per meter.');
}
}
/**
* Can be passed to a {@link MeterProvider} to select instruments and alter their metric stream.
*/
export class View {
name;
description;
aggregation;
attributesProcessor;
instrumentSelector;
meterSelector;
aggregationCardinalityLimit;
/**
* Create a new {@link View} instance.
*
* Parameters can be categorized as two types:
* Instrument selection criteria: Used to describe the instrument(s) this view will be applied to.
* Will be treated as additive (the Instrument has to meet all the provided criteria to be selected).
*
* Metric stream altering: Alter the metric stream of instruments selected by instrument selection criteria.
*
* @param viewOptions {@link ViewOptions} for altering the metric stream and instrument selection.
* @param viewOptions.name
* Alters the metric stream:
* This will be used as the name of the metrics stream.
* If not provided, the original Instrument name will be used.
* @param viewOptions.description
* Alters the metric stream:
* This will be used as the description of the metrics stream.
* If not provided, the original Instrument description will be used by default.
* @param viewOptions.attributesProcessors
* Alters the metric stream:
* If provided, the attributes will be modified as defined by the added processors.
* If not provided, all attribute keys will be used by default.
* @param viewOptions.aggregationCardinalityLimit
* Alters the metric stream:
* Sets a limit on the number of unique attribute combinations (cardinality) that can be aggregated.
* If not provided, the default limit of 2000 will be used.
* @param viewOptions.aggregation
* Alters the metric stream:
* Alters the {@link Aggregation} of the metric stream.
* @param viewOptions.instrumentName
* Instrument selection criteria:
* Original name of the Instrument(s) with wildcard support.
* @param viewOptions.instrumentType
* Instrument selection criteria:
* The original type of the Instrument(s).
* @param viewOptions.instrumentUnit
* Instrument selection criteria:
* The unit of the Instrument(s).
* @param viewOptions.meterName
* Instrument selection criteria:
* The name of the Meter. No wildcard support, name must match the meter exactly.
* @param viewOptions.meterVersion
* Instrument selection criteria:
* The version of the Meter. No wildcard support, version must match exactly.
* @param viewOptions.meterSchemaUrl
* Instrument selection criteria:
* The schema URL of the Meter. No wildcard support, schema URL must match exactly.
*
* @example
* // Create a view that changes the Instrument 'my.instrument' to use to an
* // ExplicitBucketHistogramAggregation with the boundaries [20, 30, 40]
* new View({
* aggregation: new ExplicitBucketHistogramAggregation([20, 30, 40]),
* instrumentName: 'my.instrument'
* })
*/
constructor(viewOptions) {
validateViewOptions(viewOptions);
// Create multi-processor if attributesProcessors are defined.
if (viewOptions.attributesProcessors != null) {
this.attributesProcessor = createMultiAttributesProcessor(viewOptions.attributesProcessors);
}
else {
this.attributesProcessor = createNoopAttributesProcessor();
}
this.name = viewOptions.name;
this.description = viewOptions.description;
this.aggregation = toAggregation(viewOptions.aggregation ?? { type: AggregationType.DEFAULT });
this.instrumentSelector = new InstrumentSelector({
name: viewOptions.instrumentName,
type: viewOptions.instrumentType,
unit: viewOptions.instrumentUnit,
});
this.meterSelector = new MeterSelector({
name: viewOptions.meterName,
version: viewOptions.meterVersion,
schemaUrl: viewOptions.meterSchemaUrl,
});
this.aggregationCardinalityLimit = viewOptions.aggregationCardinalityLimit;
}
}
//# sourceMappingURL=View.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
import type { InstrumentationScope } from '@opentelemetry/core';
import type { InstrumentDescriptor } from '../InstrumentDescriptor';
import type { View } from './View';
export declare class ViewRegistry {
private _registeredViews;
addView(view: View): void;
findViews(instrument: InstrumentDescriptor, meter: InstrumentationScope): View[];
private _matchInstrument;
private _matchMeter;
}
//# sourceMappingURL=ViewRegistry.d.ts.map

View File

@@ -0,0 +1,31 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
export class ViewRegistry {
_registeredViews = [];
addView(view) {
this._registeredViews.push(view);
}
findViews(instrument, meter) {
const views = this._registeredViews.filter(registeredView => {
return (this._matchInstrument(registeredView.instrumentSelector, instrument) &&
this._matchMeter(registeredView.meterSelector, meter));
});
return views;
}
_matchInstrument(selector, instrument) {
return ((selector.getType() === undefined ||
instrument.type === selector.getType()) &&
selector.getNameFilter().match(instrument.name) &&
selector.getUnitFilter().match(instrument.unit));
}
_matchMeter(selector, meter) {
return (selector.getNameFilter().match(meter.name) &&
(meter.version === undefined ||
selector.getVersionFilter().match(meter.version)) &&
(meter.schemaUrl === undefined ||
selector.getSchemaUrlFilter().match(meter.schemaUrl)));
}
}
//# sourceMappingURL=ViewRegistry.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ViewRegistry.js","sourceRoot":"","sources":["../../../src/view/ViewRegistry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,OAAO,YAAY;IACf,gBAAgB,GAAW,EAAE,CAAC;IAEtC,OAAO,CAAC,IAAU;QAChB,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,SAAS,CACP,UAAgC,EAChC,KAA2B;QAE3B,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE;YAC1D,OAAO,CACL,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC,kBAAkB,EAAE,UAAU,CAAC;gBACpE,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,aAAa,EAAE,KAAK,CAAC,CACtD,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,gBAAgB,CACtB,QAA4B,EAC5B,UAAgC;QAEhC,OAAO,CACL,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,SAAS;YAC/B,UAAU,CAAC,IAAI,KAAK,QAAQ,CAAC,OAAO,EAAE,CAAC;YACzC,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;YAC/C,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAChD,CAAC;IACJ,CAAC;IAEO,WAAW,CACjB,QAAuB,EACvB,KAA2B;QAE3B,OAAO,CACL,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;YAC1C,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS;gBAC1B,QAAQ,CAAC,gBAAgB,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACnD,CAAC,KAAK,CAAC,SAAS,KAAK,SAAS;gBAC5B,QAAQ,CAAC,kBAAkB,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CACxD,CAAC;IACJ,CAAC;CACF","sourcesContent":["/*\n * Copyright The OpenTelemetry Authors\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { InstrumentationScope } from '@opentelemetry/core';\nimport type { InstrumentDescriptor } from '../InstrumentDescriptor';\nimport type { InstrumentSelector } from './InstrumentSelector';\nimport type { MeterSelector } from './MeterSelector';\nimport type { View } from './View';\n\nexport class ViewRegistry {\n private _registeredViews: View[] = [];\n\n addView(view: View) {\n this._registeredViews.push(view);\n }\n\n findViews(\n instrument: InstrumentDescriptor,\n meter: InstrumentationScope\n ): View[] {\n const views = this._registeredViews.filter(registeredView => {\n return (\n this._matchInstrument(registeredView.instrumentSelector, instrument) &&\n this._matchMeter(registeredView.meterSelector, meter)\n );\n });\n\n return views;\n }\n\n private _matchInstrument(\n selector: InstrumentSelector,\n instrument: InstrumentDescriptor\n ): boolean {\n return (\n (selector.getType() === undefined ||\n instrument.type === selector.getType()) &&\n selector.getNameFilter().match(instrument.name) &&\n selector.getUnitFilter().match(instrument.unit)\n );\n }\n\n private _matchMeter(\n selector: MeterSelector,\n meter: InstrumentationScope\n ): boolean {\n return (\n selector.getNameFilter().match(meter.name) &&\n (meter.version === undefined ||\n selector.getVersionFilter().match(meter.version)) &&\n (meter.schemaUrl === undefined ||\n selector.getSchemaUrlFilter().match(meter.schemaUrl))\n );\n }\n}\n"]}