Skip to content

Add Doctor Check

Register custom diagnostic checks so doctor validates your feature's health alongside the built-in checks.

Important

Doctor checks are read-only diagnostics. They must not modify state. Return a setup.CheckResult describing what was found.

Step 1: Write your check functions

Each check receives a context.Context and *props.Props and returns a setup.CheckResult.

package myfeature

import (
    "context"

    "gitlab.com/phpboyscout/go-tool-base/pkg/props"
    "gitlab.com/phpboyscout/go-tool-base/pkg/setup"
)

func checkMyService(_ context.Context, props *props.Props) setup.CheckResult {
    endpoint := props.Config.GetString("myfeature.endpoint")
    if endpoint == "" {
        return setup.CheckResult{
            Name:    "My Service",
            Status:  "warn",
            Message: "endpoint not configured",
        }
    }

    // Perform a health check...
    return setup.CheckResult{
        Name:    "My Service",
        Status:  "pass",
        Message: "reachable at " + endpoint,
    }
}

Step 2: Register checks via the feature registry

Use setup.RegisterChecks in your package's init() block. The CheckProvider function receives *props.Props and returns a slice of setup.CheckFunc, allowing you to conditionally include checks based on configuration.

package myfeature

import (
    "gitlab.com/phpboyscout/go-tool-base/pkg/props"
    "gitlab.com/phpboyscout/go-tool-base/pkg/setup"
)

func init() {
    setup.RegisterChecks(props.FeatureCmd("myfeature"),
        []setup.CheckProvider{
            func(p *props.Props) []setup.CheckFunc {
                return []setup.CheckFunc{
                    checkMyService,
                }
            },
        },
    )
}

Step 3: Import your package

As with initialisers, ensure your package is imported somewhere in the dependency graph โ€” typically via a blank import in your command package:

package command

import (
    _ "github.com/myorg/mytool/pkg/setup/myfeature"
)

When the feature is enabled via props.Tool.IsEnabled(), the doctor command will automatically discover and run your checks.

Combining with Initialisers

If your feature already has an initialiser, you can register checks in the same init() block:

func init() {
    setup.Register(props.FeatureCmd("myfeature"),
        []setup.InitialiserProvider{...},
        []setup.SubcommandProvider{...},
        []setup.FeatureFlag{...},
    )

    setup.RegisterChecks(props.FeatureCmd("myfeature"),
        []setup.CheckProvider{
            func(p *props.Props) []setup.CheckFunc {
                return []setup.CheckFunc{checkMyService}
            },
        },
    )
}

Status Constants

Use the following status strings in your CheckResult:

Status Meaning
"pass" Check succeeded
"warn" Non-fatal issue, feature may work
"fail" Critical problem
"skip" Check not applicable

Tip

Look at the built-in checks in pkg/cmd/doctor/checks.go for reference implementations.