in pkg/client/client_v2.go [976:1060]
func (c *clientV2) tryPerformDiagnostics(actionResults chan *proto.ActionResponse, action *proto.ActionRequest) {
// see if we can unpack params
foundParams := map[string]bool{}
if len(action.GetParams()) > 0 {
params := DiagnosticParams{}
err := json.Unmarshal(action.GetParams(), ¶ms)
if err != nil {
actionResults <- &proto.ActionResponse{
Token: c.token,
Id: action.GetId(),
Status: proto.ActionResponse_FAILED,
Result: []byte(fmt.Sprintf("error unmarshaling json in params: %s", err)),
}
}
// convert to a map for easier checking
for _, param := range params.AdditionalMetrics {
foundParams[param] = true
}
}
// break apart the action:
// if it's unit-level, fetch unit-level diagnostics.
// if component-level, just run diagnostics that are registered at the client level.
diagHooks := make(map[string]diagHook)
if action.GetLevel() == proto.ActionRequest_COMPONENT || action.GetLevel() == proto.ActionRequest_ALL {
c.dmx.RLock()
for n, d := range c.diagHooks {
diagHooks[n] = d
}
c.dmx.RUnlock()
}
if action.GetLevel() == proto.ActionRequest_UNIT || action.GetLevel() == proto.ActionRequest_ALL {
// find the unit
c.unitsMu.RLock()
unit := c.findUnit(action.GetUnitId(), UnitType(action.GetUnitType()))
c.unitsMu.RUnlock()
if unit == nil {
actionResults <- &proto.ActionResponse{
Token: c.token,
Id: action.GetId(),
Status: proto.ActionResponse_FAILED,
Result: ActionErrUnitNotFound,
}
return
}
// gather diagnostics hooks for this unit
unit.dmx.RLock()
for n, d := range unit.diagHooks {
diagHooks[n] = d
}
unit.dmx.RUnlock()
}
// perform diagnostics in goroutine, so we don't block other work
go func() {
res := make([]*proto.ActionDiagnosticUnitResult, 0, len(diagHooks))
for diagName, diagHook := range diagHooks {
// if the hook came with a tag, check it.
// if the callback was registered with a tag but none was found in the request, skip it
if diagHook.optionalWithParamTag != "" {
if _, ok := foundParams[diagHook.optionalWithParamTag]; !ok {
continue
}
}
content := diagHook.hook()
res = append(res, &proto.ActionDiagnosticUnitResult{
Name: diagName,
Filename: diagHook.filename,
Description: diagHook.description,
ContentType: diagHook.contentType,
Content: content,
Generated: timestamppb.New(time.Now().UTC()),
})
}
actionResults <- &proto.ActionResponse{
Token: c.token,
Id: action.GetId(),
Status: proto.ActionResponse_SUCCESS,
Diagnostic: res,
}
}()
}