Install Now

grafana/grafana

grafana Documentation

Last updated on Jan 16, 2026 (Commit: 3f258c8)

Overview

Relevant Files
  • README.md
  • pkg/README.md
  • packages/README.md
  • contribute/README.md
  • contribute/backend/README.md
  • contribute/architecture/README.md

Grafana is an open-source platform for monitoring and observability. It enables users to query, visualize, alert on, and understand metrics from any data source. The codebase is organized into backend (Go) and frontend (TypeScript/React) components, with a modular architecture designed for extensibility through plugins.

What is Grafana?

Grafana provides a comprehensive observability platform with several core capabilities:

  • Visualizations: Fast, flexible client-side graphs with numerous panel types and customization options
  • Dynamic Dashboards: Reusable dashboards with template variables for dynamic filtering
  • Data Exploration: Ad-hoc queries with split-view comparisons across time ranges and data sources
  • Alerting: Visual alert rule definition with notifications to Slack, PagerDuty, OpsGenie, and other systems
  • Multi-Source Support: Mix different data sources in the same visualization with per-query source selection

Repository Structure

The Grafana repository follows a clear separation between backend and frontend:

grafana/
├── pkg/                    # Go backend code
│   ├── api/               # HTTP API endpoints
│   ├── services/          # Core services (auth, storage, plugins, etc.)
│   ├── models/            # Domain models and data structures
│   ├── storage/           # Unified storage layer for resources
│   ├── plugins/           # Plugin system and management
│   └── ...
├── public/                # Frontend assets and code
│   ├── app/              # React application code
│   │   ├── core/         # Core services and utilities
│   │   ├── features/     # Feature modules (dashboards, alerting, etc.)
│   │   └── plugins/      # Plugin integration
│   └── build/            # Compiled frontend assets
├── packages/              # Reusable frontend packages
│   ├── grafana-ui/       # UI component library
│   ├── grafana-data/     # Data utilities and types
│   ├── grafana-runtime/  # Runtime utilities
│   └── ...
└── contribute/            # Contribution guidelines
    ├── backend/          # Backend development guides
    └── architecture/     # Architecture documentation

Backend Architecture

The backend is written in Go and organized by feature domains. Key architectural patterns include:

Service-Oriented Design: Services encapsulate business logic and are registered with a service registry. Each service manages its own lifecycle (initialization, running, shutdown) through the dskit module system.

Unified Storage: A Kubernetes-inspired resource API layer (/apis/...) provides declarative, eventually-consistent resource management. This complements the traditional Legacy API (/api/...) and uses a unified storage backend that can persist to SQL databases (PostgreSQL, MySQL, SQLite).

Plugin System: Grafana supports backend plugins through a plugin framework. Plugins can implement data source queries, alerting rules, and custom resource handlers.

Package Hierarchy: Packages are organized by feature with clear ownership. Domain types and interfaces live in root packages, while implementation details (HTTP handlers, database queries) are in subpackages.

Frontend Architecture

The frontend is a React application built with TypeScript, organized into modular features:

Core Services: Global services like BackendSrv (HTTP communication), LocationService (routing), and KeybindingSrv (keyboard shortcuts) are provided through React Context.

Feature Modules: Features like dashboards, alerting, and data exploration are self-contained modules with their own components, services, and state management.

Reusable Packages: The packages/ directory contains shared libraries published to npm:

  • @grafana/ui - UI component library
  • @grafana/data - Data utilities and types
  • @grafana/runtime - Runtime utilities for plugins
  • @grafana/schema - Type definitions for Grafana resources

Plugin Integration: Plugins are loaded dynamically and can extend Grafana's functionality through extension points and custom panels.

Key Technologies

Backend: Go, PostgreSQL/MySQL/SQLite, gRPC, REST APIs

Frontend: React, TypeScript, Redux (state management), Webpack (bundling)

Build System: Make, Dagger (containerized builds), Lerna (package management)

Testing: Jest (frontend), Go testing (backend), Playwright (E2E)

Development Workflow

The repository uses a monorepo structure with:

  • Lerna for managing frontend packages and versioning
  • Go workspaces for managing backend modules
  • Makefile for common build and development tasks
  • Docker Compose for local development environments with databases and data sources

Contributors should start with the Developer guide and relevant style guides for backend or frontend work.

Architecture & System Design

Relevant Files
  • contribute/architecture/README.md
  • contribute/backend/README.md
  • contribute/backend/package-hierarchy.md
  • contribute/backend/services.md
  • pkg/server/wire.go
  • pkg/server/server.go
  • contribute/architecture/k8s-inspired-backend-arch.md

Grafana's architecture combines a modular backend service layer with a Kubernetes-inspired resource API model, enabling both traditional REST endpoints and declarative resource management.

Backend Service Architecture

Grafana uses Wire, a code generation tool for dependency injection, to wire services together. Each service encapsulates related business logic and exposes it through well-defined interfaces.

Service Structure:

Services follow a consistent pattern with three key components:

  • Root package (pkg/services/servicename/): Contains interfaces, domain types, and errors that other services depend on
  • Implementation package (pkg/services/servicename/serviceimpl/): Houses the concrete service implementation and storage logic
  • Test doubles (pkg/services/servicename/servicenametest/): Provides fakes and mocks for testing

Each service has a ProvideService factory method that Wire uses to resolve dependencies and initialize the service. Services can implement optional interfaces like registry.BackgroundService to run background tasks or registry.CanBeDisabled to support conditional initialization.

func ProvideService(cfg *setting.Cfg, db db.DB) (*Service, error) {
    s := &Service{cfg: cfg, db: db}
    if err := s.init(); err != nil {
        return nil, err
    }
    return s, nil
}

Package Hierarchy

Grafana organizes packages by feature rather than by layer. This approach reduces circular dependencies and improves maintainability:

  • Domain types and interfaces stay in root packages to minimize coupling
  • Sub-packages depend on roots, not vice versa, preventing circular imports
  • Storage is abstracted behind interfaces, allowing multiple implementations
  • Migrations and API endpoints remain centralized in pkg/services/sqlstore/migrations and pkg/api/ respectively

Dual API Model: Legacy and Resource APIs

Grafana is transitioning from traditional REST endpoints (/api/...) to Kubernetes-inspired Resource APIs (/apis/...). Both coexist during migration.

Legacy APIs (/api/...):

  • Variable URL structures and response formats
  • Implicit organization context (via session or API key)
  • Feature-specific implementations

Resource APIs (/apis/...):

  • Kubernetes-style paths: /apis/group/version/namespaces/namespace/resource/name
  • Explicit versioning (v1alpha1, v1beta1, v1) in the URL
  • Standardized schemas with OpenAPI specs
  • Unified storage backend

Unified Storage and Resource Persistence

The Unified Storage layer (pkg/storage/unified/...) decouples Resource API handlers from storage backends. It implements Kubernetes' storage.Interface, translating Kubernetes operations to Grafana's resource client.

Key features:

  • Resource versioning: Each resource has a resourceVersion that changes on modification, enabling optimistic concurrency control
  • Watch support: Efficient change detection via resource_history table, even on standard SQL databases
  • Multiple backends: Supports SQL databases (PostgreSQL, MySQL, SQLite), file storage, and remote gRPC storage

API Implementation Approaches

Registry Approach (pkg/registry/apis/...):

  • Go-based API definitions using register.go files
  • Direct implementation of REST handlers
  • Used for legacy fallbacks and infrastructure APIs

Apps Approach (apps/...):

  • Modern, modular implementation using CUE schemas
  • Self-contained apps with versioning and dependencies
  • Generates Go types and supports controllers/reconcilers
  • Preferred pattern for new resources
Loading diagram...

Server Initialization and Lifecycle

The Server struct manages Grafana's lifecycle from startup to shutdown. Wire generates wire_gen.go which instantiates all services with their dependencies resolved. The server then:

  1. Initializes all services via Wire-generated code
  2. Registers background services with the registry
  3. Starts HTTP server and background service runners
  4. Manages graceful shutdown

Services can be disabled conditionally via the IsDisabled() method, and background services run concurrently during server operation.

Backend Services & APIs

Relevant Files
  • pkg/api/api.go
  • pkg/api/http_server.go
  • pkg/services/dashboards
  • pkg/services/datasources
  • pkg/services/ngalert
  • pkg/services/auth
  • pkg/services/query
  • pkg/services/apiserver

Architecture Overview

Grafana's backend is organized around a service-oriented architecture where the HTTP API layer (pkg/api) routes requests to specialized services. The main entry point is the HTTPServer in http_server.go, which registers all API routes and manages the lifecycle of backend services.

Loading diagram...

Core API Layer

The API layer in pkg/api/api.go defines all HTTP endpoints and middleware chains. Routes are registered using a fluent builder pattern through the RouteRegister interface. Key route groups include:

  • Authentication: Login, logout, OAuth flows
  • User Management: User profiles, organizations, teams
  • Dashboards: CRUD operations, permissions, snapshots
  • Datasources: Configuration, validation, proxy
  • Alerting: Alert rules, notification policies, silences
  • Search: Dashboard and user search with sorting

Middleware is applied at multiple levels: global (CSRF, logging), group-level (authentication), and route-level (authorization, quotas).

Service Architecture

Each major feature area has a dedicated service package under pkg/services/. Services follow a consistent pattern:

Dashboards Service (pkg/services/dashboards) handles dashboard persistence, versioning, and access control. It provides methods for creating, updating, deleting, and querying dashboards with full audit trails.

Datasources Service (pkg/services/datasources) manages datasource configurations, caching, and validation. It includes a guardian system for access control and supports dynamic datasource discovery.

Query Service (pkg/services/query) orchestrates query execution across multiple datasources. It parses requests, routes queries to appropriate datasources, handles expressions, and manages concurrent query execution with configurable limits.

Alerting Service (pkg/services/ngalert) implements unified alerting with rule evaluation, notification routing, and state management. It supports multiple notification backends and integrates with external alertmanagers.

Auth Services (pkg/services/auth, pkg/services/authn) handle authentication and identity management, supporting multiple auth methods (basic, OAuth, LDAP, SAML).

Query Execution Flow

The query service processes requests through several stages:

  1. Parsing: Requests are parsed into queries grouped by datasource UID
  2. Validation: Datasource access is validated using the guardian system
  3. Routing: Queries are routed to appropriate handlers:
    • Single datasource queries execute directly
    • Multi-datasource queries execute concurrently with configurable limits
    • Expression queries are handled by the expression service
  4. Execution: Queries are sent to datasource plugins via the plugin client
  5. Response Aggregation: Results are combined and returned to the caller

API Server Integration

The newer pkg/services/apiserver provides Kubernetes-style API server capabilities for modern resource management. It supports dual-write patterns for gradual migration from legacy APIs and includes built-in authorization, audit logging, and resource versioning.

Key Design Patterns

Dependency Injection: Services are wired together using Wire, with all dependencies explicitly declared in provider functions.

Interface-Based Design: Services expose interfaces for testability and loose coupling.

Middleware Chains: HTTP middleware is composed using functional wrappers for cross-cutting concerns.

Access Control: Fine-grained permissions are enforced through the AccessControl service with role-based and resource-based policies.

Frontend Architecture & State Management

Relevant Files
  • public/app/core/store.ts
  • public/app/store/configureStore.ts
  • public/app/core/reducers/root.ts
  • public/app/core/context/GrafanaContext.ts
  • public/app/store/store.ts
  • public/app/types/store.ts
  • contribute/architecture/frontend-data-requests.md

Grafana uses a layered state management architecture combining Redux for global application state, React Context for service injection, and RTK Query for server state caching. This design enables predictable state updates, efficient data fetching, and clean separation of concerns.

Redux Store Architecture

The Redux store is configured in configureStore.ts using Redux Toolkit. The root reducer combines domain-specific reducers from features like dashboards, alerting, datasources, and variables. The store is initialized with middleware including thunks, RTK Query APIs, and custom listener middleware for side effects.

const store = reduxConfigureStore({
  reducer: createRootReducer(),
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({ thunk: true }).concat(
      listenerMiddleware.middleware,
      alertingApi.middleware,
      publicDashboardApi.middleware,
      // ... other API middlewares
    ),
  devTools: process.env.NODE_ENV !== 'production',
});

The root reducer in root.ts aggregates reducers from all features. New reducers can be added dynamically via addReducer() before store initialization. This modular approach keeps feature state isolated while maintaining a single source of truth.

GrafanaContext for Service Injection

GrafanaContext provides access to core services without prop drilling. It includes BackendSrv for HTTP requests, LocationService for routing, AppChromeService for UI chrome management, and KeybindingSrv for keyboard shortcuts. Components access these via the useGrafana() hook.

export interface GrafanaContextType {
  backend: BackendSrv;
  location: LocationService;
  config: GrafanaBootConfig;
  chrome: AppChromeService;
  keybindings: KeybindingSrv;
  newAssetsChecker: NewFrontendAssetsChecker;
}

Data Fetching Patterns

RTK Query is the modern approach for server state. It provides automatic caching, request deduplication, and background refetching. APIs are defined using createApi() with a custom base query that wraps BackendSrv.fetch().

export const alertingApi = createApi({
  reducerPath: 'alertingApi',
  baseQuery: backendSrvBaseQuery(),
  endpoints: (builder) => ({
    getAlertRules: builder.query({...}),
  }),
});

BackendSrv handles all HTTP requests with built-in request queuing and cancellation. It uses RxJS Observables for reactive request handling and supports request deduplication via requestId.

Thunks are used for legacy features. They dispatch actions to update Redux state after async operations complete.

Request Management

Grafana limits parallel data source requests to 5 (or 1000 with HTTP/2) to prevent browser connection limits from blocking interactions. Requests can be canceled by requestId or via RxJS subscription cleanup. The request queue ensures API requests always have a free slot.

Component State Patterns

Local component state uses React hooks (useState, useReducer). Complex query editors use local reducer contexts (e.g., Elasticsearch, Graphite) to manage editor state independently. Global state is accessed via useSelector() and useDispatch() from Redux, or RTK Query hooks like useGetAlertRulesQuery().

const { data, isLoading, error } = useGetAlertRulesQuery(params);

Typed Hooks

public/app/types/store.ts exports typed versions of Redux hooks: useDispatch(), useSelector(), and createAsyncThunk(). These provide full TypeScript support for store state and dispatch actions, reducing runtime errors.

Datasources & Plugin System

Relevant Files
  • pkg/tsdb - Built-in datasource implementations (Prometheus, Loki, CloudWatch, etc.)
  • pkg/plugins - Core plugin system and lifecycle management
  • pkg/services/datasources - Datasource service, storage, and caching
  • pkg/services/pluginsintegration - Plugin integration layer with Grafana services
  • public/app/plugins/datasource - Frontend datasource plugin implementations
  • packages/grafana-schema/src - Plugin and datasource schema definitions

Overview

Grafana's datasource and plugin system provides a modular architecture for extending functionality. Datasources enable querying external data systems, while plugins extend Grafana with new visualizations, data sources, and applications. Both systems share a common plugin infrastructure with discovery, loading, validation, and lifecycle management.

Datasource Architecture

Datasources are specialized plugins that connect Grafana to external data systems. Each datasource has two components:

Backend Implementation - Handles query execution and data retrieval. Located in pkg/tsdb/, built-in datasources like Prometheus, Loki, and CloudWatch implement the QueryDataHandler interface to process queries and return data frames.

Frontend Implementation - Provides UI components for query building and configuration. Located in public/app/plugins/datasource/, these implement the DataSourceApi interface to handle query requests and return observable responses.

Datasources are registered with the system through the datasource service (pkg/services/datasources/service/datasource.go), which manages CRUD operations, caching, and access control. The service stores datasource configurations in the database and handles secret encryption for sensitive credentials.

Query Execution Flow

When a dashboard executes a query, the flow follows these steps:

  1. Request Parsing - The query service (pkg/services/query/query.go) receives the request and parses it into queries grouped by datasource UID.

  2. Routing - Single datasource queries are routed directly to the plugin. Multi-datasource queries are executed concurrently. Expression queries are handled by the expression service.

  3. Plugin Invocation - The plugin client calls the datasource's QueryData method via gRPC (for external plugins) or directly (for core plugins). The request includes the plugin context with authentication and datasource settings.

  4. Response Aggregation - Results are collected and returned as a QueryDataResponse containing data frames keyed by RefID.

Frontend Request
    ↓
Query Service (parseMetricRequest)
    ↓
Route by datasource count
    ├→ Single DS: handleQuerySingleDatasource
    ├→ Multiple DS: executeConcurrentQueries
    └→ Expressions: handleExpressions
    ↓
Plugin Client (QueryData)
    ↓
Backend Plugin (QueryDataHandler)
    ↓
Data Frames Response

Plugin System Architecture

Grafana supports four plugin types:

Datasource - Connects to external data systems. Implements query execution and health checks. Examples: Prometheus, PostgreSQL, CloudWatch.

Panel - Visualizes data on dashboards. Implements rendering logic and configuration UI. Examples: Time Series, Stat, Geomap.

App - Bundles datasources, panels, and custom pages into a cohesive experience. Can add navigation and custom UI routes.

Renderer - Handles image rendering for dashboards and alerts. Typically runs as an external process.

Plugin Lifecycle

The plugin loader (pkg/plugins/manager/loader/loader.go) manages plugins through five stages:

Loading diagram...

Discovery - Scans plugin directories and identifies plugin bundles. Reads plugin.json manifests.

Bootstrap - Constructs plugin objects, resolves dependencies, and prepares assets. Sets up module URLs and base paths for frontend loading.

Validation - Verifies plugin signatures and checks for security issues. Unsigned plugins may be blocked based on configuration.

Initialization - Starts backend clients (gRPC for external plugins), registers action sets, and reports metrics.

Termination - Gracefully stops plugins and cleans up resources.

Plugin Registration and Discovery

Plugins are discovered from configured directories and registered with the plugin registry. The registry maintains metadata about all loaded plugins, including:

  • Plugin ID, type, and version
  • Signature status and signing organization
  • Module URL and loading strategy
  • Configuration pages and extensions
  • Backend capabilities (QueryData, CheckHealth, CallResource, etc.)

Frontend plugins are loaded dynamically using SystemJS. The loading strategy determines whether plugins are loaded eagerly or lazily. Core plugins are bundled with Grafana, while external plugins are loaded from the filesystem or CDN.

Backend Plugin Interface

Backend plugins implement handlers for different operations:

Plugin Interface
├── QueryDataHandler - Execute queries and return data
├── CheckHealthHandler - Verify datasource connectivity
├── CallResourceHandler - Handle custom API endpoints
├── StreamHandler - Support streaming data
├── AdmissionHandler - Validate resource changes
└── ConversionHandler - Convert between API versions

External plugins communicate with Grafana via gRPC using the plugin SDK. Core plugins are compiled directly into Grafana and called in-process.

Datasource Configuration and Secrets

Datasource configurations are stored in the database with the following structure:

  • Name - User-friendly identifier
  • Type - Plugin ID (e.g., prometheus, loki)
  • URL - Connection endpoint
  • JSONData - Plugin-specific configuration (stored as JSON)
  • SecureJsonData - Encrypted sensitive data (API keys, passwords)

The secrets service encrypts sensitive fields before storage and decrypts them on retrieval. Access control policies determine which users can query or modify datasources.

Runtime Datasources

Grafana supports registering datasources at runtime through the registerRuntimeDataSource API. This enables dynamic datasource creation without database persistence, useful for:

  • Temporary datasources created by plugins
  • Datasources derived from other datasources
  • Expression datasources for query transformations

Runtime datasources are stored in memory and are not persisted across restarts.

Plugin Extensions

Plugins can expose and consume extensions through the plugin extension system. This allows:

  • Panels to expose custom components for use in other plugins
  • Datasources to provide custom query editors
  • Apps to add navigation items and custom pages

Extensions are registered during plugin initialization and discovered by other plugins at runtime.

Frontend Packages & UI Components

Relevant Files
  • packages/grafana-ui
  • packages/grafana-data
  • packages/grafana-runtime
  • packages/grafana-alerting
  • packages/grafana-prometheus
  • packages/grafana-api-clients

Grafana's frontend is built on a modular package architecture that separates concerns into reusable, independently versioned libraries. These packages form the foundation for both Grafana core and plugin development.

Core Packages Overview

@grafana/ui is the primary component library containing 100+ React components organized by category: forms (Input, Select, Combobox, Checkbox), buttons (Button, IconButton, ToolbarButton), visualizations (Gauge, BarGauge, BigValue, Sparkline), modals and overlays (Modal, Drawer, Tooltip, Popover), tables (Table, InteractiveTable), and layout utilities (Box, Stack, Grid). Components use Emotion for styling and follow the Saga Design System. All components are documented in Storybook with interactive examples.

@grafana/data provides core data types and utilities: DataFrames (columnar data structures), field types, transformations, value formatters, and query result handling. It includes utilities for time series processing, geospatial data, and field matching. This package has no React dependencies, making it suitable for backend-agnostic data processing.

@grafana/runtime bridges plugins and Grafana core, exporting services (BackendSrv, LocationService, KeybindingSrv), components (PanelRenderer, PanelDataErrorView), and utilities for query execution. It provides the plugin API surface and handles communication with the backend.

@grafana/alerting (Alpha) contains alerting-specific components and utilities: notification policies, label matchers, alert rules UI, and RTK Query API clients for the alerting system. It's designed for building alerting integrations and custom alerting solutions.

@grafana/prometheus exports Prometheus datasource components: PromQueryEditorByApp, MetricsBrowser, PromCheatSheet, and configuration editors. It includes query builders, exemplar fields, and variable query editors for Prometheus-specific functionality.

@grafana/api-clients (Beta) provides auto-generated RTK Query clients for Grafana APIs, enabling type-safe frontend-backend communication. Clients are generated from OpenAPI specifications.

Package Dependencies

@grafana/ui
  ├── @grafana/data
  ├── @grafana/i18n
  ├── @grafana/schema
  └── React 18+

@grafana/runtime
  ├── @grafana/data
  ├── @grafana/ui
  ├── @grafana/schema
  └── React 18+

@grafana/alerting
  ├── @grafana/data
  ├── @grafana/runtime
  ├── @grafana/ui
  └── @grafana/api-clients

Export Patterns

All packages use conditional exports in package.json to support multiple entry points: the main export (.), unstable features (./unstable), and internal APIs (./internal). The internal export is stripped during npm publishing, preventing external packages from accessing private code while allowing Grafana core to use it.

Development Workflow

Packages are built with TypeScript and Rollup, generating CommonJS, ESM, and type declaration outputs. Storybook serves as the interactive documentation and testing environment for UI components. Each package maintains its own tsconfig.json and build configuration, enabling independent development and versioning.

Apps & Feature Modules

Relevant Files
  • apps/ - Backend apps using Grafana App SDK
  • apps/dashboard/ - Dashboard management app
  • apps/alerting/ - Alerting subsystem (rules, notifications, historian)
  • apps/folder/ - Folder management app
  • apps/iam/ - Identity and access management app
  • apps/provisioning/ - Resource provisioning app
  • public/app/features/ - Frontend feature modules
  • pkg/registry/apps/ - App registration and initialization

Grafana is organized into modular apps and feature modules that handle distinct responsibilities. This architecture enables independent development, versioning, and deployment of core functionality.

Backend Apps (Grafana App SDK)

Backend apps are built using the Grafana App SDK, a Kubernetes-inspired framework that provides schema-first development with CUE definitions. Each app is self-contained with its own versioning, APIs, and dependencies.

Key Apps:

  • Dashboard App (apps/dashboard/) - Manages dashboard resources with multiple API versions (v0alpha1, v1beta1, v2alpha1, v2beta1). Handles dashboard migrations, schema versioning, and layout conversions.

  • Alerting Apps (apps/alerting/) - Comprises three sub-apps:

    • rules/ - Alert rule definitions and management
    • notifications/ - Notification routing and receiver configuration
    • historian/ - Alert state history tracking
  • Folder App (apps/folder/) - Manages folder hierarchies and organization.

  • IAM App (apps/iam/) - Identity and access management, roles, and permissions.

  • Provisioning App (apps/provisioning/) - Handles resource provisioning from external sources (Git, APIs).

  • Other Apps - Playlist, Plugins, Preferences, Quotas, Annotations, Correlations, Advisor, and more.

App Structure

Each app follows a consistent pattern:

apps/myapp/
├── kinds/              # CUE schema definitions
│   ├── manifest.cue    # App manifest (versions, kinds, permissions)
│   └── myapp.cue       # Kind definitions
├── pkg/
│   ├── apis/           # Generated Go/TypeScript types
│   └── app/            # App implementation (New() entry point)
├── Makefile            # Code generation via App SDK
└── go.mod

Code Generation: Run make generate to create Go and TypeScript types from CUE definitions using the Grafana App SDK.

Frontend Feature Modules

Frontend features are organized in public/app/features/ with domain-specific modules:

Core Features: dashboard, dashboard-scene, alerting, explore, datasources, plugins, connections

Management: admin, users, teams, org, profile, serviceaccounts

Data & Visualization: panel, visualization, transformers, expressions, annotations, variables, templating

Advanced: provisioning, correlations, library-panels, scopes, search, browse-dashboards

Each feature module contains components, state management (Redux/RTK Query), hooks, and utilities organized by responsibility.

App Registration

Apps are registered in pkg/registry/apps/ with installers that:

  1. Load the app manifest (schema definitions)
  2. Configure app-specific settings
  3. Register with the Grafana API server
  4. Enable feature-gated functionality

The ProvideAppInstallers() function in apps.go composes all active app installers based on feature flags and configuration.

Integration Pattern

Loading diagram...

Apps expose REST APIs that frontend features consume via RTK Query or direct HTTP calls. This separation enables independent iteration on backend schemas and frontend UX.

Infrastructure & Utilities

Relevant Files
  • pkg/infra - Core infrastructure services
  • pkg/util - Utility functions and helpers
  • pkg/middleware - HTTP middleware and request handling
  • pkg/setting - Configuration management
  • pkg/storage - Data storage backends
  • pkg/modules - Module lifecycle management

Grafana's infrastructure layer provides foundational services for logging, caching, database access, tracing, and HTTP handling. These components enable reliable operation at scale.

Core Infrastructure Services

Database Access (pkg/infra/db) provides a unified interface for database operations across SQLite, MySQL, and PostgreSQL. The DB interface abstracts transaction management, dialect handling, and query execution through xorm.

Remote Caching (pkg/infra/remotecache) supports Redis, Memcached, and database-backed caching with optional encryption. Cache items are serialized using gob encoding, with configurable expiration and prefix support.

Logging (pkg/infra/log) uses structured logging with slog and go-kit/log. Loggers are organized hierarchically by name, support multiple handlers (file, syslog, console), and can be reloaded at runtime without restart.

Tracing (pkg/infra/tracing) integrates OpenTelemetry with support for Jaeger and OTLP exporters. Traces include service metadata, span attributes, and propagation across service boundaries for distributed tracing.

HTTP Client (pkg/infra/httpclient) provides a configurable HTTP client with middleware for authentication, metrics, response limits, and redirect handling. Supports datasource proxying with security validation.

Utilities and Helpers

Encoding & Encryption (pkg/util) includes password hashing (PBKDF2), AES encryption (CFB and GCM modes), base64 encoding, and random string generation for secure operations.

Validation (pkg/util/validation) provides email validation and other common checks. Input validation is performed at multiple layers for security.

Scheduling (pkg/util/scheduler) implements a worker pool pattern with configurable backoff and retry logic. Workers dequeue tasks and process them with exponential backoff on failure.

Debouncing (pkg/util/debouncer) groups rapid events by key and processes them after configurable wait periods. Useful for expensive operations triggered by frequent events.

Ring Data Structure (pkg/util/ring) provides a thread-safe circular buffer for efficient event queuing and adaptive channel sizing.

Middleware and Request Handling

HTTP Middleware (pkg/middleware) handles authentication, CSRF protection, security headers, compression, quota enforcement, and request tracing. Middleware is applied in a specific order to ensure proper request processing.

Security Headers include HSTS, X-Content-Type-Options, CSP, and X-Frame-Options. Headers are customizable per deployment and can be overridden for specific URLs like embedded dashboards.

Request Metadata captures trace IDs, user context, and organization information for logging and debugging. Contextual log providers allow injecting request-specific data into all log messages.

Configuration Management

Settings (pkg/setting) loads configuration from defaults.ini, environment variables, and command-line arguments. The Cfg struct centralizes all configuration with support for multiple database types, authentication methods, and feature flags.

Configuration is hierarchical: defaults are overridden by environment variables, which are overridden by command-line arguments. This allows flexible deployment across development, staging, and production environments.

Storage Backends

Unified Storage (pkg/storage/unified) provides a modern storage abstraction supporting Kubernetes-style resources. It can use SQL databases or gRPC-based remote storage, with automatic migrations from legacy tables.

Legacy SQL Storage (pkg/storage/legacysql) maintains compatibility with existing SQL-based storage for dashboards, folders, and other resources during migration periods.

Secret Storage (pkg/storage/secret) encrypts sensitive data at rest with configurable encryption backends and key rotation support.

Module System

Module Manager (pkg/modules) orchestrates service lifecycle using dskit's service framework. Modules are registered with dependencies, started in order, and stopped gracefully on shutdown. The system supports both visible and invisible modules for internal services.

Loading diagram...

Testing & Quality Assurance

Relevant Files
  • pkg/tests - Integration test infrastructure
  • e2e - Cypress-based end-to-end tests
  • e2e-playwright - Playwright-based end-to-end tests
  • packages/grafana-test-utils - Frontend testing utilities
  • contribute/backend/recommended-practices.md - Backend testing guidelines
  • contribute/style-guides/testing.md - Frontend testing guidelines
  • contribute/style-guides/e2e-playwright.md - E2E testing framework

Grafana maintains a comprehensive testing strategy across backend, frontend, and end-to-end layers. The test suite ensures code quality, prevents regressions, and validates user workflows.

Backend Testing

Backend tests use Go's standard testing library with testify for assertions. Tests are organized into unit and integration categories.

Unit Tests: Run with make test-go-unit. Tests use the -short flag and timeout after 30 minutes. The test suite is sharded across multiple CI jobs for parallel execution.

Integration Tests: Run with make test-go-integration. These tests validate database interactions and external service integrations. Database-specific variants exist:

  • make test-go-integration-postgres - PostgreSQL backend
  • make test-go-integration-mysql - MySQL backend
  • make test-go-integration-redis - Redis cache
  • make test-go-integration-memcached - Memcached cache

The pkg/tests directory provides test infrastructure including the testsuite package for package-level setup and teardown, and testinfra utilities for database and service initialization.

Frontend Testing

Frontend tests use Jest with React Testing Library. Run all tests with make test-js or yarn test.

Best Practices:

  • Use *ByRole queries to encourage accessibility-first testing
  • Use user-event library instead of fireEvent for realistic user interactions
  • Call userEvent.setup() before tests to ensure proper async handling
  • Mock getBackendSrv() and window object using Jest spies

The packages/grafana-test-utils package provides shared testing utilities, fixtures, and mock handlers for consistent test setup across the codebase.

End-to-End Testing

Grafana uses Playwright for E2E tests, organized by feature area in e2e-playwright/. The framework follows the Page Object pattern with abstractions for Selectors, Pages, Components, and Flows.

Running Tests:

yarn e2e:playwright                    # Run all tests
yarn e2e:playwright --ui               # Open interactive UI
yarn e2e:playwright --grep <testname>  # Run specific test
yarn e2e:playwright --project <name>   # Run entire project

Tests use data-testid attributes for element selection rather than CSS classes, ensuring stability across style changes. Tests run with 2 retries on CI and capture screenshots and traces on failure.

Quality Assurance

Code quality is enforced through linting and static analysis. Run make lint-go for backend linting with GolangCI-Lint. Frontend linting is integrated into the build process.

CI/CD pipelines run all test suites on pull requests. Backend tests are sharded across 16 parallel jobs for efficiency. Integration tests run against multiple database backends to ensure compatibility.

Loading diagram...

Development Workflow & Build System

Relevant Files
  • Makefile - Main build orchestration
  • build.go - Build entry point
  • pkg/build - Build system implementation
  • contribute/developer-guide.md - Developer setup guide
  • contribute/backend/manage-go-module.md - Go module management
  • devenv - Development environment setup
  • package.json - Frontend build scripts
  • go.mod - Go dependencies

Grafana uses a dual-stack build system supporting both Go (backend) and Node.js (frontend). The build process is orchestrated through a comprehensive Makefile that coordinates code generation, compilation, testing, and packaging.

Build Architecture

Loading diagram...

Core Build Commands

The Makefile provides high-level targets for common development tasks:

Dependencies:

  • make deps-go - Install backend dependencies
  • make deps-js - Install frontend dependencies (via Yarn)
  • make node_modules - Install Node modules with immutable lock file

Building:

  • make build - Build both backend and frontend
  • make build-backend - Build Go binaries only
  • make build-js - Build frontend assets only
  • make build-server - Build Grafana server binary
  • make build-cli - Build Grafana CLI tool

Development:

  • make run - Build backend and watch for changes (uses Air)
  • make run-frontend - Watch and rebuild frontend assets
  • make run-go - Run backend server immediately with profiling

Code Generation

Grafana uses multiple code generation tools:

  • Wire - Dependency injection graph generation (make gen-go)
  • CUE - Configuration and schema generation (make gen-cue)
  • Swagger - API specification generation (make swagger-gen)
  • Feature toggles - Feature flag code generation (make gen-feature-toggles)
  • Protobuf - Protocol buffer compilation (make protobuf)

Testing

Loading diagram...

Frontend: yarn test runs Jest with watch mode. Use yarn test:coverage for coverage reports.

Backend: make test-go-unit runs unit tests. Integration tests require Docker: make test-go-integration-postgres or make test-go-integration-mysql.

E2E: yarn e2e:playwright runs Playwright tests. Install browsers first: yarn playwright install chromium.

Development Environment Setup

The devenv directory provides Docker Compose configurations for local development:

make devenv sources=postgres,prometheus,loki

Available sources include databases (PostgreSQL, MySQL), monitoring tools (Prometheus, Loki), and other services. Run ./devenv/setup.sh to provision default dashboards and data sources.

Go Module Management

Grafana uses Go workspaces for managing multiple modules. When creating new modules:

  1. Initialize the module in pkg/your/module
  2. Run make update-workspace to sync workspace files
  3. Add module to Dockerfile and .github/dependabot.yml
  4. Use replace directives temporarily until merged to main

Docker Builds

  • make build-docker-full - Build development Docker image
  • make build-docker-full-ubuntu - Build Ubuntu-based image

Both support environment variables for customizing Node and Go build modes.

Linting & Formatting

  • make lint-go - Run golangci-lint on backend
  • make gofmt - Format all Go files
  • make shellcheck - Check shell scripts
  • yarn lint - Lint TypeScript and SASS

Key Build Flags

Go builds support several flags via environment variables:

  • GO_BUILD_DEV=dev - Development mode
  • GO_BUILD_TAGS - Custom build tags
  • GO_RACE=1 - Enable race detector
  • GO_BUILD_CGO - Control CGO compilation

Frontend builds use NODE_ENV (production/dev) and support feature toggles through environment variables.