@aztec/telemetry-client 0.0.0-test.1 → 0.0.1-commit.b655e406

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dest/attributes.d.ts +21 -8
  2. package/dest/attributes.d.ts.map +1 -1
  3. package/dest/attributes.js +16 -8
  4. package/dest/bench.d.ts +3 -0
  5. package/dest/bench.d.ts.map +1 -1
  6. package/dest/bench.js +7 -0
  7. package/dest/config.d.ts +5 -1
  8. package/dest/config.d.ts.map +1 -1
  9. package/dest/config.js +23 -1
  10. package/dest/index.d.ts +1 -0
  11. package/dest/index.d.ts.map +1 -1
  12. package/dest/index.js +1 -0
  13. package/dest/l1_metrics.d.ts +17 -0
  14. package/dest/l1_metrics.d.ts.map +1 -0
  15. package/dest/l1_metrics.js +70 -0
  16. package/dest/lmdb_metrics.d.ts +4 -2
  17. package/dest/lmdb_metrics.d.ts.map +1 -1
  18. package/dest/lmdb_metrics.js +8 -0
  19. package/dest/metrics.d.ts +87 -12
  20. package/dest/metrics.d.ts.map +1 -1
  21. package/dest/metrics.js +88 -13
  22. package/dest/{event_loop_monitor.d.ts → nodejs_metrics_monitor.d.ts} +5 -2
  23. package/dest/nodejs_metrics_monitor.d.ts.map +1 -0
  24. package/dest/{event_loop_monitor.js → nodejs_metrics_monitor.js} +55 -12
  25. package/dest/noop.d.ts +3 -1
  26. package/dest/noop.d.ts.map +1 -1
  27. package/dest/noop.js +2 -0
  28. package/dest/otel.d.ts +8 -4
  29. package/dest/otel.d.ts.map +1 -1
  30. package/dest/otel.js +79 -19
  31. package/dest/otel_filter_metric_exporter.d.ts +11 -3
  32. package/dest/otel_filter_metric_exporter.d.ts.map +1 -1
  33. package/dest/otel_filter_metric_exporter.js +38 -4
  34. package/dest/otel_resource.d.ts.map +1 -1
  35. package/dest/otel_resource.js +31 -2
  36. package/dest/prom_otel_adapter.d.ts +57 -8
  37. package/dest/prom_otel_adapter.d.ts.map +1 -1
  38. package/dest/prom_otel_adapter.js +143 -43
  39. package/dest/start.js +4 -4
  40. package/dest/telemetry.d.ts +28 -11
  41. package/dest/telemetry.d.ts.map +1 -1
  42. package/dest/telemetry.js +1 -1
  43. package/dest/vendor/otel-pino-stream.d.ts +0 -1
  44. package/dest/vendor/otel-pino-stream.d.ts.map +1 -1
  45. package/dest/vendor/otel-pino-stream.js +2 -2
  46. package/dest/wrappers/fetch.d.ts +1 -1
  47. package/dest/wrappers/fetch.d.ts.map +1 -1
  48. package/dest/wrappers/fetch.js +7 -5
  49. package/dest/wrappers/json_rpc_server.d.ts +1 -1
  50. package/dest/wrappers/json_rpc_server.d.ts.map +1 -1
  51. package/dest/wrappers/l2_block_stream.d.ts +1 -1
  52. package/dest/wrappers/l2_block_stream.d.ts.map +1 -1
  53. package/package.json +16 -13
  54. package/src/attributes.ts +27 -11
  55. package/src/bench.ts +15 -5
  56. package/src/config.ts +41 -2
  57. package/src/index.ts +1 -0
  58. package/src/l1_metrics.ts +80 -0
  59. package/src/lmdb_metrics.ts +24 -3
  60. package/src/metrics.ts +106 -12
  61. package/src/{event_loop_monitor.ts → nodejs_metrics_monitor.ts} +59 -10
  62. package/src/noop.ts +4 -1
  63. package/src/otel.ts +66 -21
  64. package/src/otel_filter_metric_exporter.ts +47 -5
  65. package/src/otel_resource.ts +40 -2
  66. package/src/prom_otel_adapter.ts +191 -59
  67. package/src/start.ts +4 -4
  68. package/src/telemetry.ts +50 -12
  69. package/src/vendor/otel-pino-stream.ts +1 -4
  70. package/src/wrappers/fetch.ts +24 -31
  71. package/src/wrappers/json_rpc_server.ts +1 -1
  72. package/src/wrappers/l2_block_stream.ts +1 -1
  73. package/dest/event_loop_monitor.d.ts.map +0 -1
@@ -10,21 +10,23 @@ import { ATTR_JSONRPC_METHOD, ATTR_JSONRPC_REQUEST_ID } from '../vendor/attribut
10
10
  * @param log - Optional logger for logging attempts.
11
11
  * @returns A fetch function.
12
12
  */ export function makeTracedFetch(retries, defaultNoRetry, fetch = defaultFetch, log) {
13
- return (host, rpcMethod, body, useApiEndpoints, extraHeaders = {}, noRetry)=>{
13
+ return (host, body, extraHeaders = {}, noRetry)=>{
14
14
  const telemetry = getTelemetryClient();
15
- return telemetry.getTracer('fetch').startActiveSpan(`JsonRpcClient.${rpcMethod}`, {
15
+ return telemetry.getTracer('fetch').startActiveSpan(`JsonRpcClient`, {
16
16
  kind: SpanKind.CLIENT
17
17
  }, async (span)=>{
18
18
  try {
19
- if (body && typeof body.id === 'number') {
19
+ if (body && typeof body === 'object' && 'id' in body && typeof body.id === 'number') {
20
20
  span.setAttribute(ATTR_JSONRPC_REQUEST_ID, body.id);
21
21
  }
22
- span.setAttribute(ATTR_JSONRPC_METHOD, rpcMethod);
22
+ if (body && typeof body === 'object' && 'method' in body && typeof body.method === 'string') {
23
+ span.setAttribute(ATTR_JSONRPC_METHOD, body.method);
24
+ }
23
25
  const headers = {
24
26
  ...extraHeaders
25
27
  };
26
28
  propagation.inject(context.active(), headers);
27
- return await retry(()=>fetch(host, rpcMethod, body, useApiEndpoints, headers, noRetry ?? defaultNoRetry), `JsonRpcClient request ${rpcMethod} to ${host}`, makeBackoff(retries), log, false);
29
+ return await retry(()=>fetch(host, body, headers, noRetry ?? defaultNoRetry), `JsonRpcClient request to ${host}`, makeBackoff(retries), log, false);
28
30
  } catch (err) {
29
31
  span.setStatus({
30
32
  code: SpanStatusCode.ERROR,
@@ -1,4 +1,4 @@
1
1
  import { type SafeJsonRpcServerOptions } from '@aztec/foundation/json-rpc/server';
2
2
  import type { ApiSchemaFor } from '@aztec/stdlib/schemas';
3
- export declare function createTracedJsonRpcServer<T extends object = any>(handler: T, schema: ApiSchemaFor<T>, options?: Partial<SafeJsonRpcServerOptions>): import("@aztec/foundation/json-rpc/server").SafeJsonRpcServer;
3
+ export declare function createTracedJsonRpcServer<T extends object = any>(handler: T, schema: ApiSchemaFor<T>, options?: SafeJsonRpcServerOptions): import("@aztec/foundation/json-rpc/server").SafeJsonRpcServer;
4
4
  //# sourceMappingURL=json_rpc_server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"json_rpc_server.d.ts","sourceRoot":"","sources":["../../src/wrappers/json_rpc_server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,wBAAwB,EAA2B,MAAM,mCAAmC,CAAC;AAC3G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAI1D,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,MAAM,GAAG,GAAG,EAC9D,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EACvB,OAAO,GAAE,OAAO,CAAC,wBAAwB,CAAM,iEAMhD"}
1
+ {"version":3,"file":"json_rpc_server.d.ts","sourceRoot":"","sources":["../../src/wrappers/json_rpc_server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,wBAAwB,EAA2B,MAAM,mCAAmC,CAAC;AAC3G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAI1D,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,MAAM,GAAG,GAAG,EAC9D,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EACvB,OAAO,GAAE,wBAA6B,iEAMvC"}
@@ -4,7 +4,7 @@ import { type Traceable, type Tracer } from '@aztec/telemetry-client';
4
4
  export declare class TraceableL2BlockStream extends L2BlockStream implements Traceable {
5
5
  readonly tracer: Tracer;
6
6
  private readonly name;
7
- constructor(l2BlockSource: Pick<L2BlockSource, 'getBlocks' | 'getBlockHeader' | 'getL2Tips'>, localData: L2BlockStreamLocalDataProvider, handler: L2BlockStreamEventHandler, tracer: Tracer, name?: string, log?: import("@aztec/foundation/log").Logger, opts?: {
7
+ constructor(l2BlockSource: Pick<L2BlockSource, 'getPublishedBlocks' | 'getBlockHeader' | 'getL2Tips'>, localData: L2BlockStreamLocalDataProvider, handler: L2BlockStreamEventHandler, tracer: Tracer, name?: string, log?: import("@aztec/foundation/log").Logger, opts?: {
8
8
  proven?: boolean;
9
9
  pollIntervalMS?: number;
10
10
  batchSize?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"l2_block_stream.d.ts","sourceRoot":"","sources":["../../src/wrappers/l2_block_stream.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,aAAa,EACb,KAAK,yBAAyB,EAC9B,KAAK,8BAA8B,EACpC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,MAAM,EAAa,MAAM,yBAAyB,CAAC;AAEjF,kFAAkF;AAClF,qBAAa,sBAAuB,SAAQ,aAAc,YAAW,SAAS;aAK1D,MAAM,EAAE,MAAM;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAJrB,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,WAAW,GAAG,gBAAgB,GAAG,WAAW,CAAC,EAChF,SAAS,EAAE,8BAA8B,EACzC,OAAO,EAAE,yBAAyB,EAClB,MAAM,EAAE,MAAM,EACb,IAAI,GAAE,MAAwB,EAC/C,GAAG,yCAAqC,EACxC,IAAI,GAAE;QACJ,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;KACnB;IAUC,IAAI;CAGd"}
1
+ {"version":3,"file":"l2_block_stream.d.ts","sourceRoot":"","sources":["../../src/wrappers/l2_block_stream.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAClB,aAAa,EACb,KAAK,yBAAyB,EAC9B,KAAK,8BAA8B,EACpC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,MAAM,EAAa,MAAM,yBAAyB,CAAC;AAEjF,kFAAkF;AAClF,qBAAa,sBAAuB,SAAQ,aAAc,YAAW,SAAS;aAK1D,MAAM,EAAE,MAAM;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAJrB,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,oBAAoB,GAAG,gBAAgB,GAAG,WAAW,CAAC,EACzF,SAAS,EAAE,8BAA8B,EACzC,OAAO,EAAE,yBAAyB,EAClB,MAAM,EAAE,MAAM,EACb,IAAI,GAAE,MAAwB,EAC/C,GAAG,yCAAqC,EACxC,IAAI,GAAE;QACJ,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,aAAa,CAAC,EAAE,MAAM,CAAC;KACnB;IAUC,IAAI;CAGd"}
package/package.json CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/telemetry-client",
3
+ "version": "0.0.1-commit.b655e406",
3
4
  "inherits": [
4
5
  "../package.common.json"
5
6
  ],
@@ -13,12 +14,10 @@
13
14
  "build": "yarn clean && tsc -b",
14
15
  "build:dev": "tsc -b --watch",
15
16
  "clean": "rm -rf ./dest .tsbuildinfo",
16
- "formatting": "run -T prettier --check ./src && run -T eslint ./src",
17
- "formatting:fix": "run -T eslint --fix ./src && run -T prettier -w ./src",
18
17
  "test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests --maxWorkers=${JEST_MAX_WORKERS:-8}"
19
18
  },
20
19
  "engines": {
21
- "node": ">=18"
20
+ "node": ">=20.10"
22
21
  },
23
22
  "files": [
24
23
  "dest",
@@ -26,15 +25,15 @@
26
25
  "!*.test.*"
27
26
  ],
28
27
  "dependencies": {
29
- "@aztec/foundation": "0.0.0-test.1",
30
- "@aztec/stdlib": "0.0.0-test.1",
28
+ "@aztec/foundation": "0.0.1-commit.b655e406",
29
+ "@aztec/stdlib": "0.0.1-commit.b655e406",
31
30
  "@opentelemetry/api": "^1.9.0",
32
31
  "@opentelemetry/api-logs": "^0.55.0",
33
32
  "@opentelemetry/core": "^1.28.0",
34
33
  "@opentelemetry/exporter-logs-otlp-http": "^0.55.0",
35
34
  "@opentelemetry/exporter-metrics-otlp-http": "^0.55.0",
36
35
  "@opentelemetry/exporter-trace-otlp-http": "^0.55.0",
37
- "@opentelemetry/host-metrics": "^0.35.4",
36
+ "@opentelemetry/host-metrics": "^0.36.2",
38
37
  "@opentelemetry/otlp-exporter-base": "^0.55.0",
39
38
  "@opentelemetry/resource-detector-gcp": "^0.32.0",
40
39
  "@opentelemetry/resources": "^1.28.0",
@@ -42,15 +41,16 @@
42
41
  "@opentelemetry/sdk-metrics": "^1.28.0",
43
42
  "@opentelemetry/sdk-trace-node": "^1.28.0",
44
43
  "@opentelemetry/semantic-conventions": "^1.28.0",
45
- "prom-client": "^15.1.3"
44
+ "prom-client": "^15.1.3",
45
+ "viem": "npm:@spalladino/viem@2.38.2-eip7594.0"
46
46
  },
47
47
  "devDependencies": {
48
- "@jest/globals": "^29.5.0",
49
- "@types/jest": "^29.5.0",
48
+ "@jest/globals": "^30.0.0",
49
+ "@types/jest": "^30.0.0",
50
50
  "@types/koa": "^2.15.0",
51
- "jest": "^29.5.0",
51
+ "jest": "^30.0.0",
52
52
  "ts-node": "^10.9.1",
53
- "typescript": "^5.0.4"
53
+ "typescript": "^5.3.3"
54
54
  },
55
55
  "jest": {
56
56
  "extensionsToTreatAsEsm": [
@@ -83,7 +83,10 @@
83
83
  "testTimeout": 120000,
84
84
  "setupFiles": [
85
85
  "../../foundation/src/jest/setup.mjs"
86
+ ],
87
+ "testEnvironment": "../../foundation/src/jest/env.mjs",
88
+ "setupFilesAfterEnv": [
89
+ "../../foundation/src/jest/setupAfterEnv.mjs"
86
90
  ]
87
- },
88
- "version": "0.0.0-test.1"
91
+ }
89
92
  }
package/src/attributes.ts CHANGED
@@ -14,34 +14,35 @@
14
14
  * @see {@link https://opentelemetry.io/docs/specs/semconv/general/attribute-naming/}
15
15
  */
16
16
 
17
+ /** The host of an HTTP request */
18
+ export const HTTP_REQUEST_HOST = 'http.header.request.host';
19
+ export const HTTP_RESPONSE_STATUS_CODE = 'http.response.status_code';
20
+
17
21
  /** The Aztec network identifier */
18
22
  export const NETWORK_NAME = 'aztec.network_name';
19
23
 
24
+ export const AZTEC_NODE_ROLE = 'aztec.node_role';
25
+ export const AZTEC_ROLLUP_VERSION = 'aztec.rollup_version';
26
+ export const AZTEC_ROLLUP_ADDRESS = 'aztec.rollup_address';
27
+ export const AZTEC_REGISTRY_ADDRESS = 'aztec.registry_address';
28
+
20
29
  /**
21
30
  * The name of the protocol circuit being run (e.g. public-kernel-setup or base-rollup)
22
31
  * @see {@link @aztec/stdlib/stats:CircuitName}
23
32
  */
24
33
  export const PROTOCOL_CIRCUIT_NAME = 'aztec.circuit.protocol_circuit_name';
25
34
 
26
- /**
27
- * The type of protocol circuit being run: server or client
28
- */
29
- export const PROTOCOL_CIRCUIT_TYPE = 'aztec.circuit.protocol_circuit_type';
30
-
31
35
  /**
32
36
  * For an app circuit, the contract:function being run (e.g. Token:transfer)
33
37
  */
34
38
  export const APP_CIRCUIT_NAME = 'aztec.circuit.app_circuit_name';
35
39
 
36
- /**
37
- * The type of app circuit being run: server or client
38
- */
39
- export const APP_CIRCUIT_TYPE = 'aztec.circuit.app_circuit_type';
40
-
41
40
  /** The block archive */
42
41
  export const BLOCK_ARCHIVE = 'aztec.block.archive';
43
42
  /** The block number */
44
43
  export const BLOCK_NUMBER = 'aztec.block.number';
44
+ /** The L2 block hash */
45
+ export const BLOCK_HASH = 'aztec.block.hash';
45
46
  /** The slot number */
46
47
  export const SLOT_NUMBER = 'aztec.slot.number';
47
48
  /** The parent's block number */
@@ -70,6 +71,8 @@ export const ERROR_TYPE = 'aztec.error_type';
70
71
  export const L1_TX_TYPE = 'aztec.l1.tx_type';
71
72
  /** The L1 address of the entity that sent a transaction to L1 */
72
73
  export const L1_SENDER = 'aztec.l1.sender';
74
+ /** The L1 address receiving rewards */
75
+ export const COINBASE = 'aztec.coinbase';
73
76
  /** The phase of the transaction */
74
77
  export const TX_PHASE_NAME = 'aztec.tx.phase_name';
75
78
  /** The reason for disconnecting a peer */
@@ -78,12 +81,14 @@ export const P2P_GOODBYE_REASON = 'aztec.p2p.goodbye.reason';
78
81
  export const PROVING_JOB_TYPE = 'aztec.proving.job_type';
79
82
  /** The proving job id */
80
83
  export const PROVING_JOB_ID = 'aztec.proving.job_id';
81
-
84
+ /** Merkle tree name */
82
85
  export const MERKLE_TREE_NAME = 'aztec.merkle_tree.name';
83
86
  /** The prover-id in a root rollup proof. */
84
87
  export const ROLLUP_PROVER_ID = 'aztec.rollup.prover_id';
85
88
  /** Whether the proof submission was timed out (delayed more than 20 min) */
86
89
  export const PROOF_TIMED_OUT = 'aztec.proof.timed_out';
90
+ /** Status of the validator (eg proposer, in-committee, none) */
91
+ export const VALIDATOR_STATUS = 'aztec.validator_status';
87
92
 
88
93
  export const P2P_ID = 'aztec.p2p.id';
89
94
  export const P2P_REQ_RESP_PROTOCOL = 'aztec.p2p.req_resp.protocol';
@@ -96,6 +101,7 @@ export const SIMULATOR_PHASE = 'aztec.simulator.phase';
96
101
  export const TARGET_ADDRESS = 'aztec.address.target';
97
102
  export const SENDER_ADDRESS = 'aztec.address.sender';
98
103
  export const MANA_USED = 'aztec.mana.used';
104
+ export const TOTAL_INSTRUCTIONS = 'aztec.total_instructions';
99
105
 
100
106
  /** Whether a sync process is the initial run, which is usually slower than iterative ones. */
101
107
  export const INITIAL_SYNC = 'aztec.initial_sync';
@@ -113,3 +119,13 @@ export const GAS_DIMENSION = 'aztec.gas_dimension';
113
119
  export const WORLD_STATE_REQUEST_TYPE = 'aztec.world_state_request';
114
120
 
115
121
  export const NODEJS_EVENT_LOOP_STATE = 'nodejs.eventloop.state';
122
+
123
+ export const TOPIC_NAME = 'aztec.gossip.topic_name';
124
+
125
+ export const TX_COLLECTION_METHOD = 'aztec.tx_collection.method';
126
+
127
+ /** Scope of L1 transaction (sequencer, prover, or other) */
128
+ export const L1_TX_SCOPE = 'aztec.l1_tx.scope';
129
+
130
+ /** Generic error type attribute */
131
+ export const IS_COMMITTEE_MEMBER = 'aztec.is_committee_member';
package/src/bench.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { createLogger } from '@aztec/foundation/log';
2
+
1
3
  import type { BatchObservableCallback, Context, MetricOptions, Observable, ValueType } from '@opentelemetry/api';
2
4
 
3
5
  import { NoopTracer } from './noop.js';
@@ -29,6 +31,14 @@ export type BenchmarkMetricsType = {
29
31
  export class BenchmarkTelemetryClient implements TelemetryClient {
30
32
  private meters: InMemoryPlainMeter[] = [];
31
33
 
34
+ constructor() {
35
+ const log = createLogger('telemetry:client');
36
+ log.info(`Using benchmark telemetry client`);
37
+ }
38
+
39
+ setExportedPublicTelemetry(_prefixes: string[]): void {}
40
+ setPublicTelemetryCollectFrom(_roles: string[]): void {}
41
+
32
42
  getMeter(name: string): Meter {
33
43
  const meter = new InMemoryPlainMeter(name);
34
44
  this.meters.push(meter);
@@ -69,23 +79,23 @@ class InMemoryPlainMeter implements Meter {
69
79
  this.metrics.forEach(metric => metric.clear());
70
80
  }
71
81
 
72
- createGauge(name: MetricsType, options?: MetricOptions | undefined): Gauge {
82
+ createGauge(name: MetricsType, options?: MetricOptions): Gauge {
73
83
  return this.createMetric('gauge', name, options);
74
84
  }
75
85
 
76
- createObservableGauge(name: MetricsType, options?: MetricOptions | undefined): ObservableGauge {
86
+ createObservableGauge(name: MetricsType, options?: MetricOptions): ObservableGauge {
77
87
  return this.createMetric('gauge', name, options);
78
88
  }
79
89
 
80
- createHistogram(name: MetricsType, options?: MetricOptions | undefined): Histogram {
90
+ createHistogram(name: MetricsType, options?: MetricOptions): Histogram {
81
91
  return this.createMetric('histogram', name, options);
82
92
  }
83
93
 
84
- createUpDownCounter(name: MetricsType, options?: MetricOptions | undefined): UpDownCounter {
94
+ createUpDownCounter(name: MetricsType, options?: MetricOptions): UpDownCounter {
85
95
  return this.createMetric('counter', name, options);
86
96
  }
87
97
 
88
- createObservableUpDownCounter(name: MetricsType, options?: MetricOptions | undefined): ObservableUpDownCounter {
98
+ createObservableUpDownCounter(name: MetricsType, options?: MetricOptions): ObservableUpDownCounter {
89
99
  return this.createMetric('counter', name, options);
90
100
  }
91
101
 
package/src/config.ts CHANGED
@@ -1,12 +1,16 @@
1
- import { type ConfigMappingsType, getConfigFromMappings } from '@aztec/foundation/config';
1
+ import { type ConfigMappingsType, booleanConfigHelper, getConfigFromMappings } from '@aztec/foundation/config';
2
2
 
3
3
  export interface TelemetryClientConfig {
4
4
  metricsCollectorUrl?: URL;
5
+ publicMetricsCollectorUrl?: URL;
6
+ publicIncludeMetrics: string[];
7
+ publicMetricsOptOut: boolean;
8
+ publicMetricsCollectFrom: string[];
5
9
  tracesCollectorUrl?: URL;
6
10
  logsCollectorUrl?: URL;
7
11
  otelCollectIntervalMs: number;
8
12
  otelExportTimeoutMs: number;
9
- otelExcludeMetrics?: string[];
13
+ otelExcludeMetrics: string[];
10
14
  }
11
15
 
12
16
  export const telemetryClientConfigMappings: ConfigMappingsType<TelemetryClientConfig> = {
@@ -49,6 +53,41 @@ export const telemetryClientConfigMappings: ConfigMappingsType<TelemetryClientCo
49
53
  : [],
50
54
  defaultValue: [],
51
55
  },
56
+
57
+ publicMetricsCollectorUrl: {
58
+ env: 'PUBLIC_OTEL_EXPORTER_OTLP_METRICS_ENDPOINT',
59
+ description: 'A URL to publish a subset of metrics for public consumption',
60
+ parseEnv: (val: string) => val && new URL(val),
61
+ },
62
+ publicMetricsCollectFrom: {
63
+ env: 'PUBLIC_OTEL_COLLECT_FROM',
64
+ description: 'The role types to collect metrics from',
65
+ parseEnv: (val: string) =>
66
+ val
67
+ ? val
68
+ .split(',')
69
+ .map(s => s.trim())
70
+ .filter(s => s.length > 0)
71
+ : [],
72
+ defaultValue: [],
73
+ },
74
+ publicIncludeMetrics: {
75
+ env: 'PUBLIC_OTEL_INCLUDE_METRICS',
76
+ description: 'A list of metric prefixes to publicly export',
77
+ parseEnv: (val: string) =>
78
+ val
79
+ ? val
80
+ .split(',')
81
+ .map(s => s.trim())
82
+ .filter(s => s.length > 0)
83
+ : [],
84
+ defaultValue: [],
85
+ },
86
+ publicMetricsOptOut: {
87
+ env: 'PUBLIC_OTEL_OPT_OUT',
88
+ description: 'Whether to opt out of sharing optional telemetry',
89
+ ...booleanConfigHelper(false),
90
+ },
52
91
  };
53
92
 
54
93
  export function getConfigEnvVars(): TelemetryClientConfig {
package/src/index.ts CHANGED
@@ -4,6 +4,7 @@ export * as Attributes from './attributes.js';
4
4
  export * from './with_tracer.js';
5
5
  export * from './prom_otel_adapter.js';
6
6
  export * from './lmdb_metrics.js';
7
+ export * from './l1_metrics.js';
7
8
  export * from './wrappers/index.js';
8
9
  export * from './start.js';
9
10
  export * from './otel_propagation.js';
@@ -0,0 +1,80 @@
1
+ import type { EthAddress } from '@aztec/foundation/eth-address';
2
+
3
+ import { type Chain, type FallbackTransport, type Hex, type HttpTransport, type PublicClient, formatEther } from 'viem';
4
+
5
+ import { L1_SENDER } from './attributes.js';
6
+ import { L1_BALANCE_ETH, L1_BLOB_BASE_FEE_WEI, L1_BLOCK_HEIGHT, L1_GAS_PRICE_WEI } from './metrics.js';
7
+ import { type BatchObservableResult, type Meter, type ObservableGauge, ValueType } from './telemetry.js';
8
+
9
+ export class L1Metrics {
10
+ private l1BlockHeight: ObservableGauge;
11
+ private l1BalanceEth: ObservableGauge;
12
+ private gasPriceWei: ObservableGauge;
13
+ private blobBaseFeeWei: ObservableGauge;
14
+ private addresses: Hex[];
15
+
16
+ constructor(
17
+ private meter: Meter,
18
+ private client: PublicClient<FallbackTransport<HttpTransport[]>, Chain>,
19
+ addresses: EthAddress[],
20
+ ) {
21
+ this.l1BlockHeight = meter.createObservableGauge(L1_BLOCK_HEIGHT, {
22
+ description: 'The latest L1 block seen',
23
+ valueType: ValueType.INT,
24
+ });
25
+ this.l1BalanceEth = meter.createObservableGauge(L1_BALANCE_ETH, {
26
+ description: 'Eth balance of an address',
27
+ unit: 'eth',
28
+ valueType: ValueType.DOUBLE,
29
+ });
30
+ this.gasPriceWei = meter.createObservableGauge(L1_GAS_PRICE_WEI, {
31
+ description: 'L1 gas price',
32
+ unit: 'wei',
33
+ valueType: ValueType.DOUBLE,
34
+ });
35
+ this.blobBaseFeeWei = meter.createObservableGauge(L1_BLOB_BASE_FEE_WEI, {
36
+ description: 'L1 blob fee',
37
+ unit: 'wei',
38
+ valueType: ValueType.DOUBLE,
39
+ });
40
+
41
+ this.addresses = addresses.map(addr => addr.toString());
42
+ }
43
+
44
+ start() {
45
+ this.meter.addBatchObservableCallback(this.observe, [this.l1BalanceEth, this.l1BlockHeight]);
46
+ }
47
+
48
+ stop() {
49
+ this.meter.removeBatchObservableCallback(this.observe, [this.l1BalanceEth, this.l1BlockHeight]);
50
+ }
51
+
52
+ private observe = async (observer: BatchObservableResult) => {
53
+ const blockNumber = await this.client.getBlockNumber();
54
+ const ethBalances = await Promise.all(
55
+ this.addresses.map(address =>
56
+ this.client.getBalance({
57
+ address,
58
+ blockNumber,
59
+ }),
60
+ ),
61
+ );
62
+
63
+ const gasPrice = await this.client.getGasPrice();
64
+ const blobFee = await this.client.getBlobBaseFee();
65
+
66
+ observer.observe(this.l1BlockHeight, Number(blockNumber));
67
+ observer.observe(this.gasPriceWei, Number(gasPrice));
68
+ observer.observe(this.blobBaseFeeWei, Number(blobFee));
69
+
70
+ for (let i = 0; i < ethBalances.length; i++) {
71
+ const wei = ethBalances[i];
72
+ const address = this.addresses[i];
73
+ const eth = parseFloat(formatEther(wei, 'wei'));
74
+
75
+ observer.observe(this.l1BalanceEth, eth, {
76
+ [L1_SENDER]: address,
77
+ });
78
+ }
79
+ };
80
+ }
@@ -7,19 +7,34 @@ import {
7
7
  ValueType,
8
8
  } from './telemetry.js';
9
9
 
10
- export type LmdbStatsCallback = () => Promise<{ mappingSize: number; numItems: number; actualSize: number }>;
10
+ export type LmdbStatsCallback = () => Promise<{
11
+ mappingSize: number;
12
+ physicalFileSize: number;
13
+ numItems: number;
14
+ actualSize: number;
15
+ }>;
11
16
 
12
17
  export class LmdbMetrics {
13
18
  private dbMapSize: ObservableGauge;
19
+ private dbPhysicalFileSize: ObservableGauge;
14
20
  private dbUsedSize: ObservableGauge;
15
21
  private dbNumItems: ObservableGauge;
16
22
 
17
- constructor(meter: Meter, private attributes?: AttributesType, private getStats?: LmdbStatsCallback) {
23
+ constructor(
24
+ meter: Meter,
25
+ private attributes?: AttributesType,
26
+ private getStats?: LmdbStatsCallback,
27
+ ) {
18
28
  this.dbMapSize = meter.createObservableGauge(Metrics.DB_MAP_SIZE, {
19
29
  description: 'LMDB Map Size',
20
30
  valueType: ValueType.INT,
21
31
  unit: 'By',
22
32
  });
33
+ this.dbPhysicalFileSize = meter.createObservableGauge(Metrics.DB_PHYSICAL_FILE_SIZE, {
34
+ description: 'LMDB Physical File Size',
35
+ valueType: ValueType.INT,
36
+ unit: 'By',
37
+ });
23
38
  this.dbUsedSize = meter.createObservableGauge(Metrics.DB_USED_SIZE, {
24
39
  description: 'LMDB Used Size',
25
40
  valueType: ValueType.INT,
@@ -30,7 +45,12 @@ export class LmdbMetrics {
30
45
  valueType: ValueType.INT,
31
46
  });
32
47
 
33
- meter.addBatchObservableCallback(this.recordDBMetrics, [this.dbMapSize, this.dbUsedSize, this.dbNumItems]);
48
+ meter.addBatchObservableCallback(this.recordDBMetrics, [
49
+ this.dbMapSize,
50
+ this.dbPhysicalFileSize,
51
+ this.dbUsedSize,
52
+ this.dbNumItems,
53
+ ]);
34
54
  }
35
55
 
36
56
  private recordDBMetrics = async (observable: BatchObservableResult) => {
@@ -39,6 +59,7 @@ export class LmdbMetrics {
39
59
  }
40
60
  const metrics = await this.getStats();
41
61
  observable.observe(this.dbMapSize, metrics.mappingSize, this.attributes);
62
+ observable.observe(this.dbPhysicalFileSize, metrics.physicalFileSize, this.attributes);
42
63
  observable.observe(this.dbNumItems, metrics.numItems, this.attributes);
43
64
  observable.observe(this.dbUsedSize, metrics.actualSize, this.attributes);
44
65
  };