-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: improve logging of debug information (#90)
* feat: create zip archive will all debug information if voting invalid
- Loading branch information
1 parent
ca53fe1
commit ba3c1d6
Showing
17 changed files
with
431 additions
and
225 deletions.
There are no files selected for viewing
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
116 changes: 96 additions & 20 deletions
116
common/protocol/src/methods/helpers/archiveDebugBundle.ts
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,33 +1,109 @@ | ||
import { appendFileSync, existsSync, mkdirSync } from "fs"; | ||
import { existsSync, mkdirSync, createWriteStream, readFileSync } from "fs"; | ||
import path from "path"; | ||
import { DataItem, Validator } from "../.."; | ||
import { DataItem, standardizeError, Validator } from "../.."; | ||
import JSZip from "jszip"; | ||
import * as Diff from "diff"; | ||
import { VoteType } from "@kyvejs/types/client/kyve/bundles/v1beta1/tx"; | ||
|
||
/** | ||
* archiveDebugBundle is used for storing a bundle for debug | ||
* purposes if the validator voted with invalid | ||
* purposes if the validator voted with abstain or invalid | ||
* | ||
* @method archiveDebugBundle | ||
* @param {Validator} this | ||
* @param {DataItem[]} bundle local validation bundle which should get archived for debug purposes | ||
* @param {number} vote type of the vote | ||
* @param {DataItem[]} proposedBundle the proposed bundle uploaded to the storage provider | ||
* @param {DataItem[]} validationBundle the local bundle from the node | ||
* @param {object} metadata additional info about the bundle | ||
* @return {void} | ||
*/ | ||
export function archiveDebugBundle(this: Validator, bundle: DataItem[]): void { | ||
// if "debug" folder under target path does not exist create it | ||
if (!existsSync(path.join(this.home, `debug`))) { | ||
mkdirSync(path.join(this.home, `debug`), { recursive: true }); | ||
} | ||
export function archiveDebugBundle( | ||
this: Validator, | ||
vote: number, | ||
proposedBundle: DataItem[], | ||
validationBundle: DataItem[], | ||
metadata: object | ||
): void { | ||
try { | ||
// if "debug" folder under target path does not exist create it | ||
if (!existsSync(path.join(this.home, `debug`))) { | ||
mkdirSync(path.join(this.home, `debug`), { recursive: true }); | ||
} | ||
|
||
const zip = new JSZip(); | ||
|
||
// save metadata which includes vote reasons and args | ||
const metadata_str = JSON.stringify(metadata || {}, null, 2); | ||
zip.file("metadata.json", metadata_str); | ||
|
||
// save current pool state including the raw bundle proposal | ||
const pool_str = JSON.stringify(this.pool || {}, null, 2); | ||
zip.file("pool.json", pool_str); | ||
|
||
// save the proposed bundle from the uploader | ||
const proposed_bundle_str = JSON.stringify(proposedBundle || [], null, 2); | ||
zip.file("proposed_bundle.json", proposed_bundle_str); | ||
|
||
const storageId = this.pool?.bundle_proposal?.storage_id ?? ""; | ||
// save the locally created bundle from this node | ||
const validation_bundle_str = JSON.stringify( | ||
validationBundle || [], | ||
null, | ||
2 | ||
); | ||
zip.file("validation_bundle.json", validation_bundle_str); | ||
|
||
// save current pool state to specified path target | ||
appendFileSync( | ||
path.join(this.home, `debug`, `pool_state_${storageId}.json`), | ||
JSON.stringify(this.pool || {}) | ||
); | ||
// save the diff of the proposed and local bundle | ||
const diff_str = Diff.createTwoFilesPatch( | ||
"proposed_bundle.json", | ||
"validation_bundle.json", | ||
proposed_bundle_str, | ||
validation_bundle_str | ||
); | ||
zip.file("diff.txt", diff_str); | ||
|
||
// save local bundle to specified path target | ||
appendFileSync( | ||
path.join(this.home, `debug`, `validation_bundle_${storageId}.json`), | ||
JSON.stringify(bundle || {}) | ||
); | ||
// save the logfile of the current session | ||
const debug_str = readFileSync(path.join(this.home, "logs", this.logFile)); | ||
zip.file("debug.log", debug_str); | ||
|
||
// get human readable vote | ||
let voteType = ""; | ||
|
||
switch (vote) { | ||
case VoteType.VOTE_TYPE_VALID: | ||
voteType = "valid"; | ||
break; | ||
case VoteType.VOTE_TYPE_INVALID: | ||
voteType = "invalid"; | ||
break; | ||
case VoteType.VOTE_TYPE_ABSTAIN: | ||
voteType = "abstain"; | ||
break; | ||
case VoteType.VOTE_TYPE_UNSPECIFIED: | ||
voteType = "unspecified"; | ||
break; | ||
default: | ||
voteType = "unrecognized"; | ||
} | ||
|
||
const storageId = this.pool?.bundle_proposal?.storage_id ?? ""; | ||
const zipPath = path.join( | ||
this.home, | ||
`debug`, | ||
`${voteType}_${Math.floor(Date.now() / 1000)}_${storageId.slice( | ||
0, | ||
6 | ||
)}.zip` | ||
); | ||
|
||
// save zip file | ||
zip | ||
.generateNodeStream({ type: "nodebuffer", streamFiles: true }) | ||
.pipe(createWriteStream(zipPath)) | ||
.on("finish", () => { | ||
this.logger.info("Successfully saved debug information"); | ||
}); | ||
} catch (err) { | ||
this.logger.error("Failed to save debug information"); | ||
this.logger.error(standardizeError(err)); | ||
} | ||
} |
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
33 changes: 33 additions & 0 deletions
33
common/protocol/src/methods/validate/parseProposedBundle.ts
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,33 @@ | ||
import { Validator } from "../.."; | ||
import { DataItem } from "../../types"; | ||
import { bytesToBundle } from "../../utils"; | ||
|
||
/** | ||
* parseProposedBundle takes the raw data from the storage | ||
* provider and tries to decompress and parse it back to | ||
* the original JSON format | ||
* | ||
* @method parseProposedBundle | ||
* @param {Validator} this | ||
* @param {number} updatedAt | ||
* @return {Promise<DataItem[] | null>} | ||
*/ | ||
export async function parseProposedBundle( | ||
this: Validator, | ||
storageProviderResult: Buffer | ||
): Promise<DataItem[]> { | ||
// get current compression defined on pool | ||
this.logger.debug(`this.compressionFactory()`); | ||
const compression = this.compressionFactory(); | ||
|
||
// decompress the bundle with the specified compression type | ||
this.logger.debug(`this.compression.decompress($STORAGE_PROVIDER_RESULT)`); | ||
const decompressed = await compression.decompress(storageProviderResult); | ||
|
||
this.logger.info( | ||
`Successfully decompressed bundle with Compression:${compression.name}` | ||
); | ||
|
||
// parse raw decompressed bundle back to json format | ||
return bytesToBundle(decompressed); | ||
} |
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
Oops, something went wrong.