diff --git a/yarn-project/archiver/src/archiver/instrumentation.ts b/yarn-project/archiver/src/archiver/instrumentation.ts index 3d8768b4d2a..5dc3ab844c5 100644 --- a/yarn-project/archiver/src/archiver/instrumentation.ts +++ b/yarn-project/archiver/src/archiver/instrumentation.ts @@ -10,8 +10,6 @@ import { type TelemetryClient, type UpDownCounter, ValueType, - exponentialBuckets, - millisecondBuckets, } from '@aztec/telemetry-client'; export class ArchiverInstrumentation { @@ -41,9 +39,6 @@ export class ArchiverInstrumentation { unit: 'ms', description: 'Duration to sync a block', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: exponentialBuckets(1, 16), - }, }); this.proofsSubmittedCount = meter.createUpDownCounter(Metrics.ARCHIVER_ROLLUP_PROOF_COUNT, { @@ -55,9 +50,6 @@ export class ArchiverInstrumentation { unit: 'ms', description: 'Time after a block is submitted until its proof is published', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: millisecondBuckets(1, 80), // 10ms -> ~3hs - }, }); this.l1BlocksSynced = meter.createUpDownCounter(Metrics.ARCHIVER_L1_BLOCKS_SYNCED, { diff --git a/yarn-project/aztec-node/src/aztec-node/node_metrics.ts b/yarn-project/aztec-node/src/aztec-node/node_metrics.ts index 27df451152d..8bddcce063b 100644 --- a/yarn-project/aztec-node/src/aztec-node/node_metrics.ts +++ b/yarn-project/aztec-node/src/aztec-node/node_metrics.ts @@ -18,9 +18,6 @@ export class NodeMetrics { description: 'The duration of the receiveTx method', unit: 'ms', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: [10, 50, 100, 200, 500, 1000, 2000, 5000], - }, }); } diff --git a/yarn-project/bb-prover/src/instrumentation.ts b/yarn-project/bb-prover/src/instrumentation.ts index 3b2360e866c..782042da6f5 100644 --- a/yarn-project/bb-prover/src/instrumentation.ts +++ b/yarn-project/bb-prover/src/instrumentation.ts @@ -8,7 +8,6 @@ import { type TelemetryClient, type Tracer, ValueType, - millisecondBuckets, } from '@aztec/telemetry-client'; /** @@ -36,27 +35,18 @@ export class ProverInstrumentation { description: 'Records how long it takes to simulate a circuit', unit: 'ms', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: millisecondBuckets(1), // 10ms -> ~327s - }, }); this.witGenDuration = meter.createHistogram(Metrics.CIRCUIT_WITNESS_GEN_DURATION, { description: 'Records how long it takes to generate the partial witness for a circuit', unit: 'ms', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: millisecondBuckets(1), - }, }); this.provingDuration = meter.createHistogram(Metrics.CIRCUIT_PROVING_DURATION, { unit: 'ms', description: 'Records how long it takes to prove a circuit', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: millisecondBuckets(2), // 100ms -> 54 minutes - }, }); this.witGenInputSize = meter.createGauge(Metrics.CIRCUIT_WITNESS_GEN_INPUT_SIZE, { diff --git a/yarn-project/p2p/src/mem_pools/instrumentation.ts b/yarn-project/p2p/src/mem_pools/instrumentation.ts index 0d5fda2687e..431a3e95c89 100644 --- a/yarn-project/p2p/src/mem_pools/instrumentation.ts +++ b/yarn-project/p2p/src/mem_pools/instrumentation.ts @@ -72,17 +72,6 @@ export class PoolInstrumentation { this.objectSize = meter.createHistogram(metricsLabels.objectSize, { unit: 'By', description: 'The size of transactions in the mempool', - advice: { - explicitBucketBoundaries: [ - 5_000, // 5KB - 10_000, - 20_000, - 50_000, - 75_000, - 100_000, // 100KB - 200_000, - ], - }, }); this.dbMetrics = new LmdbMetrics( diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_metrics.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_metrics.ts index 08811291d82..749f4648706 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_metrics.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_metrics.ts @@ -1,11 +1,4 @@ -import { - type Histogram, - Metrics, - type TelemetryClient, - type Tracer, - ValueType, - millisecondBuckets, -} from '@aztec/telemetry-client'; +import { type Histogram, Metrics, type TelemetryClient, type Tracer, ValueType } from '@aztec/telemetry-client'; export class ProvingOrchestratorMetrics { public readonly tracer: Tracer; @@ -20,9 +13,6 @@ export class ProvingOrchestratorMetrics { unit: 'ms', description: 'Duration to build base rollup inputs', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: millisecondBuckets(1), // 10ms -> ~327s - }, }); } diff --git a/yarn-project/prover-client/src/proving_broker/proving_broker_instrumentation.ts b/yarn-project/prover-client/src/proving_broker/proving_broker_instrumentation.ts index 2379bdd8a32..5a17de276a6 100644 --- a/yarn-project/prover-client/src/proving_broker/proving_broker_instrumentation.ts +++ b/yarn-project/prover-client/src/proving_broker/proving_broker_instrumentation.ts @@ -9,7 +9,6 @@ import { type TelemetryClient, type UpDownCounter, ValueType, - millisecondBuckets, } from '@aztec/telemetry-client'; export type MonitorCallback = (proofType: ProvingRequestType) => number; @@ -55,18 +54,12 @@ export class ProvingBrokerInstrumentation { description: 'Records how long a job sits in the queue', unit: 'ms', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: millisecondBuckets(1), // 10ms -> ~327s - }, }); this.jobDuration = meter.createHistogram(Metrics.PROVING_QUEUE_JOB_DURATION, { description: 'Records how long a job takes to complete', unit: 'ms', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: millisecondBuckets(1), // 10ms -> ~327s - }, }); } diff --git a/yarn-project/prover-node/src/metrics.ts b/yarn-project/prover-node/src/metrics.ts index 8ce6e25db81..4828b784d93 100644 --- a/yarn-project/prover-node/src/metrics.ts +++ b/yarn-project/prover-node/src/metrics.ts @@ -1,5 +1,5 @@ import { type Timer } from '@aztec/foundation/timer'; -import { type Histogram, Metrics, type TelemetryClient, ValueType, millisecondBuckets } from '@aztec/telemetry-client'; +import { type Histogram, Metrics, type TelemetryClient, ValueType } from '@aztec/telemetry-client'; export class ProverNodeMetrics { provingJobDuration: Histogram; @@ -10,9 +10,6 @@ export class ProverNodeMetrics { description: 'Duration of proving job', unit: 'ms', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: millisecondBuckets(2), // 60 buckets spanning an interval of ~100ms to ~1hour - }, }); } diff --git a/yarn-project/sequencer-client/src/publisher/l1-publisher-metrics.ts b/yarn-project/sequencer-client/src/publisher/l1-publisher-metrics.ts index 29d8bb4b527..b33c857a529 100644 --- a/yarn-project/sequencer-client/src/publisher/l1-publisher-metrics.ts +++ b/yarn-project/sequencer-client/src/publisher/l1-publisher-metrics.ts @@ -38,9 +38,6 @@ export class L1PublisherMetrics { description: 'The duration of transaction processing', unit: 'ms', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: [10, 50, 100, 200, 500, 1000, 2000, 5000, 10000], - }, }); this.txGas = meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS, { @@ -51,11 +48,8 @@ export class L1PublisherMetrics { this.txCalldataSize = meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE, { description: 'The size of the calldata in transactions', - unit: 'bytes', + unit: 'By', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: [0, 100, 200, 500, 1000, 2000, 5000, 10000], - }, }); this.txCalldataGas = meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS, { diff --git a/yarn-project/sequencer-client/src/sequencer/metrics.ts b/yarn-project/sequencer-client/src/sequencer/metrics.ts index ea0d14bb6dd..55cd5b1b145 100644 --- a/yarn-project/sequencer-client/src/sequencer/metrics.ts +++ b/yarn-project/sequencer-client/src/sequencer/metrics.ts @@ -7,7 +7,6 @@ import { type Tracer, type UpDownCounter, ValueType, - millisecondBuckets, } from '@aztec/telemetry-client'; import { type SequencerState, type SequencerStateCallback, sequencerStateToNumber } from './utils.js'; @@ -32,18 +31,12 @@ export class SequencerMetrics { unit: 'ms', description: 'Duration to build a block', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: millisecondBuckets(2), - }, }); this.stateTransitionBufferDuration = meter.createHistogram(Metrics.SEQUENCER_STATE_TRANSITION_BUFFER_DURATION, { unit: 'ms', description: 'The time difference between when the sequencer needed to transition to a new state and when it actually did.', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: millisecondBuckets(2), - }, }); const currentState = meter.createObservableGauge(Metrics.SEQUENCER_CURRENT_STATE, { diff --git a/yarn-project/simulator/src/public/executor_metrics.ts b/yarn-project/simulator/src/public/executor_metrics.ts index 17267f58b90..621a3c09498 100644 --- a/yarn-project/simulator/src/public/executor_metrics.ts +++ b/yarn-project/simulator/src/public/executor_metrics.ts @@ -6,7 +6,6 @@ import { type Tracer, type UpDownCounter, ValueType, - linearBuckets, } from '@aztec/telemetry-client'; export class ExecutorMetrics { @@ -33,9 +32,6 @@ export class ExecutorMetrics { description: 'Mana used per second', unit: 'mana/s', valueType: ValueType.INT, - advice: { - explicitBucketBoundaries: linearBuckets(0, 10_000_000, 10), - }, }); } diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index eb817b121fc..0462bb66239 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -253,6 +253,13 @@ export class PublicProcessor { feePaymentPublicDataWrite, this.globalVariables, ); + + this.metrics.recordClassRegistration( + ...tx.contractClassLogs + .unrollLogs() + .filter(log => ContractClassRegisteredEvent.isContractClassRegisteredEvent(log.data)) + .map(log => ContractClassRegisteredEvent.fromLog(log.data)), + ); return [processedTx]; } diff --git a/yarn-project/telemetry-client/src/histogram_utils.test.ts b/yarn-project/telemetry-client/src/histogram_utils.test.ts index f23482f995b..6281420819d 100644 --- a/yarn-project/telemetry-client/src/histogram_utils.test.ts +++ b/yarn-project/telemetry-client/src/histogram_utils.test.ts @@ -1,4 +1,4 @@ -import { exponentialBuckets, linearBuckets, millisecondBuckets } from './histogram_utils.js'; +import { exponentialBuckets, linearBuckets } from './histogram_utils.js'; describe('linearBuckets', () => { it.each([[10, 1_000, 5, [10, 208, 406, 604, 802, 1000]]] as const)( @@ -17,31 +17,3 @@ describe('exponentialBuckets', () => { }, ); }); - -describe('millisecondBuckets', () => { - it('should throw an error if significantFractionalDigits is less than 1', () => { - expect(() => millisecondBuckets(0)).toThrow(); - }); - - it('should return the expected buckets for milliseconds', () => { - expect(millisecondBuckets(1, 16)).toEqual([ - 10, // 2^0 * 10 - 12, - 14, - 17, - 20, // 2^1 * 10 - 24, - 28, - 34, - 40, // 2^2 * 10 - 48, - 57, - 67, - 80, // 2^3 * 10 - 95, - 113, - 135, - 160, // 2^4 * 10 - ]); - }); -}); diff --git a/yarn-project/telemetry-client/src/histogram_utils.ts b/yarn-project/telemetry-client/src/histogram_utils.ts index 0296bac486a..35167b8c3af 100644 --- a/yarn-project/telemetry-client/src/histogram_utils.ts +++ b/yarn-project/telemetry-client/src/histogram_utils.ts @@ -6,10 +6,10 @@ * @returns - An array of bucket boundaries */ export function linearBuckets(start: number, end: number, count: number): number[] { - const buckets = []; + const buckets: number[] = []; const step = (end - start) / count; for (let i = 0; i <= count; i++) { - buckets.push(start + i * step); + buckets.push(Math.floor(start + i * step)); } return buckets; } @@ -48,19 +48,3 @@ export function exponentialBuckets(scale: number, count: number): number[] { } return buckets; } - -/** - * Creates an array of exponential buckets optimized for milliseconds - * @param significantFractionalDigits - The number of significant digits to round to - * @param count - The number of buckets. Defaults to 60 - * @returns - An array of bucket boundaries - */ -export function millisecondBuckets(significantFractionalDigits: number, count = 60): number[] { - if (significantFractionalDigits < 1) { - // if significant digits is 1 then we end up having duplicate buckets - throw new Error('significantFractionalDigits must be >= 1'); - } - - const scale = 10 ** significantFractionalDigits; - return exponentialBuckets(2, count).map(x => Math.round(x * scale)); -} diff --git a/yarn-project/telemetry-client/src/otel.ts b/yarn-project/telemetry-client/src/otel.ts index 5ba3f5bcec9..14d28f9fe6f 100644 --- a/yarn-project/telemetry-client/src/otel.ts +++ b/yarn-project/telemetry-client/src/otel.ts @@ -16,11 +16,18 @@ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; import { HostMetrics } from '@opentelemetry/host-metrics'; import { type IResource } from '@opentelemetry/resources'; import { type LoggerProvider } from '@opentelemetry/sdk-logs'; -import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics'; +import { + ExplicitBucketHistogramAggregation, + InstrumentType, + MeterProvider, + PeriodicExportingMetricReader, + View, +} from '@opentelemetry/sdk-metrics'; import { BatchSpanProcessor, NodeTracerProvider } from '@opentelemetry/sdk-trace-node'; import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions'; import { type TelemetryClientConfig } from './config.js'; +import { linearBuckets } from './histogram_utils.js'; import { registerOtelLoggerProvider } from './otel_logger_provider.js'; import { getOtelResource } from './otel_resource.js'; import { type Gauge, type TelemetryClient } from './telemetry.js'; @@ -140,6 +147,43 @@ export class OpenTelemetryClient implements TelemetryClient { exportTimeoutMillis: config.otelExportTimeoutMs, }), ], + views: [ + // Every histogram matching the selector (type + unit) gets these custom buckets assigned + new View({ + instrumentType: InstrumentType.HISTOGRAM, + instrumentUnit: 'ms', + aggregation: new ExplicitBucketHistogramAggregation( + // 181 buckets between 5ms and 1hr + [ + ...linearBuckets(5, 100, 20), // 20 buckets between 5 and 100ms + ...linearBuckets(100, 1_000, 20).slice(1), // another 20 buckets between 100ms and 1s. slice(1) to remove duplicate 100 + ...linearBuckets(1_000, 10_000, 20).slice(1), + ...linearBuckets(10_000, 60_000, 20).slice(1), + ...linearBuckets(60_000, 300_000, 20).slice(1), + ...linearBuckets(300_000, 600_000, 20).slice(1), + ...linearBuckets(600_000, 1_200_000, 20).slice(1), + ...linearBuckets(1_200_000, 1_800_000, 20).slice(1), + ...linearBuckets(1_800_000, 3_600_000, 20).slice(1), // 1hr + ], + true, + ), + }), + new View({ + instrumentType: InstrumentType.HISTOGRAM, + instrumentUnit: 'By', + aggregation: new ExplicitBucketHistogramAggregation( + // 143 buckets between 32 bytes and 2MB + [ + ...linearBuckets(2 ** 5, 2 ** 10, 31), // 32 bytes to 1KB at a resolution of 32 bytes + ...linearBuckets(2 ** 10, 2 ** 15, 31).slice(1), // 1KB to 32KB at a resolution of 1KB + ...linearBuckets(2 ** 15, 2 ** 18, 32).slice(1), // 32KB to 256KB at a resolution of 7KB + ...linearBuckets(2 ** 18, 2 ** 20, 32).slice(1), // 256KB to 1MB at a resolution of 24KB + ...linearBuckets(2 ** 20, 2 ** 21, 16).slice(1), // 1MB to 2MB at a resolution of 64KB + ], + true, + ), + }), + ], }); const loggerProvider = await registerOtelLoggerProvider(resource, config.logsCollectorUrl);