in internal/pkg/agent/application/coordinator/coordinator.go [789:1049]
func (c *Coordinator) DiagnosticHooks() diagnostics.Hooks {
hooks := diagnostics.Hooks{
{
Name: "agent-info",
Filename: "agent-info.yaml",
Description: "current state of the agent information of the running Elastic Agent",
ContentType: "application/yaml",
Hook: func(_ context.Context) []byte {
meta, err := c.agentInfo.ECSMetadata(c.logger)
if err != nil {
c.logger.Errorw("Error getting ECS metadata", "error.message", err)
}
output := struct {
Headers map[string]string `yaml:"headers"`
LogLevel string `yaml:"log_level"`
RawLogLevel string `yaml:"log_level_raw"`
Metadata *info.ECSMeta `yaml:"metadata"`
}{
Headers: c.agentInfo.Headers(),
LogLevel: c.agentInfo.LogLevel(),
RawLogLevel: c.agentInfo.RawLogLevel(),
Metadata: meta,
}
o, err := yaml.Marshal(output)
if err != nil {
return []byte(fmt.Sprintf("error: %q", err))
}
return o
},
},
{
Name: "local-config",
Filename: "local-config.yaml",
Description: "current local configuration of the running Elastic Agent",
ContentType: "application/yaml",
Hook: func(_ context.Context) []byte {
if c.cfg == nil {
return []byte("error: failed no local configuration")
}
o, err := yaml.Marshal(c.cfg)
if err != nil {
return []byte(fmt.Sprintf("error: %q", err))
}
return o
},
},
{
Name: "pre-config",
Filename: "pre-config.yaml",
Description: "current pre-configuration of the running Elastic Agent before variable substitution",
ContentType: "application/yaml",
Hook: func(_ context.Context) []byte {
if c.ast == nil {
return []byte("error: failed no configuration by the coordinator")
}
cfg, err := c.ast.Map()
if err != nil {
return []byte(fmt.Sprintf("error: %q", err))
}
o, err := yaml.Marshal(cfg)
if err != nil {
return []byte(fmt.Sprintf("error: %q", err))
}
return o
},
},
{
Name: "variables",
Filename: "variables.yaml",
Description: "current variable contexts of the running Elastic Agent",
ContentType: "application/yaml",
Hook: func(_ context.Context) []byte {
if c.vars == nil {
return []byte("error: failed no variables by the coordinator")
}
vars := make([]map[string]interface{}, 0, len(c.vars))
for _, v := range c.vars {
m, err := v.Map()
if err != nil {
return []byte(fmt.Sprintf("error: %q", err))
}
vars = append(vars, m)
}
o, err := yaml.Marshal(struct {
Variables []map[string]interface{} `yaml:"variables"`
}{
Variables: vars,
})
if err != nil {
return []byte(fmt.Sprintf("error: %q", err))
}
return o
},
},
{
Name: "computed-config",
Filename: "computed-config.yaml",
Description: "current computed configuration of the running Elastic Agent after variable substitution",
ContentType: "application/yaml",
Hook: func(_ context.Context) []byte {
cfg := c.derivedConfig
o, err := yaml.Marshal(cfg)
if err != nil {
return []byte(fmt.Sprintf("error: %q", err))
}
return o
},
},
{
Name: "components-expected",
Filename: "components-expected.yaml",
Description: "current expected components model of the running Elastic Agent",
ContentType: "application/yaml",
Hook: func(_ context.Context) []byte {
comps := c.componentModel
o, err := yaml.Marshal(struct {
Components []component.Component `yaml:"components"`
}{
Components: comps,
})
if err != nil {
return []byte(fmt.Sprintf("error: %q", err))
}
return o
},
},
{
Name: "components-actual",
Filename: "components-actual.yaml",
Description: "actual components model of the running Elastic Agent",
ContentType: "application/yaml",
Hook: func(_ context.Context) []byte {
components := c.State().Components
componentConfigs := make([]component.Component, len(components))
for i := 0; i < len(components); i++ {
componentConfigs[i] = components[i].Component
}
o, err := yaml.Marshal(struct {
Components []component.Component `yaml:"components"`
}{
Components: componentConfigs,
})
if err != nil {
return []byte(fmt.Sprintf("error: %q", err))
}
return o
},
},
{
Name: "state",
Filename: "state.yaml",
Description: "current state of running components by the Elastic Agent",
ContentType: "application/yaml",
Hook: func(_ context.Context) []byte {
type StateComponentOutput struct {
ID string `yaml:"id"`
State runtime.ComponentState `yaml:"state"`
}
type StateCollectorStatus struct {
Status componentstatus.Status `yaml:"status"`
Err string `yaml:"error,omitempty"`
Timestamp string `yaml:"timestamp"`
Components map[string]*StateCollectorStatus `yaml:"components,omitempty"`
}
type StateHookOutput struct {
State agentclient.State `yaml:"state"`
Message string `yaml:"message"`
FleetState agentclient.State `yaml:"fleet_state"`
FleetMessage string `yaml:"fleet_message"`
LogLevel logp.Level `yaml:"log_level"`
Components []StateComponentOutput `yaml:"components"`
Collector *StateCollectorStatus `yaml:"collector,omitempty"`
UpgradeDetails *details.Details `yaml:"upgrade_details,omitempty"`
}
var toCollectorStatus func(status *status.AggregateStatus) *StateCollectorStatus
toCollectorStatus = func(status *status.AggregateStatus) *StateCollectorStatus {
s := &StateCollectorStatus{
Status: status.Status(),
Timestamp: status.Timestamp().Format(time.RFC3339Nano),
}
statusErr := status.Err()
if statusErr != nil {
s.Err = statusErr.Error()
}
if len(status.ComponentStatusMap) > 0 {
s.Components = make(map[string]*StateCollectorStatus, len(status.ComponentStatusMap))
for k, v := range status.ComponentStatusMap {
s.Components[k] = toCollectorStatus(v)
}
}
return s
}
s := c.State()
n := len(s.Components)
compStates := make([]StateComponentOutput, n)
for i := 0; i < n; i++ {
compStates[i] = StateComponentOutput{
ID: s.Components[i].Component.ID,
State: s.Components[i].State,
}
}
var collectorStatus *StateCollectorStatus
if s.Collector != nil {
collectorStatus = toCollectorStatus(s.Collector)
}
output := StateHookOutput{
State: s.State,
Message: s.Message,
FleetState: s.FleetState,
FleetMessage: s.FleetMessage,
LogLevel: s.LogLevel,
Components: compStates,
Collector: collectorStatus,
UpgradeDetails: s.UpgradeDetails,
}
o, err := yaml.Marshal(output)
if err != nil {
return []byte(fmt.Sprintf("error: %q", err))
}
return o
},
},
{
Name: "otel",
Filename: "otel.yaml",
Description: "current otel configuration used by the Elastic Agent",
ContentType: "application/yaml",
Hook: func(_ context.Context) []byte {
if c.otelCfg == nil {
return []byte("no active OTel configuration")
}
o, err := yaml.Marshal(c.otelCfg.ToStringMap())
if err != nil {
return []byte(fmt.Sprintf("error: failed to convert to yaml: %v", err))
}
return o
},
},
diagnostics.Hook{
Name: "otel-final",
Filename: "otel-final.yaml",
Description: "Final otel configuration used by the Elastic Agent. Includes hybrid mode config and component config.",
ContentType: "application/yaml",
Hook: func(_ context.Context) []byte {
if c.finalOtelCfg == nil {
return []byte("no active OTel configuration")
}
o, err := yaml.Marshal(c.finalOtelCfg.ToStringMap())
if err != nil {
return []byte(fmt.Sprintf("error: failed to convert to yaml: %v", err))
}
return o
},
},
}
return hooks
}