diff --git a/conf/defaults.ini b/conf/defaults.ini index 4ca993038f9..5faba3ea7bd 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -14,6 +14,9 @@ instance_name = ${HOSTNAME} # Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) data = data +# Temporary files in `data` directory older than given duration will be removed +temp_data_lifetime = 24h + # Directory where grafana can store logs logs = data/log diff --git a/conf/sample.ini b/conf/sample.ini index 45888cbadd8..87544a5ac39 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -14,6 +14,9 @@ # Path to where grafana can store temp files, sessions, and the sqlite3 db (if that is used) ;data = /var/lib/grafana +# Temporary files in `data` directory older than given duration will be removed +;temp_data_lifetime = 24h + # Directory where grafana can store logs ;logs = /var/log/grafana diff --git a/docs/sources/installation/configuration.md b/docs/sources/installation/configuration.md index c1d0f3da834..668a44fcb2b 100644 --- a/docs/sources/installation/configuration.md +++ b/docs/sources/installation/configuration.md @@ -80,6 +80,11 @@ Path to where Grafana stores the sqlite3 database (if used), file based sessions (if used), and other data. This path is usually specified via command line in the init.d script or the systemd service file. +### temp_data_lifetime + +How long temporary images in `data` directory should be kept. Defaults to: `24h`. Supported modifiers: `h` (hours), +`m` (minutes), for example: `168h`, `30m`, `10h30m`. Use `0` to never clean up temporary files. + ### logs Path to where Grafana will store logs. This path is usually specified via diff --git a/pkg/services/cleanup/cleanup.go b/pkg/services/cleanup/cleanup.go index 69bc7695dea..521601a358b 100644 --- a/pkg/services/cleanup/cleanup.go +++ b/pkg/services/cleanup/cleanup.go @@ -57,8 +57,10 @@ func (srv *CleanUpService) cleanUpTmpFiles() { } var toDelete []os.FileInfo + var now = time.Now() + for _, file := range files { - if file.ModTime().AddDate(0, 0, 1).Before(time.Now()) { + if srv.shouldCleanupTempFile(file.ModTime(), now) { toDelete = append(toDelete, file) } } @@ -74,6 +76,14 @@ func (srv *CleanUpService) cleanUpTmpFiles() { srv.log.Debug("Found old rendered image to delete", "deleted", len(toDelete), "keept", len(files)) } +func (srv *CleanUpService) shouldCleanupTempFile(filemtime time.Time, now time.Time) bool { + if srv.Cfg.TempDataLifetime == 0 { + return false + } + + return filemtime.Add(srv.Cfg.TempDataLifetime).Before(now) +} + func (srv *CleanUpService) deleteExpiredSnapshots() { cmd := m.DeleteExpiredSnapshotsCommand{} if err := bus.Dispatch(&cmd); err != nil { diff --git a/pkg/services/cleanup/cleanup_test.go b/pkg/services/cleanup/cleanup_test.go new file mode 100644 index 00000000000..54d29e32bf1 --- /dev/null +++ b/pkg/services/cleanup/cleanup_test.go @@ -0,0 +1,41 @@ +package cleanup + +import ( + "github.com/grafana/grafana/pkg/setting" + . "github.com/smartystreets/goconvey/convey" + "testing" + "time" +) + +func TestCleanUpTmpFiles(t *testing.T) { + Convey("Cleanup service tests", t, func() { + cfg := setting.Cfg{} + cfg.TempDataLifetime, _ = time.ParseDuration("24h") + service := CleanUpService{ + Cfg: &cfg, + } + now := time.Now() + secondAgo := now.Add(-time.Second) + twoDaysAgo := now.Add(-time.Second * 3600 * 24 * 2) + weekAgo := now.Add(-time.Second * 3600 * 24 * 7) + + Convey("Should not cleanup recent files", func() { + So(service.shouldCleanupTempFile(secondAgo, now), ShouldBeFalse) + }) + + Convey("Should cleanup older files", func() { + So(service.shouldCleanupTempFile(twoDaysAgo, now), ShouldBeTrue) + }) + + Convey("After increasing temporary files lifetime, older files should be kept", func() { + cfg.TempDataLifetime, _ = time.ParseDuration("1000h") + So(service.shouldCleanupTempFile(weekAgo, now), ShouldBeFalse) + }) + + Convey("If lifetime is 0, files should never be cleaned up", func() { + cfg.TempDataLifetime = 0 + So(service.shouldCleanupTempFile(weekAgo, now), ShouldBeFalse) + }) + }) + +} diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 9bae4e35950..e71a3619aa5 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -20,6 +20,7 @@ import ( "github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/util" + "time" ) type Scheme string @@ -195,6 +196,8 @@ type Cfg struct { PhantomDir string RendererUrl string DisableBruteForceLoginProtection bool + + TempDataLifetime time.Duration } type CommandLineArgs struct { @@ -637,6 +640,7 @@ func (cfg *Cfg) Load(args *CommandLineArgs) error { cfg.RendererUrl = renderSec.Key("server_url").String() cfg.ImagesDir = filepath.Join(DataPath, "png") cfg.PhantomDir = filepath.Join(HomePath, "tools/phantomjs") + cfg.TempDataLifetime = iniFile.Section("paths").Key("temp_data_lifetime").MustDuration(time.Second * 3600 * 24) analytics := iniFile.Section("analytics") ReportingEnabled = analytics.Key("reporting_enabled").MustBool(true)