Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions yarn-project/p2p/src/client/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ export async function createP2PClient<T extends P2PClientType>(
config.txCollectionFileStoreUrls,
txFileStoreBasePath,
logger.createChild('file-store-tx-source'),
telemetry,
);
if (fileStoreSources.length > 0) {
logger.info(`Using ${fileStoreSources.length} file store sources for tx collection.`, {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,59 @@
import { type Logger, createLogger } from '@aztec/foundation/log';
import { Timer } from '@aztec/foundation/timer';
import { type ReadOnlyFileStore, createReadOnlyFileStore } from '@aztec/stdlib/file-store';
import { Tx, type TxHash } from '@aztec/stdlib/tx';
import {
type Histogram,
Metrics,
type TelemetryClient,
type UpDownCounter,
getTelemetryClient,
} from '@aztec/telemetry-client';

import type { TxSource } from './tx_source.js';

/** TxSource implementation that downloads txs from a file store. */
export class FileStoreTxSource implements TxSource {
private downloadsSuccess: UpDownCounter;
private downloadsFailed: UpDownCounter;
private downloadDuration: Histogram;
private downloadSize: Histogram;

private constructor(
private readonly fileStore: ReadOnlyFileStore,
private readonly baseUrl: string,
private readonly basePath: string,
private readonly log: Logger,
) {}
telemetry: TelemetryClient,
) {
const meter = telemetry.getMeter('file-store-tx-source');
this.downloadsSuccess = meter.createUpDownCounter(Metrics.TX_FILE_STORE_DOWNLOADS_SUCCESS);
this.downloadsFailed = meter.createUpDownCounter(Metrics.TX_FILE_STORE_DOWNLOADS_FAILED);
this.downloadDuration = meter.createHistogram(Metrics.TX_FILE_STORE_DOWNLOAD_DURATION);
this.downloadSize = meter.createHistogram(Metrics.TX_FILE_STORE_DOWNLOAD_SIZE);
}

/**
* Creates a FileStoreTxSource from a URL.
* @param url - The file store URL (s3://, gs://, file://, http://, https://).
* @param basePath - Base path for tx files within the store.
* @param log - Optional logger.
* @param telemetry - Optional telemetry client.
* @returns The FileStoreTxSource instance, or undefined if creation fails.
*/
public static async create(
url: string,
basePath: string,
log: Logger = createLogger('p2p:file_store_tx_source'),
telemetry: TelemetryClient = getTelemetryClient(),
): Promise<FileStoreTxSource | undefined> {
try {
const fileStore = await createReadOnlyFileStore(url, log);
if (!fileStore) {
log.warn(`Failed to create file store for URL: ${url}`);
return undefined;
}
return new FileStoreTxSource(fileStore, url, basePath, log);
return new FileStoreTxSource(fileStore, url, basePath, log, telemetry);
} catch (err) {
log.warn(`Error creating file store for URL: ${url}`, { error: err });
return undefined;
Expand All @@ -45,10 +68,15 @@ export class FileStoreTxSource implements TxSource {
return Promise.all(
txHashes.map(async txHash => {
const path = `${this.basePath}/txs/${txHash.toString()}.bin`;
const timer = new Timer();
try {
const buffer = await this.fileStore.read(path);
this.downloadsSuccess.add(1);
this.downloadDuration.record(Math.ceil(timer.ms()));
this.downloadSize.record(buffer.length);
return Tx.fromBuffer(buffer);
} catch {
this.downloadsFailed.add(1);
// Tx not found or error reading - return undefined
return undefined;
}
Expand All @@ -60,14 +88,17 @@ export class FileStoreTxSource implements TxSource {
/**
* Creates FileStoreTxSource instances from URLs.
* @param urls - Array of file store URLs.
* @param basePath - Base path for tx files within each store.
* @param log - Optional logger.
* @param telemetry - Optional telemetry client.
* @returns Array of successfully created FileStoreTxSource instances.
*/
export async function createFileStoreTxSources(
urls: string[],
basePath: string,
log: Logger = createLogger('p2p:file_store_tx_source'),
telemetry: TelemetryClient = getTelemetryClient(),
): Promise<FileStoreTxSource[]> {
const sources = await Promise.all(urls.map(url => FileStoreTxSource.create(url, basePath, log)));
const sources = await Promise.all(urls.map(url => FileStoreTxSource.create(url, basePath, log, telemetry)));
return sources.filter((s): s is FileStoreTxSource => s !== undefined);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ export class TxCollectionInstrumentation {
const meter = client.getMeter(name);

this.txsCollected = createUpDownCounterWithDefault(meter, Metrics.TX_COLLECTOR_COUNT, {
[Attributes.TX_COLLECTION_METHOD]: ['fast-req-resp', 'fast-node-rpc', 'slow-req-resp', 'slow-node-rpc'],
[Attributes.TX_COLLECTION_METHOD]: [
'fast-req-resp',
'fast-node-rpc',
'slow-req-resp',
'slow-node-rpc',
'file-store',
],
});

this.collectionDurationPerTx = meter.createHistogram(Metrics.TX_COLLECTOR_DURATION_PER_TX);
Expand Down
22 changes: 22 additions & 0 deletions yarn-project/telemetry-client/src/metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1402,6 +1402,28 @@ export const TX_FILE_STORE_QUEUE_SIZE: MetricDefinition = {
description: 'Number of txs pending upload',
valueType: ValueType.INT,
};
export const TX_FILE_STORE_DOWNLOADS_SUCCESS: MetricDefinition = {
name: 'aztec.p2p.tx_file_store.downloads_success',
description: 'Number of successful tx downloads from file storage',
valueType: ValueType.INT,
};
export const TX_FILE_STORE_DOWNLOADS_FAILED: MetricDefinition = {
name: 'aztec.p2p.tx_file_store.downloads_failed',
description: 'Number of failed tx downloads from file storage',
valueType: ValueType.INT,
};
export const TX_FILE_STORE_DOWNLOAD_DURATION: MetricDefinition = {
name: 'aztec.p2p.tx_file_store.download_duration',
description: 'Duration to download a tx from file storage',
unit: 'ms',
valueType: ValueType.INT,
};
export const TX_FILE_STORE_DOWNLOAD_SIZE: MetricDefinition = {
name: 'aztec.p2p.tx_file_store.download_size',
description: 'Size of a downloaded tx from file storage',
unit: 'By',
valueType: ValueType.INT,
};

export const IVC_VERIFIER_TIME: MetricDefinition = {
name: 'aztec.ivc_verifier.time',
Expand Down
Loading