Просмотр исходного кода

dashboard history: clean up dashboard version history

Alexander Zobnin 8 лет назад
Родитель
Сommit
08e2bbef83

+ 8 - 1
conf/defaults.ini

@@ -174,6 +174,7 @@ disable_gravatar = false
 # data source proxy whitelist (ip_or_domain:port separated by spaces)
 # data source proxy whitelist (ip_or_domain:port separated by spaces)
 data_source_proxy_whitelist =
 data_source_proxy_whitelist =
 
 
+#################################### Snapshots ###########################
 [snapshots]
 [snapshots]
 # snapshot sharing options
 # snapshot sharing options
 external_enabled = true
 external_enabled = true
@@ -186,7 +187,13 @@ snapshot_remove_expired = true
 # remove snapshots after 90 days
 # remove snapshots after 90 days
 snapshot_TTL_days = 90
 snapshot_TTL_days = 90
 
 
-#################################### Users ####################################
+#################################### Dashboards History ##################
+[dashboards.history]
+# A setting of 20 (default) means only the last 20 versions will be stored and older versions removed.
+# To keep all dashboard versions you can set this value to 2147483647.
+versions_to_keep = 20
+
+#################################### Users ###############################
 [users]
 [users]
 # disable user signup / registration
 # disable user signup / registration
 allow_sign_up = false
 allow_sign_up = false

+ 7 - 0
pkg/models/dashboard_version.go

@@ -69,3 +69,10 @@ type GetDashboardVersionsQuery struct {
 
 
 	Result []*DashboardVersionDTO
 	Result []*DashboardVersionDTO
 }
 }
+
+//
+// Commands
+//
+
+type DeleteExpiredVersionsCommand struct {
+}

+ 5 - 0
pkg/services/cleanup/cleanup.go

@@ -45,6 +45,7 @@ func (service *CleanUpService) start(ctx context.Context) error {
 		case <-ticker.C:
 		case <-ticker.C:
 			service.cleanUpTmpFiles()
 			service.cleanUpTmpFiles()
 			service.deleteExpiredSnapshots()
 			service.deleteExpiredSnapshots()
+			service.deleteExpiredDashboardVersions()
 		case <-ctx.Done():
 		case <-ctx.Done():
 			return ctx.Err()
 			return ctx.Err()
 		}
 		}
@@ -83,3 +84,7 @@ func (service *CleanUpService) cleanUpTmpFiles() {
 func (service *CleanUpService) deleteExpiredSnapshots() {
 func (service *CleanUpService) deleteExpiredSnapshots() {
 	bus.Dispatch(&m.DeleteExpiredSnapshotsCommand{})
 	bus.Dispatch(&m.DeleteExpiredSnapshotsCommand{})
 }
 }
+
+func (service *CleanUpService) deleteExpiredDashboardVersions() {
+	bus.Dispatch(&m.DeleteExpiredVersionsCommand{})
+}

+ 97 - 0
pkg/services/sqlstore/dashboard_version.go

@@ -1,13 +1,21 @@
 package sqlstore
 package sqlstore
 
 
 import (
 import (
+	"fmt"
+	"math"
+	"sort"
+	"strconv"
+	"strings"
+
 	"github.com/grafana/grafana/pkg/bus"
 	"github.com/grafana/grafana/pkg/bus"
 	m "github.com/grafana/grafana/pkg/models"
 	m "github.com/grafana/grafana/pkg/models"
+	"github.com/grafana/grafana/pkg/setting"
 )
 )
 
 
 func init() {
 func init() {
 	bus.AddHandler("sql", GetDashboardVersion)
 	bus.AddHandler("sql", GetDashboardVersion)
 	bus.AddHandler("sql", GetDashboardVersions)
 	bus.AddHandler("sql", GetDashboardVersions)
+	bus.AddHandler("sql", DeleteExpiredVersions)
 }
 }
 
 
 // GetDashboardVersion gets the dashboard version for the given dashboard ID and version number.
 // GetDashboardVersion gets the dashboard version for the given dashboard ID and version number.
@@ -58,3 +66,92 @@ func GetDashboardVersions(query *m.GetDashboardVersionsQuery) error {
 	}
 	}
 	return nil
 	return nil
 }
 }
+
+func DeleteExpiredVersions(cmd *m.DeleteExpiredVersionsCommand) error {
+	return inTransaction(func(sess *DBSession) error {
+		var expiredCount int64 = 0
+		var versions []DashboardVersionExp
+
+		// Don't clean up if user set versions_to_keep to 2147483647 (MaxInt32)
+		if versionsToKeep := setting.DashboardVersionsToKeep; versionsToKeep < math.MaxInt32 {
+			// Get dashboard ids to clean up
+			affectedDashboardsQuery := fmt.Sprintf(`SELECT dashboard_id FROM dashboard_version
+				GROUP BY dashboard_id HAVING COUNT(dashboard_version.id)>%d`, versionsToKeep)
+
+			err := x.Table("dashboard_version").
+				Select("dashboard_version.id, dashboard_version.version, dashboard_version.dashboard_id").
+				Where(fmt.Sprintf("dashboard_id IN (%s)", affectedDashboardsQuery)).
+				Find(&versions)
+
+			if err != nil {
+				return err
+			}
+
+			// Keep last versionsToKeep versions and delete other
+			versionIdsToDelete := getVersionIDsToDelete(versions, versionsToKeep)
+			versionIdsToDeleteStr := getVersionIDsToDeleteStr(versionIdsToDelete)
+			deleteExpiredSql := fmt.Sprintf("DELETE FROM dashboard_version WHERE id IN (%v)", strings.Join(versionIdsToDeleteStr, ", "))
+			expiredResponse, err := x.Exec(deleteExpiredSql)
+			if err != nil {
+				return err
+			}
+			expiredCount, _ = expiredResponse.RowsAffected()
+		}
+
+		sqlog.Debug("Deleted old/expired dashboard versions", "expired", expiredCount)
+		return nil
+	})
+}
+
+// Short version of DashboardVersion for getting expired versions
+type DashboardVersionExp struct {
+	Id          int64 `json:"id"`
+	DashboardId int64 `json:"dashboardId"`
+	Version     int   `json:"version"`
+}
+
+// Implement sort.Interface for []DashboardVersionExp (sort by Version field)
+type ByVersion []DashboardVersionExp
+
+func (v ByVersion) Len() int {
+	return len(v)
+}
+
+func (v ByVersion) Swap(i, j int) {
+	v[i], v[j] = v[j], v[i]
+}
+
+func (v ByVersion) Less(i, j int) bool {
+	return v[i].Version < v[j].Version
+}
+
+func getVersionIDsToDelete(versions []DashboardVersionExp, versionsToKeep int) []int64 {
+	dashboards := make(map[int64][]DashboardVersionExp)
+	for _, v := range versions {
+		elem, present := dashboards[v.DashboardId]
+		if present {
+			dashboards[v.DashboardId] = append(elem, v)
+		} else {
+			dashboards[v.DashboardId] = []DashboardVersionExp{v}
+		}
+	}
+
+	versionIds := make([]int64, 0)
+	for dashboard_id, versions := range dashboards {
+		sort.Sort(sort.Reverse(ByVersion(versions)))
+		dashboards[dashboard_id] = versions[versionsToKeep:]
+		for _, ver := range dashboards[dashboard_id] {
+			versionIds = append(versionIds, ver.Id)
+		}
+	}
+
+	return versionIds
+}
+
+func getVersionIDsToDeleteStr(versionIds []int64) []string {
+	var versionIdsToDeleteStr []string
+	for _, versionId := range versionIds {
+		versionIdsToDeleteStr = append(versionIdsToDeleteStr, strconv.FormatInt(versionId, 10))
+	}
+	return versionIdsToDeleteStr
+}

+ 7 - 0
pkg/setting/setting.go

@@ -89,6 +89,9 @@ var (
 	SnapShotTTLDays       int
 	SnapShotTTLDays       int
 	SnapShotRemoveExpired bool
 	SnapShotRemoveExpired bool
 
 
+	// Dashboard history
+	DashboardVersionsToKeep int
+
 	// User settings
 	// User settings
 	AllowUserSignUp         bool
 	AllowUserSignUp         bool
 	AllowUserOrgCreate      bool
 	AllowUserOrgCreate      bool
@@ -518,6 +521,10 @@ func NewConfigContext(args *CommandLineArgs) error {
 	SnapShotRemoveExpired = snapshots.Key("snapshot_remove_expired").MustBool(true)
 	SnapShotRemoveExpired = snapshots.Key("snapshot_remove_expired").MustBool(true)
 	SnapShotTTLDays = snapshots.Key("snapshot_TTL_days").MustInt(90)
 	SnapShotTTLDays = snapshots.Key("snapshot_TTL_days").MustInt(90)
 
 
+	// read dashboard settings
+	dashboards := Cfg.Section("dashboards")
+	DashboardVersionsToKeep = dashboards.Key("snapshot_TTL_days").MustInt(20)
+
 	//  read data source proxy white list
 	//  read data source proxy white list
 	DataProxyWhiteList = make(map[string]bool)
 	DataProxyWhiteList = make(map[string]bool)
 	for _, hostAndIp := range util.SplitString(security.Key("data_source_proxy_whitelist").String()) {
 	for _, hostAndIp := range util.SplitString(security.Key("data_source_proxy_whitelist").String()) {