grafana/apps/advisor
Tania 2c7349f863
Actionlint / Lint GitHub Actions files (push) Waiting to run Details
Backend Code Checks / Validate Backend Configs (push) Waiting to run Details
Backend Unit Tests / Detect whether code changed (push) Waiting to run Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (1/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (2/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (3/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (4/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (5/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (6/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (7/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana (${{ matrix.shard }}) (8/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (1/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (2/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (3/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (4/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (5/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (6/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (7/8) (push) Blocked by required conditions Details
Backend Unit Tests / Grafana Enterprise (${{ matrix.shard }}) (8/8) (push) Blocked by required conditions Details
Backend Unit Tests / All backend unit tests complete (push) Blocked by required conditions Details
CodeQL checks / Analyze (actions) (push) Waiting to run Details
CodeQL checks / Analyze (go) (push) Waiting to run Details
CodeQL checks / Analyze (javascript) (push) Waiting to run Details
Lint Frontend / Detect whether code changed (push) Waiting to run Details
Lint Frontend / Lint (push) Blocked by required conditions Details
Lint Frontend / Typecheck (push) Blocked by required conditions Details
Lint Frontend / Betterer (push) Blocked by required conditions Details
golangci-lint / lint-go (push) Waiting to run Details
Crowdin Upload Action / upload-sources-to-crowdin (push) Waiting to run Details
Verify i18n / verify-i18n (push) Waiting to run Details
Documentation / Build & Verify Docs (push) Waiting to run Details
End-to-end tests / Detect whether code changed (push) Waiting to run Details
End-to-end tests / Build & Package Grafana (push) Blocked by required conditions Details
End-to-end tests / Build E2E test runner (push) Blocked by required conditions Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env dashboardScene=false", e2e/old-arch/dashboards-suite, dashboards-suite (old arch)) (push) Blocked by required conditions Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env dashboardScene=false", e2e/old-arch/panels-suite, panels-suite (old arch)) (push) Blocked by required conditions Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env dashboardScene=false", e2e/old-arch/smoke-tests-suite, smoke-tests-suite (old arch)) (push) Blocked by required conditions Details
End-to-end tests / ${{ matrix.suite }} (--flags="--env dashboardScene=false", e2e/old-arch/various-suite, various-suite (old arch)) (push) Blocked by required conditions Details
End-to-end tests / ${{ matrix.suite }} (e2e/dashboards-suite, dashboards-suite) (push) Blocked by required conditions Details
End-to-end tests / ${{ matrix.suite }} (e2e/panels-suite, panels-suite) (push) Blocked by required conditions Details
End-to-end tests / ${{ matrix.suite }} (e2e/various-suite, various-suite) (push) Blocked by required conditions Details
End-to-end tests / Verify Storybook (Playwright) (push) Blocked by required conditions Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (1, 8) (push) Blocked by required conditions Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (2, 8) (push) Blocked by required conditions Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (3, 8) (push) Blocked by required conditions Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (4, 8) (push) Blocked by required conditions Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (5, 8) (push) Blocked by required conditions Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (6, 8) (push) Blocked by required conditions Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (7, 8) (push) Blocked by required conditions Details
End-to-end tests / Playwright E2E tests (${{ matrix.shard }}/${{ matrix.shardTotal }}) (8, 8) (push) Blocked by required conditions Details
End-to-end tests / All Playwright tests complete (push) Blocked by required conditions Details
End-to-end tests / A11y test (push) Blocked by required conditions Details
End-to-end tests / All E2E tests complete (push) Blocked by required conditions Details
Frontend tests / Detect whether code changed (push) Waiting to run Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (1) (push) Blocked by required conditions Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (2) (push) Blocked by required conditions Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (3) (push) Blocked by required conditions Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (4) (push) Blocked by required conditions Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (5) (push) Blocked by required conditions Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (6) (push) Blocked by required conditions Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (7) (push) Blocked by required conditions Details
Frontend tests / Unit tests (${{ matrix.chunk }} / 8) (8) (push) Blocked by required conditions Details
Frontend tests / Decoupled plugin tests (push) Blocked by required conditions Details
Frontend tests / All frontend unit tests complete (push) Blocked by required conditions Details
Integration Tests / Sqlite (${{ matrix.shard }}) (1/8) (push) Waiting to run Details
Integration Tests / Sqlite (${{ matrix.shard }}) (2/8) (push) Waiting to run Details
Integration Tests / Sqlite (${{ matrix.shard }}) (3/8) (push) Waiting to run Details
Integration Tests / Sqlite (${{ matrix.shard }}) (4/8) (push) Waiting to run Details
Integration Tests / Sqlite (${{ matrix.shard }}) (5/8) (push) Waiting to run Details
Integration Tests / Sqlite (${{ matrix.shard }}) (6/8) (push) Waiting to run Details
Integration Tests / Sqlite (${{ matrix.shard }}) (7/8) (push) Waiting to run Details
Integration Tests / Sqlite (${{ matrix.shard }}) (8/8) (push) Waiting to run Details
Integration Tests / MySQL (${{ matrix.shard }}) (1/8) (push) Waiting to run Details
Integration Tests / MySQL (${{ matrix.shard }}) (2/8) (push) Waiting to run Details
Integration Tests / MySQL (${{ matrix.shard }}) (3/8) (push) Waiting to run Details
Integration Tests / MySQL (${{ matrix.shard }}) (4/8) (push) Waiting to run Details
Integration Tests / MySQL (${{ matrix.shard }}) (5/8) (push) Waiting to run Details
Integration Tests / MySQL (${{ matrix.shard }}) (6/8) (push) Waiting to run Details
Integration Tests / MySQL (${{ matrix.shard }}) (7/8) (push) Waiting to run Details
Integration Tests / MySQL (${{ matrix.shard }}) (8/8) (push) Waiting to run Details
Integration Tests / Postgres (${{ matrix.shard }}) (1/8) (push) Waiting to run Details
Integration Tests / Postgres (${{ matrix.shard }}) (2/8) (push) Waiting to run Details
Integration Tests / Postgres (${{ matrix.shard }}) (3/8) (push) Waiting to run Details
Integration Tests / Postgres (${{ matrix.shard }}) (4/8) (push) Waiting to run Details
Integration Tests / Postgres (${{ matrix.shard }}) (5/8) (push) Waiting to run Details
Integration Tests / Postgres (${{ matrix.shard }}) (6/8) (push) Waiting to run Details
Integration Tests / Postgres (${{ matrix.shard }}) (7/8) (push) Waiting to run Details
Integration Tests / Postgres (${{ matrix.shard }}) (8/8) (push) Waiting to run Details
Integration Tests / All backend integration tests complete (push) Blocked by required conditions Details
publish-technical-documentation-next / sync (push) Waiting to run Details
Reject GitHub secrets / reject-gh-secrets (push) Waiting to run Details
Build Release Packages / setup (push) Waiting to run Details
Build Release Packages / Dispatch grafana-enterprise build (push) Blocked by required conditions Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:darwin/amd64, darwin-amd64) (push) Blocked by required conditions Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:darwin/arm64, darwin-arm64) (push) Blocked by required conditions Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/amd64,deb:grafana:linux/amd64,rpm:grafana:linux/amd64,docker:grafana:linux/amd64,docker:grafana:linux/amd64:ubuntu,npm:grafana,storybook, linux-amd64) (push) Blocked by required conditions Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/arm/v6,deb:grafana:linux/arm/v6, linux-armv6) (push) Blocked by required conditions Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/arm/v7,deb:grafana:linux/arm/v7,docker:grafana:linux/arm/v7,docker:grafana:linux/arm/v7:ubuntu, linux-armv7) (push) Blocked by required conditions Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/arm64,deb:grafana:linux/arm64,rpm:grafana:linux/arm64,docker:grafana:linux/arm64,docker:grafana:linux/arm64:ubuntu, linux-arm64) (push) Blocked by required conditions Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:linux/s390x,deb:grafana:linux/s390x,rpm:grafana:linux/s390x,docker:grafana:linux/s390x,docker:grafana:linux/s390x:ubuntu, linux-s390x) (push) Blocked by required conditions Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:windows/amd64,zip:grafana:windows/amd64,msi:grafana:windows/amd64, windows-amd64) (push) Blocked by required conditions Details
Build Release Packages / ${{ needs.setup.outputs.version }} / ${{ matrix.name }} (targz:grafana:windows/arm64,zip:grafana:windows/arm64, windows-arm64) (push) Blocked by required conditions Details
Build Release Packages / Upload artifacts (push) Blocked by required conditions Details
Run dashboard schema v2 e2e / dashboard-schema-v2-e2e (push) Waiting to run Details
Shellcheck / Shellcheck scripts (push) Waiting to run Details
Run Storybook a11y tests / Detect whether code changed (push) Waiting to run Details
Run Storybook a11y tests / Run Storybook a11y tests (push) Blocked by required conditions Details
Swagger generated code / Verify committed API specs match (push) Waiting to run Details
Dispatch sync to mirror / dispatch-job (push) Waiting to run Details
trigger-dashboard-search-e2e / trigger-search-e2e (push) Waiting to run Details
Trivy Scan / trivy-scan (push) Waiting to run Details
OpenFeature: Use types from Go Feature Flag pkg (#108802)
* Use go feature flag types

* Add go-feature-flag module

* Update go.mod

* Update test

* Fix
2025-07-29 15:05:59 +02:00
..
kinds K8s: Add App SDK installer (#107773) 2025-07-21 13:32:15 -04:00
pkg Advisor: Fix paginated requests for checks (#108583) 2025-07-25 13:42:16 +02:00
Makefile K8s: Add App SDK installer (#107773) 2025-07-21 13:32:15 -04:00
README.md Update dependency prettier to v3.6.2 (#108689) 2025-07-25 17:47:44 +01:00
go.mod OpenFeature: Use types from Go Feature Flag pkg (#108802) 2025-07-29 15:05:59 +02:00
go.sum OpenFeature: Use types from Go Feature Flag pkg (#108802) 2025-07-29 15:05:59 +02:00

README.md

Grafana Advisor - Implementing New Checks

This guide explains how to implement new checks in the Grafana Advisor system. The Advisor system allows you to create custom checks that can validate various aspects of your Grafana instance.

Check Structure

A check in Grafana Advisor consists of two main components:

  1. A main check struct that implements the checks.Check interface
  2. One or more step structs that implement the checks.Step interface

Implementing a New Check

1. Create the Check Package

Create a new package in pkg/app/checks/ for your check. For example, if you're creating a check for validating configuration fields, you might create pkg/app/checks/configchecks/. Add a check.go file to the package, there we will implement the check interface. Let's start by implementing the Check interface but without any steps yet:

package configchecks

var _ checks.Check = (*check)(nil)

type check struct{}

func New() checks.Check {
	return &check{}
}

func (c *check) ID() string {
	return "config"
}

func (c *check) Name() string {
	return "config setting"
}

func (c *check) Items(ctx context.Context) ([]any, error) {
	return nil, nil
}

func (c *check) Item(ctx context.Context, id string) (any, error) {
	return nil, nil
}

func (c *check) Init(ctx context.Context) error {
	return nil
}

func (c *check) Steps() []checks.Step {
	return []checks.Step{}
}

2. Define Dependencies and Register the Check

In order to be able to implement a check, it will likely need some dependencies in the form of wire services. This is the internal dependency injection system used in Grafana and it allows you to access the services you need.

For our example, we will need access to the grafana settings, which are exposed by wire as *setting.Cfg (in this case is a pointer to a struct, not an interface but the idea is the same). So let's add it to our check as a parameter for our New function:

type check struct {
	cfg *setting.Cfg
}

func New(cfg *setting.Cfg) checks.Check {
	return &check{
		cfg: cfg,
	}
}

Now, to register our check in the checkregistry package, we need to add it to the ProvideService function. First, we need to verify that the services we need are available in the ProvideService function, and if not, add them. Then, we need to add our check to the Checks slice.

func ProvideService(..., cfg *setting.Cfg,
) *Service {
    return &Service{
        ...
        cfg: cfg,
    }
}

func (s *Service) Checks() []checks.Check {
	return []checks.Check{
        ...
        configchecks.New(s.cfg),
    }
}

3. Complete the Check Implementation

Now that we have our check registered, we can implement the rest of the check logic.

3.1. Implement the Items and Item methods

The Items method is used to return a list of items that the check will be run on (e.g. all data sources, all plugins, etc). The Item method is used to return a single item by its ID.

These functions can return any type, we will convert them to the expected type in the step Run method.

In our case, we will implement the Items method to return a list of config sections that we want to check. The Item method will return a single config section by its name.

func (c *check) Items(ctx context.Context) ([]any, error) {
	return []any{"security.secret_key"}, nil
}

func (c *check) Item(ctx context.Context, id string) (any, error) {
	return id, nil
}

Check other checks for examples of how to implement these methods in more interesting ways.

3.2. Implement the Init method

The Init method is used to initialize the check. It is called when the check is first created. It should be used to gather any information that is needed to run the check and for the steps to have some shared context.

In our case, we don't need to do anything special so we can just return nil.

func (c *check) Init(ctx context.Context) error {
	return nil
}

One more interesting example is the plugincheck, where we gather all the plugin information from GCOM and store it in the check struct.

4. Implement Steps

Like the Check interface, each Step needs to return some information (metadata) about the step, which will be used to populate the UI, and the logic to Run the step.

In our example, we will implement a step that will check if the security.secret_key is set correctly. In case it's not correct, we recommend the user to follow the documentation.

Check security_config_step.go for the full implementation.

Best Practices

  1. Error Handling: In general, avoid returning errors for known issues, these will mark the check report as failed and the UI will render an error page. Only unexpected errors should be returned.

  2. Type Safety: Use type assertions to ensure you're working with the correct type of item.

  3. Severity Levels: Use appropriate severity levels:

    • CheckReportFailureSeverityHigh: For critical issues that need immediate attention
    • CheckReportFailureSeverityLow: For non-critical issues that can be addressed later
  4. Resolution Links: Provide helpful links in the CheckErrorLink slice to help users resolve issues.

  5. Logging: Use the provided logger to log important information and errors.

Testing

Create tests for your check and its steps to ensure they work as expected. Test both successful and failure scenarios.