From 619b02a30b453b1cf44ad228a1e59233c06602dc Mon Sep 17 00:00:00 2001 From: Tom de Bruijn Date: Tue, 26 Oct 2021 16:51:10 +0200 Subject: [PATCH] Print agent diagnose report in CLI output The agent diagnose report wasn't printed in the diagnose report as the only missing section. It was sent with the diagnose report, just not printed. I don't understand much of TypeScript. I had to add a lot more type definitions than I expected for the functions, which is why the new types exist at the top of the `cli/diagnose.ts` file. I considered changing the structure of how agent returns this report, but I was already far enough done a rabbit hole trying to make this work in the first place. Looking back I structured the report by the agent and extension in such as way that it was future proof (adding more tests to it later), but I haven't found a way to easily parse or format this in any integration or on the server side validator. This may be a nice thing to change to make this whole thing more easy to maintain. To change it to an easier (less nested) format. --- .../print-agent-diagnose-report.md | 5 + packages/nodejs/src/cli/diagnose.ts | 136 ++++++++++++++++++ packages/nodejs/src/extension.ts | 13 +- test/integration/diagnose | 2 +- 4 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 packages/nodejs/.changesets/print-agent-diagnose-report.md diff --git a/packages/nodejs/.changesets/print-agent-diagnose-report.md b/packages/nodejs/.changesets/print-agent-diagnose-report.md new file mode 100644 index 00000000..7181f430 --- /dev/null +++ b/packages/nodejs/.changesets/print-agent-diagnose-report.md @@ -0,0 +1,5 @@ +--- +bump: "patch" +--- + +Print agent diagnose report in diagnose CLI output. diff --git a/packages/nodejs/src/cli/diagnose.ts b/packages/nodejs/src/cli/diagnose.ts index 115d22ae..ec0e4c9e 100644 --- a/packages/nodejs/src/cli/diagnose.ts +++ b/packages/nodejs/src/cli/diagnose.ts @@ -5,6 +5,37 @@ const path = require("path") const util = require("util") const readline = require("readline") +interface AgentUnitTestDefinition { + label: string + values?: { + [key: string]: string + } +} +interface AgentTestDefinition { + [key: string]: { + // component: agent/extension + label: string + tests: { + [key: string]: { + // category: config/boot/some_dir/etc + [key: string]: AgentUnitTestDefinition // test: valid/started/uid/gid/etc + } + } + } +} +interface AgentReportUnit { + result?: string | boolean + error?: any + output?: any +} +interface AgentReport { + [key: string]: { + [key: string]: { + [key: string]: AgentReportUnit + } + } +} + export class Diagnose { public async run() { const data = await new DiagnoseTool({}).generate() @@ -128,6 +159,9 @@ export class Diagnose { data["host"]["running_in_container"] )}` ) + this.print_newline() + + this.printAgentDiagnose(data["agent"]) this.print_newline() @@ -240,6 +274,108 @@ export class Diagnose { } } + printAgentDiagnose(report: AgentReport) { + if (report["error"]) { + console.log(" Error while parsing agent diagnostics report:") + console.log(` Error: ${report["error"]}`) + console.log(` Output: ${report["output"]}`) + } else { + console.log("Agent diagnostics") + const reportDefinition = this.agentDiagnosticTestDefinition() + for (const component in reportDefinition) { + const componentDefinition = reportDefinition[component] + const componentTests = componentDefinition["tests"] + console.log(` ${componentDefinition.label}`) + for (const category in componentTests) { + const tests = componentTests[category] + for (const testName in tests) { + const testDefinition = tests[testName] + const testReport = report[component][category][testName] + this.printAgentTest(testDefinition, testReport) + } + } + } + } + } + + printAgentTest(definition: AgentUnitTestDefinition, test: AgentReportUnit) { + const value = test["result"] + const error = test["error"] + const output = test["output"] + + let formattedValue + if (value !== undefined) { + const stringValue = value.toString() + formattedValue = definition.values + ? definition.values[stringValue] + : stringValue + } + if (!formattedValue) { + formattedValue = "-" + } + console.log(` ${definition["label"]}: ${formattedValue}`) + if (error) { + console.log(` Error: ${error}`) + } + if (output) { + console.log(` Output: ${output}`) + } + } + + agentDiagnosticTestDefinition(): AgentTestDefinition { + return { + extension: { + label: "Extension tests", + tests: { + config: { + valid: { + label: "Configuration", + values: { true: "valid", false: "invalid" } + } + } + } + }, + agent: { + label: "Agent tests", + tests: { + boot: { + started: { + label: "Started", + values: { true: "started", false: "not started" } + } + }, + host: { + uid: { label: "Process user id" }, + gid: { label: "Process user group id" } + }, + config: { + valid: { + label: "Configuration", + values: { true: "valid", false: "invalid" } + } + }, + logger: { + started: { + label: "Logger", + values: { true: "started", false: "not started" } + } + }, + working_directory_stat: { + uid: { label: "Working directory user id" }, + gid: { label: "Working directory user group id" }, + mode: { label: "Working directory permissions" } + }, + lock_path: { + created: { + label: "Lock path", + values: { true: "writable", false: "not writable" } + } + } + } + } + } + } + send_report(data: object) { const json = JSON.stringify(data) diff --git a/packages/nodejs/src/extension.ts b/packages/nodejs/src/extension.ts index 12477652..721a57f9 100644 --- a/packages/nodejs/src/extension.ts +++ b/packages/nodejs/src/extension.ts @@ -50,7 +50,18 @@ export class Extension { public diagnose(): object { if (this.isLoaded) { - return JSON.parse(extension.diagnoseRaw()) + process.env._APPSIGNAL_DIAGNOSE = "true" + const diagnostics_report_string = extension.diagnoseRaw() + delete process.env._APPSIGNAL_DIAGNOSE + + try { + return JSON.parse(diagnostics_report_string) + } catch (error) { + return { + error: error, + output: diagnostics_report_string.split("\n") + } + } } else { return {} } diff --git a/test/integration/diagnose b/test/integration/diagnose index f53dfd3c..a3d94d92 160000 --- a/test/integration/diagnose +++ b/test/integration/diagnose @@ -1 +1 @@ -Subproject commit f53dfd3c0405e4d7d5137d99a654547bdfb04831 +Subproject commit a3d94d92f2e0d3307c7fb62978d4069190acf237