mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Previews: refactor (#47728)
* #44449: return standard thumb service even if auth setup fails * #44449: remove dashboardPreviewsScheduler feature flag * #44449: externalize dashboardPreviews config * #44449: disable previews by default * #44449: rename logger * #44449: dashboardPreviewsAdmin feature requires dev mode * #44449: retrigger CII
This commit is contained in:
parent
70a7b73839
commit
2e599643f6
@ -1176,3 +1176,22 @@ default_baselayer_config =
|
|||||||
|
|
||||||
# Enable or disable loading other base map layers
|
# Enable or disable loading other base map layers
|
||||||
enable_custom_baselayers = true
|
enable_custom_baselayers = true
|
||||||
|
|
||||||
|
#################################### Dashboard previews #####################################
|
||||||
|
|
||||||
|
[dashboard_previews.crawler]
|
||||||
|
# Number of dashboards rendered in parallel. Default is 6.
|
||||||
|
thread_count =
|
||||||
|
|
||||||
|
# Timeout passed down to the Image Renderer plugin. It is used in two separate places within a single rendering request:
|
||||||
|
# First during the initial navigation to the dashboard and then when waiting for all the panels to load. Default is 20s.
|
||||||
|
# This setting should be expressed as a duration. Examples: 10s (seconds), 1m (minutes).
|
||||||
|
rendering_timeout =
|
||||||
|
|
||||||
|
# Maximum duration of a single crawl. Default is 1h.
|
||||||
|
# This setting should be expressed as a duration. Examples: 10s (seconds), 1m (minutes).
|
||||||
|
max_crawl_duration =
|
||||||
|
|
||||||
|
# Minimum interval between two subsequent scheduler runs. Default is 12h.
|
||||||
|
# This setting should be expressed as a duration. Examples: 10s (seconds), 1m (minutes).
|
||||||
|
scheduler_interval =
|
||||||
|
@ -22,7 +22,6 @@ export interface FeatureToggles {
|
|||||||
serviceAccounts?: boolean;
|
serviceAccounts?: boolean;
|
||||||
database_metrics?: boolean;
|
database_metrics?: boolean;
|
||||||
dashboardPreviews?: boolean;
|
dashboardPreviews?: boolean;
|
||||||
dashboardPreviewsScheduler?: boolean;
|
|
||||||
dashboardPreviewsAdmin?: boolean;
|
dashboardPreviewsAdmin?: boolean;
|
||||||
['live-config']?: boolean;
|
['live-config']?: boolean;
|
||||||
['live-pipeline']?: boolean;
|
['live-pipeline']?: boolean;
|
||||||
|
@ -39,14 +39,10 @@ var (
|
|||||||
State: FeatureStateAlpha,
|
State: FeatureStateAlpha,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "dashboardPreviewsScheduler",
|
Name: "dashboardPreviewsAdmin",
|
||||||
Description: "Schedule automatic updates to dashboard previews",
|
Description: "Manage the dashboard previews crawler process from the UI",
|
||||||
State: FeatureStateAlpha,
|
State: FeatureStateAlpha,
|
||||||
},
|
RequiresDevMode: true,
|
||||||
{
|
|
||||||
Name: "dashboardPreviewsAdmin",
|
|
||||||
Description: "Manage the dashboard previews crawler process from the UI",
|
|
||||||
State: FeatureStateAlpha,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "live-config",
|
Name: "live-config",
|
||||||
|
@ -31,10 +31,6 @@ const (
|
|||||||
// Create and show thumbnails for dashboard search results
|
// Create and show thumbnails for dashboard search results
|
||||||
FlagDashboardPreviews = "dashboardPreviews"
|
FlagDashboardPreviews = "dashboardPreviews"
|
||||||
|
|
||||||
// FlagDashboardPreviewsScheduler
|
|
||||||
// Schedule automatic updates to dashboard previews
|
|
||||||
FlagDashboardPreviewsScheduler = "dashboardPreviewsScheduler"
|
|
||||||
|
|
||||||
// FlagDashboardPreviewsAdmin
|
// FlagDashboardPreviewsAdmin
|
||||||
// Manage the dashboard previews crawler process from the UI
|
// Manage the dashboard previews crawler process from the UI
|
||||||
FlagDashboardPreviewsAdmin = "dashboardPreviewsAdmin"
|
FlagDashboardPreviewsAdmin = "dashboardPreviewsAdmin"
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
@ -19,8 +20,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type simpleCrawler struct {
|
type simpleCrawler struct {
|
||||||
renderService rendering.Service
|
renderService rendering.Service
|
||||||
threadCount int
|
threadCount int
|
||||||
|
concurrentLimit int
|
||||||
|
renderingTimeout time.Duration
|
||||||
|
|
||||||
glive *live.GrafanaLive
|
glive *live.GrafanaLive
|
||||||
thumbnailRepo thumbnailRepo
|
thumbnailRepo thumbnailRepo
|
||||||
@ -36,13 +39,17 @@ type simpleCrawler struct {
|
|||||||
renderingSessionByOrgId map[int64]rendering.Session
|
renderingSessionByOrgId map[int64]rendering.Session
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSimpleCrawler(renderService rendering.Service, gl *live.GrafanaLive, repo thumbnailRepo) dashRenderer {
|
func newSimpleCrawler(renderService rendering.Service, gl *live.GrafanaLive, repo thumbnailRepo, cfg *setting.Cfg, settings setting.DashboardPreviewsSettings) dashRenderer {
|
||||||
|
threadCount := int(settings.CrawlThreadCount)
|
||||||
c := &simpleCrawler{
|
c := &simpleCrawler{
|
||||||
renderService: renderService,
|
// temporarily increases the concurrentLimit from the 'cfg.RendererConcurrentRequestLimit' to 'cfg.RendererConcurrentRequestLimit + crawlerThreadCount'
|
||||||
threadCount: 6,
|
concurrentLimit: cfg.RendererConcurrentRequestLimit + threadCount,
|
||||||
glive: gl,
|
renderingTimeout: settings.RenderingTimeout,
|
||||||
thumbnailRepo: repo,
|
renderService: renderService,
|
||||||
log: log.New("thumbnails_crawler"),
|
threadCount: threadCount,
|
||||||
|
glive: gl,
|
||||||
|
thumbnailRepo: repo,
|
||||||
|
log: log.New("thumbnails_crawler"),
|
||||||
status: crawlStatus{
|
status: crawlStatus{
|
||||||
State: initializing,
|
State: initializing,
|
||||||
Complete: 0,
|
Complete: 0,
|
||||||
@ -154,11 +161,11 @@ func (r *simpleCrawler) Run(ctx context.Context, auth CrawlerAuth, mode CrawlerM
|
|||||||
r.auth = auth
|
r.auth = auth
|
||||||
r.opts = rendering.Opts{
|
r.opts = rendering.Opts{
|
||||||
TimeoutOpts: rendering.TimeoutOpts{
|
TimeoutOpts: rendering.TimeoutOpts{
|
||||||
Timeout: 20 * time.Second,
|
Timeout: r.renderingTimeout,
|
||||||
RequestTimeoutMultiplier: 3,
|
RequestTimeoutMultiplier: 3,
|
||||||
},
|
},
|
||||||
Theme: theme,
|
Theme: theme,
|
||||||
ConcurrentLimit: 10,
|
ConcurrentLimit: r.concurrentLimit,
|
||||||
}
|
}
|
||||||
|
|
||||||
r.renderingSessionByOrgId = make(map[int64]rendering.Session)
|
r.renderingSessionByOrgId = make(map[int64]rendering.Session)
|
||||||
|
@ -51,6 +51,8 @@ type thumbService struct {
|
|||||||
crawlLockServiceActionName string
|
crawlLockServiceActionName string
|
||||||
log log.Logger
|
log log.Logger
|
||||||
usageStatsService usagestats.Service
|
usageStatsService usagestats.Service
|
||||||
|
canRunCrawler bool
|
||||||
|
settings setting.DashboardPreviewsSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
type crawlerScheduleOptions struct {
|
type crawlerScheduleOptions struct {
|
||||||
@ -67,30 +69,34 @@ func ProvideService(cfg *setting.Cfg, features featuremgmt.FeatureToggles, lockS
|
|||||||
if !features.IsEnabled(featuremgmt.FlagDashboardPreviews) {
|
if !features.IsEnabled(featuremgmt.FlagDashboardPreviews) {
|
||||||
return &dummyService{}
|
return &dummyService{}
|
||||||
}
|
}
|
||||||
logger := log.New("thumbnails_service")
|
logger := log.New("previews_service")
|
||||||
|
|
||||||
|
logger.Info("initialized thumb", "settings", cfg.DashboardPreviews)
|
||||||
thumbnailRepo := newThumbnailRepo(store)
|
thumbnailRepo := newThumbnailRepo(store)
|
||||||
|
|
||||||
|
canRunCrawler := true
|
||||||
crawlerAuth, err := authSetupService.Setup(context.Background())
|
crawlerAuth, err := authSetupService.Setup(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("Failed to setup auth for the dashboard previews crawler", "err", err)
|
logger.Error("failed to setup auth for the dashboard previews crawler", "err", err)
|
||||||
return &dummyService{}
|
canRunCrawler = false
|
||||||
}
|
}
|
||||||
t := &thumbService{
|
t := &thumbService{
|
||||||
usageStatsService: usageStatsService,
|
usageStatsService: usageStatsService,
|
||||||
renderingService: renderService,
|
renderingService: renderService,
|
||||||
renderer: newSimpleCrawler(renderService, gl, thumbnailRepo),
|
renderer: newSimpleCrawler(renderService, gl, thumbnailRepo, cfg, cfg.DashboardPreviews),
|
||||||
thumbnailRepo: thumbnailRepo,
|
thumbnailRepo: thumbnailRepo,
|
||||||
store: store,
|
store: store,
|
||||||
features: features,
|
features: features,
|
||||||
lockService: lockService,
|
lockService: lockService,
|
||||||
crawlLockServiceActionName: "dashboard-crawler",
|
crawlLockServiceActionName: "dashboard-crawler",
|
||||||
log: logger,
|
log: logger,
|
||||||
|
canRunCrawler: canRunCrawler,
|
||||||
|
settings: cfg.DashboardPreviews,
|
||||||
|
|
||||||
scheduleOptions: crawlerScheduleOptions{
|
scheduleOptions: crawlerScheduleOptions{
|
||||||
tickerInterval: time.Hour,
|
tickerInterval: 5 * time.Minute,
|
||||||
crawlInterval: time.Hour * 12,
|
crawlInterval: cfg.DashboardPreviews.SchedulerInterval,
|
||||||
maxCrawlDuration: time.Hour,
|
maxCrawlDuration: cfg.DashboardPreviews.MaxCrawlDuration,
|
||||||
crawlerMode: CrawlerModeThumbs,
|
crawlerMode: CrawlerModeThumbs,
|
||||||
thumbnailKind: models.ThumbnailKindDefault,
|
thumbnailKind: models.ThumbnailKindDefault,
|
||||||
themes: []models.Theme{models.ThemeDark, models.ThemeLight},
|
themes: []models.Theme{models.ThemeDark, models.ThemeLight},
|
||||||
@ -401,6 +407,10 @@ func (hs *thumbService) getDashboardId(c *models.ReqContext, uid string) (int64,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (hs *thumbService) runOnDemandCrawl(parentCtx context.Context, theme models.Theme, mode CrawlerMode, kind models.ThumbnailKind, authOpts rendering.AuthOpts) {
|
func (hs *thumbService) runOnDemandCrawl(parentCtx context.Context, theme models.Theme, mode CrawlerMode, kind models.ThumbnailKind, authOpts rendering.AuthOpts) {
|
||||||
|
if !hs.canRunCrawler {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
crawlerCtx, cancel := context.WithTimeout(parentCtx, hs.scheduleOptions.maxCrawlDuration)
|
crawlerCtx, cancel := context.WithTimeout(parentCtx, hs.scheduleOptions.maxCrawlDuration)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@ -435,7 +445,7 @@ func (hs *thumbService) runScheduledCrawl(parentCtx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (hs *thumbService) Run(ctx context.Context) error {
|
func (hs *thumbService) Run(ctx context.Context) error {
|
||||||
if !hs.features.IsEnabled(featuremgmt.FlagDashboardPreviewsScheduler) {
|
if !hs.canRunCrawler {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,6 +439,8 @@ type Cfg struct {
|
|||||||
|
|
||||||
// Query history
|
// Query history
|
||||||
QueryHistoryEnabled bool
|
QueryHistoryEnabled bool
|
||||||
|
|
||||||
|
DashboardPreviews DashboardPreviewsSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommandLineArgs struct {
|
type CommandLineArgs struct {
|
||||||
@ -1001,6 +1003,8 @@ func (cfg *Cfg) Load(args CommandLineArgs) error {
|
|||||||
|
|
||||||
cfg.readDataSourcesSettings()
|
cfg.readDataSourcesSettings()
|
||||||
|
|
||||||
|
cfg.DashboardPreviews = readDashboardPreviewsSettings(iniFile)
|
||||||
|
|
||||||
if VerifyEmailEnabled && !cfg.Smtp.Enabled {
|
if VerifyEmailEnabled && !cfg.Smtp.Enabled {
|
||||||
cfg.Logger.Warn("require_email_validation is enabled but smtp is disabled")
|
cfg.Logger.Warn("require_email_validation is enabled but smtp is disabled")
|
||||||
}
|
}
|
||||||
|
31
pkg/setting/setting_dashboard_previews.go
Normal file
31
pkg/setting/setting_dashboard_previews.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package setting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DashboardPreviewsSettings struct {
|
||||||
|
SchedulerInterval time.Duration
|
||||||
|
MaxCrawlDuration time.Duration
|
||||||
|
RenderingTimeout time.Duration
|
||||||
|
CrawlThreadCount uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func readDashboardPreviewsSettings(iniFile *ini.File) DashboardPreviewsSettings {
|
||||||
|
maxThreadCount := uint32(20)
|
||||||
|
|
||||||
|
s := DashboardPreviewsSettings{}
|
||||||
|
|
||||||
|
previewsCrawlerSection := iniFile.Section("dashboard_previews.crawler")
|
||||||
|
s.CrawlThreadCount = uint32(previewsCrawlerSection.Key("thread_count").MustUint(6))
|
||||||
|
if s.CrawlThreadCount > maxThreadCount {
|
||||||
|
s.CrawlThreadCount = maxThreadCount
|
||||||
|
}
|
||||||
|
|
||||||
|
s.SchedulerInterval = previewsCrawlerSection.Key("scheduler_interval").MustDuration(12 * time.Hour)
|
||||||
|
s.MaxCrawlDuration = previewsCrawlerSection.Key("max_crawl_duration").MustDuration(1 * time.Hour)
|
||||||
|
s.RenderingTimeout = previewsCrawlerSection.Key("rendering_timeout").MustDuration(20 * time.Second)
|
||||||
|
return s
|
||||||
|
}
|
@ -6,7 +6,7 @@ import { PREVIEWS_LOCAL_STORAGE_KEY } from '../constants';
|
|||||||
|
|
||||||
export const useShowDashboardPreviews = () => {
|
export const useShowDashboardPreviews = () => {
|
||||||
const previewFeatureEnabled = Boolean(config.featureToggles.dashboardPreviews);
|
const previewFeatureEnabled = Boolean(config.featureToggles.dashboardPreviews);
|
||||||
const [showPreviews, setShowPreviews] = useLocalStorage<boolean>(PREVIEWS_LOCAL_STORAGE_KEY, previewFeatureEnabled);
|
const [showPreviews, setShowPreviews] = useLocalStorage<boolean>(PREVIEWS_LOCAL_STORAGE_KEY, false);
|
||||||
|
|
||||||
return { showPreviews: Boolean(showPreviews && previewFeatureEnabled), previewFeatureEnabled, setShowPreviews };
|
return { showPreviews: Boolean(showPreviews && previewFeatureEnabled), previewFeatureEnabled, setShowPreviews };
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user