-
-
Notifications
You must be signed in to change notification settings - Fork 317
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* wip * WIP * Add nodejs metrics to discv5 worker * Fix build error * Add optional prefix to gc metrics * Add to discv5 dashboard * Add discv5 worker comments * Patch some tests * Update discv5 to 2.0.0 * Fix e2e test * Bump timeouts * fix typo
- Loading branch information
1 parent
460ba59
commit c49ee3c
Showing
23 changed files
with
1,066 additions
and
221 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
export * from "./metrics.js"; | ||
export * from "./server/index.js"; | ||
export * from "./interface.js"; | ||
export * from "./nodeJsMetrics.js"; | ||
export {RegistryMetricCreator} from "./utils/registryMetricCreator.js"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import {collectDefaultMetrics, Registry} from "prom-client"; | ||
import gcStats from "prometheus-gc-stats"; | ||
|
||
export function collectNodeJSMetrics(register: Registry, prefix?: string): void { | ||
collectDefaultMetrics({ | ||
register, | ||
prefix, | ||
// eventLoopMonitoringPrecision with sampling rate in milliseconds | ||
eventLoopMonitoringPrecision: 10, | ||
}); | ||
|
||
// Collects GC metrics using a native binding module | ||
// - nodejs_gc_runs_total: Counts the number of time GC is invoked | ||
// - nodejs_gc_pause_seconds_total: Time spent in GC in seconds | ||
// - nodejs_gc_reclaimed_bytes_total: The number of bytes GC has freed | ||
gcStats(register, {prefix})(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import EventEmitter from "events"; | ||
import {PeerId} from "@libp2p/interface-peer-id"; | ||
import StrictEventEmitter from "strict-event-emitter-types"; | ||
import {exportToProtobuf} from "@libp2p/peer-id-factory"; | ||
import {ENR, IDiscv5DiscoveryInputOptions} from "@chainsafe/discv5"; | ||
import {spawn, Thread, Worker} from "@chainsafe/threads"; | ||
import {ILogger} from "@lodestar/utils"; | ||
import {Discv5WorkerApi, Discv5WorkerData} from "./types.js"; | ||
|
||
export type Discv5Opts = { | ||
peerId: PeerId; | ||
discv5: Omit<IDiscv5DiscoveryInputOptions, "metrics" | "searchInterval" | "enabled">; | ||
logger: ILogger; | ||
metrics: boolean; | ||
}; | ||
|
||
export interface IDiscv5Events { | ||
discovered: (enr: ENR) => void; | ||
} | ||
|
||
type Discv5WorkerStatus = | ||
| {status: "stopped"} | ||
| {status: "started"; workerApi: Discv5WorkerApi; subscription: {unsubscribe(): void}}; | ||
|
||
/** | ||
* Wrapper class abstracting the details of discv5 worker instantiation and message-passing | ||
*/ | ||
export class Discv5Worker extends (EventEmitter as {new (): StrictEventEmitter<EventEmitter, IDiscv5Events>}) { | ||
private logger: ILogger; | ||
private status: Discv5WorkerStatus; | ||
|
||
constructor(private opts: Discv5Opts) { | ||
super(); | ||
|
||
this.logger = opts.logger; | ||
this.status = {status: "stopped"}; | ||
} | ||
|
||
async start(): Promise<void> { | ||
if (this.status.status === "started") return; | ||
|
||
const workerData: Discv5WorkerData = { | ||
enrStr: (this.opts.discv5.enr as ENR).encodeTxt(), | ||
peerIdProto: exportToProtobuf(this.opts.peerId), | ||
bindAddr: this.opts.discv5.bindAddr, | ||
config: this.opts.discv5, | ||
bootEnrs: this.opts.discv5.bootEnrs as string[], | ||
metrics: this.opts.metrics, | ||
}; | ||
const worker = new Worker("./worker.js", {workerData} as ConstructorParameters<typeof Worker>[1]); | ||
|
||
const workerApi = await spawn<Discv5WorkerApi>(worker, { | ||
// A Lodestar Node may do very expensive task at start blocking the event loop and causing | ||
// the initialization to timeout. The number below is big enough to almost disable the timeout | ||
timeout: 5 * 60 * 1000, | ||
}); | ||
|
||
const subscription = workerApi.discoveredBuf().subscribe((enrStr) => this.onDiscoveredStr(enrStr)); | ||
|
||
this.status = {status: "started", workerApi, subscription}; | ||
} | ||
|
||
async stop(): Promise<void> { | ||
if (this.status.status === "stopped") return; | ||
|
||
this.status.subscription.unsubscribe(); | ||
await this.status.workerApi.close(); | ||
await Thread.terminate((this.status.workerApi as unknown) as Thread); | ||
|
||
this.status = {status: "stopped"}; | ||
} | ||
|
||
onDiscoveredStr(enrStr: Uint8Array): void { | ||
try { | ||
this.emit("discovered", ENR.decode(Buffer.from(enrStr))); | ||
} catch (e) { | ||
// TODO there is a bug in enr encoding(?) that causes many enrs to be incorrectly encoded (and thus incorrectly decoded) | ||
// this.logger.error("Unable to decode enr", {enr: Buffer.from(enrStr).toString("hex")}, e as Error); | ||
} | ||
} | ||
|
||
async enr(): Promise<ENR> { | ||
if (this.status.status === "started") { | ||
return ENR.decode(Buffer.from(await this.status.workerApi.enrBuf())); | ||
} else { | ||
throw new Error("Cannot get enr before module is started"); | ||
} | ||
} | ||
|
||
async setEnrValue(key: string, value: Uint8Array): Promise<void> { | ||
if (this.status.status === "started") { | ||
await this.status.workerApi.setEnrValue(key, value); | ||
} else { | ||
throw new Error("Cannot setEnrValue before module is started"); | ||
} | ||
} | ||
|
||
async kadValues(): Promise<ENR[]> { | ||
if (this.status.status === "started") { | ||
return (await this.status.workerApi.kadValuesBuf()).map((enrBuf) => ENR.decode(Buffer.from(enrBuf))); | ||
} else { | ||
return []; | ||
} | ||
} | ||
|
||
async findRandomNode(): Promise<ENR[]> { | ||
if (this.status.status === "started") { | ||
return (await this.status.workerApi.findRandomNodeBuf()).map((enrBuf) => ENR.decode(Buffer.from(enrBuf))); | ||
} else { | ||
return []; | ||
} | ||
} | ||
|
||
async metrics(): Promise<string> { | ||
if (this.status.status === "started") { | ||
return await this.status.workerApi.metrics(); | ||
} else { | ||
return ""; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import {Discv5} from "@chainsafe/discv5"; | ||
import {Observable} from "@chainsafe/threads/observable"; | ||
|
||
// TODO export IDiscv5Config so we don't need this convoluted type | ||
type Discv5Config = Parameters<typeof Discv5["create"]>[0]["config"]; | ||
|
||
/** discv5 worker constructor data */ | ||
export interface Discv5WorkerData { | ||
enrStr: string; | ||
peerIdProto: Uint8Array; | ||
bindAddr: string; | ||
config: Discv5Config; | ||
bootEnrs: string[]; | ||
metrics: boolean; | ||
} | ||
|
||
/** | ||
* API exposed by the discv5 worker | ||
* | ||
* Note: ENRs are represented as bytes to facilitate message-passing | ||
*/ | ||
export type Discv5WorkerApi = { | ||
/** The current host ENR */ | ||
enrBuf(): Promise<Uint8Array>; | ||
/** Set a key-value of the current host ENR */ | ||
setEnrValue(key: string, value: Uint8Array): Promise<void>; | ||
|
||
/** Return the ENRs currently in the kad table */ | ||
kadValuesBuf(): Promise<Uint8Array[]>; | ||
/** Begin a random search through the DHT, return discovered ENRs */ | ||
findRandomNodeBuf(): Promise<Uint8Array[]>; | ||
/** Stream of discovered ENRs */ | ||
discoveredBuf(): Observable<Uint8Array>; | ||
|
||
/** Prometheus metrics string */ | ||
metrics(): Promise<string>; | ||
/** tear down discv5 resources */ | ||
close(): Promise<void>; | ||
}; |
Oops, something went wrong.