Skip to content

Commit

Permalink
Print agent diagnose report in CLI output
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tombruijn committed Oct 26, 2021
1 parent fbea22c commit 619b02a
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 2 deletions.
5 changes: 5 additions & 0 deletions packages/nodejs/.changesets/print-agent-diagnose-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
bump: "patch"
---

Print agent diagnose report in diagnose CLI output.
136 changes: 136 additions & 0 deletions packages/nodejs/src/cli/diagnose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -128,6 +159,9 @@ export class Diagnose {
data["host"]["running_in_container"]
)}`
)
this.print_newline()

this.printAgentDiagnose(data["agent"])

this.print_newline()

Expand Down Expand Up @@ -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)

Expand Down
13 changes: 12 additions & 1 deletion packages/nodejs/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
}
Expand Down
2 changes: 1 addition & 1 deletion test/integration/diagnose
Submodule diagnose updated 1 files
+11 −30 spec/diagnose_spec.rb

0 comments on commit 619b02a

Please sign in to comment.