TUN-8768: add job report to diagnostic zipfile
## Summary Add a new job that write to a file the result of all of the other tasks along with possible errors. This file is also added to the root of the diagnostic zip file. Closes TUN-8768
This commit is contained in:
parent
f12036c2da
commit
f07d04d129
|
@ -33,4 +33,5 @@ const (
|
||||||
tunnelStateBaseName = "tunnelstate.json"
|
tunnelStateBaseName = "tunnelstate.json"
|
||||||
cliConfigurationBaseName = "cli-configuration.json"
|
cliConfigurationBaseName = "cli-configuration.json"
|
||||||
configurationBaseName = "configuration.json"
|
configurationBaseName = "configuration.json"
|
||||||
|
taskResultBaseName = "task-result.json"
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,6 +17,29 @@ import (
|
||||||
network "github.com/cloudflare/cloudflared/diagnostic/network"
|
network "github.com/cloudflare/cloudflared/diagnostic/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
taskSuccess = "success"
|
||||||
|
taskFailure = "failure"
|
||||||
|
jobReportName = "job report"
|
||||||
|
tunnelStateJobName = "tunnel state"
|
||||||
|
systemInformationJobName = "system information"
|
||||||
|
goroutineJobName = "goroutine profile"
|
||||||
|
heapJobName = "heap profile"
|
||||||
|
metricsJobName = "metrics"
|
||||||
|
logInformationJobName = "log information"
|
||||||
|
rawNetworkInformationJobName = "raw network information"
|
||||||
|
networkInformationJobName = "network information"
|
||||||
|
cliConfigurationJobName = "cli configuration"
|
||||||
|
configurationJobName = "configuration"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Struct used to hold the results of different routines executing the network collection.
|
||||||
|
type taskResult struct {
|
||||||
|
Result string `json:"result,omitempty"`
|
||||||
|
Err error `json:"error,omitempty"`
|
||||||
|
path string
|
||||||
|
}
|
||||||
|
|
||||||
// Struct used to hold the results of different routines executing the network collection.
|
// Struct used to hold the results of different routines executing the network collection.
|
||||||
type networkCollectionResult struct {
|
type networkCollectionResult struct {
|
||||||
name string
|
name string
|
||||||
|
@ -335,54 +358,54 @@ func createJobs(
|
||||||
rawNetworkCollectorFunc, jsonNetworkCollectorFunc := networkInformationCollectors()
|
rawNetworkCollectorFunc, jsonNetworkCollectorFunc := networkInformationCollectors()
|
||||||
jobs := []collectJob{
|
jobs := []collectJob{
|
||||||
{
|
{
|
||||||
jobName: "tunnel state",
|
jobName: tunnelStateJobName,
|
||||||
fn: tunnelStateCollectEndpointAdapter(client, tunnel, tunnelStateBaseName),
|
fn: tunnelStateCollectEndpointAdapter(client, tunnel, tunnelStateBaseName),
|
||||||
bypass: false,
|
bypass: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
jobName: "system information",
|
jobName: systemInformationJobName,
|
||||||
fn: collectFromEndpointAdapter(client.GetSystemInformation, systemInformationBaseName),
|
fn: collectFromEndpointAdapter(client.GetSystemInformation, systemInformationBaseName),
|
||||||
bypass: noDiagSystem,
|
bypass: noDiagSystem,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
jobName: "goroutine profile",
|
jobName: goroutineJobName,
|
||||||
fn: collectFromEndpointAdapter(client.GetGoroutineDump, goroutinePprofBaseName),
|
fn: collectFromEndpointAdapter(client.GetGoroutineDump, goroutinePprofBaseName),
|
||||||
bypass: noDiagRuntime,
|
bypass: noDiagRuntime,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
jobName: "heap profile",
|
jobName: heapJobName,
|
||||||
fn: collectFromEndpointAdapter(client.GetMemoryDump, heapPprofBaseName),
|
fn: collectFromEndpointAdapter(client.GetMemoryDump, heapPprofBaseName),
|
||||||
bypass: noDiagRuntime,
|
bypass: noDiagRuntime,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
jobName: "metrics",
|
jobName: metricsJobName,
|
||||||
fn: collectFromEndpointAdapter(client.GetMetrics, metricsBaseName),
|
fn: collectFromEndpointAdapter(client.GetMetrics, metricsBaseName),
|
||||||
bypass: noDiagMetrics,
|
bypass: noDiagMetrics,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
jobName: "log information",
|
jobName: logInformationJobName,
|
||||||
fn: func(ctx context.Context) (string, error) {
|
fn: func(ctx context.Context) (string, error) {
|
||||||
return collectLogs(ctx, client, diagContainer, diagPod)
|
return collectLogs(ctx, client, diagContainer, diagPod)
|
||||||
},
|
},
|
||||||
bypass: noDiagLogs,
|
bypass: noDiagLogs,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
jobName: "raw network information",
|
jobName: rawNetworkInformationJobName,
|
||||||
fn: rawNetworkCollectorFunc,
|
fn: rawNetworkCollectorFunc,
|
||||||
bypass: noDiagNetwork,
|
bypass: noDiagNetwork,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
jobName: "network information",
|
jobName: networkInformationJobName,
|
||||||
fn: jsonNetworkCollectorFunc,
|
fn: jsonNetworkCollectorFunc,
|
||||||
bypass: noDiagNetwork,
|
bypass: noDiagNetwork,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
jobName: "cli configuration",
|
jobName: cliConfigurationJobName,
|
||||||
fn: collectFromEndpointAdapter(client.GetCliConfiguration, cliConfigurationBaseName),
|
fn: collectFromEndpointAdapter(client.GetCliConfiguration, cliConfigurationBaseName),
|
||||||
bypass: false,
|
bypass: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
jobName: "configuration",
|
jobName: configurationJobName,
|
||||||
fn: collectFromEndpointAdapter(client.GetTunnelConfiguration, configurationBaseName),
|
fn: collectFromEndpointAdapter(client.GetTunnelConfiguration, configurationBaseName),
|
||||||
bypass: false,
|
bypass: false,
|
||||||
},
|
},
|
||||||
|
@ -391,6 +414,69 @@ func createJobs(
|
||||||
return jobs
|
return jobs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createTaskReport(taskReport map[string]taskResult) (string, error) {
|
||||||
|
dumpHandle, err := os.Create(filepath.Join(os.TempDir(), taskResultBaseName))
|
||||||
|
if err != nil {
|
||||||
|
return "", ErrCreatingTemporaryFile
|
||||||
|
}
|
||||||
|
defer dumpHandle.Close()
|
||||||
|
|
||||||
|
err = json.NewEncoder(dumpHandle).Encode(taskReport)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("error encoding task results: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return dumpHandle.Name(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func runJobs(ctx context.Context, jobs []collectJob, log *zerolog.Logger) map[string]taskResult {
|
||||||
|
jobReport := make(map[string]taskResult, len(jobs))
|
||||||
|
|
||||||
|
for _, job := range jobs {
|
||||||
|
if job.bypass {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info().Msgf("Collecting %s...", job.jobName)
|
||||||
|
path, err := job.fn(ctx)
|
||||||
|
|
||||||
|
var result taskResult
|
||||||
|
if err != nil {
|
||||||
|
result = taskResult{Result: taskFailure, Err: err, path: path}
|
||||||
|
|
||||||
|
log.Error().Err(err).Msgf("Job: %s finished with error.", job.jobName)
|
||||||
|
} else {
|
||||||
|
result = taskResult{Result: taskSuccess, Err: nil, path: path}
|
||||||
|
|
||||||
|
log.Info().Msgf("Collected %s.", job.jobName)
|
||||||
|
}
|
||||||
|
|
||||||
|
jobReport[job.jobName] = result
|
||||||
|
}
|
||||||
|
|
||||||
|
taskReportName, err := createTaskReport(jobReport)
|
||||||
|
|
||||||
|
var result taskResult
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
result = taskResult{
|
||||||
|
Result: taskFailure,
|
||||||
|
path: taskReportName,
|
||||||
|
Err: err,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = taskResult{
|
||||||
|
Result: taskSuccess,
|
||||||
|
path: taskReportName,
|
||||||
|
Err: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jobReport[jobReportName] = result
|
||||||
|
|
||||||
|
return jobReport
|
||||||
|
}
|
||||||
|
|
||||||
func RunDiagnostic(
|
func RunDiagnostic(
|
||||||
log *zerolog.Logger,
|
log *zerolog.Logger,
|
||||||
options Options,
|
options Options,
|
||||||
|
@ -410,7 +496,6 @@ func RunDiagnostic(
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
paths := make([]string, 0)
|
|
||||||
jobs := createJobs(
|
jobs := createJobs(
|
||||||
client,
|
client,
|
||||||
tunnel,
|
tunnel,
|
||||||
|
@ -423,27 +508,17 @@ func RunDiagnostic(
|
||||||
options.Toggles.NoDiagNetwork,
|
options.Toggles.NoDiagNetwork,
|
||||||
)
|
)
|
||||||
|
|
||||||
for _, job := range jobs {
|
jobsReport := runJobs(ctx, jobs, log)
|
||||||
if job.bypass {
|
paths := make([]string, 0)
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info().Msgf("Collecting %s...", job.jobName)
|
for _, v := range jobsReport {
|
||||||
path, err := job.fn(ctx)
|
paths = append(paths, v.path)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if !errors.Is(err, ErrCreatingTemporaryFile) {
|
if !errors.Is(v.Err, ErrCreatingTemporaryFile) {
|
||||||
os.Remove(path)
|
os.Remove(v.path)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info().Msgf("Collected %s.", job.jobName)
|
|
||||||
|
|
||||||
paths = append(paths, path)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zipfile, err := CreateDiagnosticZipFile(zipName, paths)
|
zipfile, err := CreateDiagnosticZipFile(zipName, paths)
|
||||||
|
|
Loading…
Reference in New Issue