mirror of
https://github.com/ccfos/nightingale.git
synced 2026-03-03 06:29:16 +00:00
Compare commits
3 Commits
v8.2.0
...
dash-annot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
640e914420 | ||
|
|
6d6dee160b | ||
|
|
473a00bbaa |
@@ -322,6 +322,11 @@ func (rt *Router) Config(r *gin.Engine) {
|
||||
pages.GET("/share-charts", rt.chartShareGets)
|
||||
pages.POST("/share-charts", rt.auth(), rt.chartShareAdd)
|
||||
|
||||
pages.POST("/dashboard-annotations", rt.auth(), rt.user(), rt.perm("/dashboards/put"), rt.dashAnnotationAdd)
|
||||
pages.GET("/dashboard-annotations", rt.dashAnnotationGets)
|
||||
pages.PUT("/dashboard-annotation/:id", rt.auth(), rt.user(), rt.perm("/dashboards/put"), rt.dashAnnotationPut)
|
||||
pages.DELETE("/dashboard-annotation/:id", rt.auth(), rt.user(), rt.perm("/dashboards/del"), rt.dashAnnotationDel)
|
||||
|
||||
// pages.GET("/alert-rules/builtin/alerts-cates", rt.auth(), rt.user(), rt.builtinAlertCateGets)
|
||||
// pages.GET("/alert-rules/builtin/list", rt.auth(), rt.user(), rt.builtinAlertRules)
|
||||
pages.GET("/alert-rules/callbacks", rt.auth(), rt.user(), rt.alertRuleCallbacks)
|
||||
@@ -479,6 +484,7 @@ func (rt *Router) Config(r *gin.Engine) {
|
||||
pages.PUT("/builtin-payloads", rt.auth(), rt.user(), rt.perm("/built-in-components/put"), rt.builtinPayloadsPut)
|
||||
pages.DELETE("/builtin-payloads", rt.auth(), rt.user(), rt.perm("/built-in-components/del"), rt.builtinPayloadsDel)
|
||||
pages.GET("/builtin-payload", rt.auth(), rt.user(), rt.builtinPayloadsGetByUUIDOrID)
|
||||
|
||||
}
|
||||
|
||||
r.GET("/api/n9e/versions", func(c *gin.Context) {
|
||||
|
||||
99
center/router/router_dash_annotation.go
Normal file
99
center/router/router_dash_annotation.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/ccfos/nightingale/v6/models"
|
||||
"github.com/ccfos/nightingale/v6/pkg/ctx"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/toolkits/pkg/ginx"
|
||||
)
|
||||
|
||||
func checkAnnotationPermission(c *gin.Context, ctx *ctx.Context, dashboardId int64) {
|
||||
dashboard, err := models.BoardGetByID(ctx, dashboardId)
|
||||
if err != nil {
|
||||
ginx.Bomb(http.StatusInternalServerError, "failed to get dashboard: %v", err)
|
||||
}
|
||||
|
||||
if dashboard == nil {
|
||||
ginx.Bomb(http.StatusNotFound, "dashboard not found")
|
||||
}
|
||||
|
||||
bg := BusiGroup(ctx, dashboard.GroupId)
|
||||
me := c.MustGet("user").(*models.User)
|
||||
can, err := me.CanDoBusiGroup(ctx, bg, "rw")
|
||||
ginx.Dangerous(err)
|
||||
|
||||
if !can {
|
||||
ginx.Bomb(http.StatusForbidden, "forbidden")
|
||||
}
|
||||
}
|
||||
|
||||
func (rt *Router) dashAnnotationAdd(c *gin.Context) {
|
||||
var f models.DashAnnotation
|
||||
ginx.BindJSON(c, &f)
|
||||
|
||||
username := c.MustGet("username").(string)
|
||||
now := time.Now().Unix()
|
||||
|
||||
checkAnnotationPermission(c, rt.Ctx, f.DashboardId)
|
||||
|
||||
f.CreateBy = username
|
||||
f.CreateAt = now
|
||||
f.UpdateBy = username
|
||||
f.UpdateAt = now
|
||||
|
||||
ginx.NewRender(c).Data(f.Id, f.Add(rt.Ctx))
|
||||
}
|
||||
|
||||
func (rt *Router) dashAnnotationGets(c *gin.Context) {
|
||||
dashboardId := ginx.QueryInt64(c, "dashboard_id")
|
||||
from := ginx.QueryInt64(c, "from")
|
||||
to := ginx.QueryInt64(c, "to")
|
||||
limit := ginx.QueryInt(c, "limit", 100)
|
||||
|
||||
lst, err := models.DashAnnotationGets(rt.Ctx, dashboardId, from, to, limit)
|
||||
ginx.NewRender(c).Data(lst, err)
|
||||
}
|
||||
|
||||
func (rt *Router) dashAnnotationPut(c *gin.Context) {
|
||||
var f models.DashAnnotation
|
||||
ginx.BindJSON(c, &f)
|
||||
|
||||
id := ginx.UrlParamInt64(c, "id")
|
||||
annotation, err := getAnnotationById(rt.Ctx, id)
|
||||
ginx.Dangerous(err)
|
||||
|
||||
checkAnnotationPermission(c, rt.Ctx, annotation.DashboardId)
|
||||
|
||||
f.Id = id
|
||||
f.UpdateAt = time.Now().Unix()
|
||||
f.UpdateBy = c.MustGet("username").(string)
|
||||
|
||||
ginx.NewRender(c).Message(f.Update(rt.Ctx))
|
||||
}
|
||||
|
||||
func (rt *Router) dashAnnotationDel(c *gin.Context) {
|
||||
id := ginx.UrlParamInt64(c, "id")
|
||||
|
||||
annotation, err := getAnnotationById(rt.Ctx, id)
|
||||
ginx.Dangerous(err)
|
||||
checkAnnotationPermission(c, rt.Ctx, annotation.DashboardId)
|
||||
|
||||
ginx.NewRender(c).Message(models.DashAnnotationDel(rt.Ctx, id))
|
||||
}
|
||||
|
||||
// 可以提取获取注释的通用方法
|
||||
func getAnnotationById(ctx *ctx.Context, id int64) (*models.DashAnnotation, error) {
|
||||
annotation, err := models.DashAnnotationGet(ctx, "id=?", id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if annotation == nil {
|
||||
return nil, fmt.Errorf("annotation not found")
|
||||
}
|
||||
return annotation, nil
|
||||
}
|
||||
@@ -887,4 +887,20 @@ CREATE TABLE builtin_payloads (
|
||||
CREATE INDEX idx_component ON builtin_payloads (component);
|
||||
CREATE INDEX idx_builtin_payloads_name ON builtin_payloads (name);
|
||||
CREATE INDEX idx_cate ON builtin_payloads (cate);
|
||||
CREATE INDEX idx_type ON builtin_payloads (type);
|
||||
CREATE INDEX idx_type ON builtin_payloads (type);
|
||||
|
||||
|
||||
CREATE TABLE dash_annotation (
|
||||
id bigserial PRIMARY KEY,
|
||||
dashboard_id bigint not null,
|
||||
panel_id varchar(191) not null,
|
||||
tags text,
|
||||
description text,
|
||||
config text,
|
||||
time_start bigint not null default 0,
|
||||
time_end bigint not null default 0,
|
||||
create_at bigint not null default 0,
|
||||
create_by varchar(64) not null default '',
|
||||
update_at bigint not null default 0,
|
||||
update_by varchar(64) not null default ''
|
||||
);
|
||||
@@ -747,6 +747,24 @@ CREATE TABLE `target_busi_group` (
|
||||
UNIQUE KEY `idx_target_group` (`target_ident`,`group_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
|
||||
CREATE TABLE `dash_annotation` (
|
||||
`id` bigint unsigned not null auto_increment,
|
||||
`dashboard_id` bigint not null comment 'dashboard id',
|
||||
`panel_id` varchar(191) not null comment 'panel id',
|
||||
`tags` text comment 'tags array json string',
|
||||
`description` text comment 'annotation description',
|
||||
`config` text comment 'annotation config',
|
||||
`time_start` bigint not null default 0 comment 'start timestamp',
|
||||
`time_end` bigint not null default 0 comment 'end timestamp',
|
||||
`create_at` bigint not null default 0 comment 'create time',
|
||||
`create_by` varchar(64) not null default '' comment 'creator',
|
||||
`update_at` bigint not null default 0 comment 'update time',
|
||||
`update_by` varchar(64) not null default '' comment 'updater',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_dashboard_id` (`dashboard_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE `task_meta`
|
||||
(
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
|
||||
|
||||
@@ -129,4 +129,22 @@ ALTER TABLE `builtin_components` MODIFY COLUMN `logo` mediumtext COMMENT '''logo
|
||||
/* v8.0.0-beta.2 2024-12-26 */
|
||||
ALTER TABLE `es_index_pattern` ADD COLUMN `cross_cluster_enabled` int not null default 0;
|
||||
|
||||
ALTER TABLE builtin_components ADD COLUMN disabled INT NOT NULL DEFAULT 0 COMMENT 'is disabled or not';
|
||||
/* v8.0.0-beta.3 2024-01-03 */
|
||||
ALTER TABLE `builtin_components` ADD COLUMN `disabled` INT NOT NULL DEFAULT 0 COMMENT 'is disabled or not';
|
||||
|
||||
CREATE TABLE `dash_annotation` (
|
||||
`id` bigint unsigned not null auto_increment,
|
||||
`dashboard_id` bigint not null comment 'dashboard id',
|
||||
`panel_id` varchar(191) not null comment 'panel id',
|
||||
`tags` text comment 'tags array json string',
|
||||
`description` text comment 'annotation description',
|
||||
`config` text comment 'annotation config',
|
||||
`time_start` bigint not null default 0 comment 'start timestamp',
|
||||
`time_end` bigint not null default 0 comment 'end timestamp',
|
||||
`create_at` bigint not null default 0 comment 'create time',
|
||||
`create_by` varchar(64) not null default '' comment 'creator',
|
||||
`update_at` bigint not null default 0 comment 'update time',
|
||||
`update_by` varchar(64) not null default '' comment 'updater',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_dashboard_id` (`dashboard_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
@@ -684,6 +684,22 @@ CREATE TABLE `target_busi_group` (
|
||||
|
||||
CREATE UNIQUE INDEX idx_target_busi_group ON target_busi_group (target_ident, group_id);
|
||||
|
||||
|
||||
CREATE TABLE `dash_annotation` (
|
||||
`id` integer primary key autoincrement,
|
||||
`dashboard_id` bigint not null,
|
||||
`panel_id` varchar(191) not null,
|
||||
`tags` text,
|
||||
`description` text,
|
||||
`config` text,
|
||||
`time_start` bigint not null default 0,
|
||||
`time_end` bigint not null default 0,
|
||||
`create_at` bigint not null default 0,
|
||||
`create_by` varchar(64) not null default '',
|
||||
`update_at` bigint not null default 0,
|
||||
`update_by` varchar(64) not null default ''
|
||||
);
|
||||
|
||||
CREATE TABLE `task_meta`
|
||||
(
|
||||
`id` integer primary key autoincrement,
|
||||
|
||||
89
models/dash_annotation.go
Normal file
89
models/dash_annotation.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/ccfos/nightingale/v6/pkg/ctx"
|
||||
)
|
||||
|
||||
type DashAnnotation struct {
|
||||
Id int64 `json:"id" gorm:"primaryKey"`
|
||||
DashboardId int64 `json:"dashboard_id"`
|
||||
PanelId string `json:"panel_id"`
|
||||
Tags string `json:"-"`
|
||||
TagsJSON []string `json:"tags" gorm:"-"`
|
||||
Description string `json:"description"`
|
||||
Config string `json:"config"`
|
||||
TimeStart int64 `json:"time_start"`
|
||||
TimeEnd int64 `json:"time_end"`
|
||||
CreateAt int64 `json:"create_at"`
|
||||
CreateBy string `json:"create_by"`
|
||||
UpdateAt int64 `json:"update_at"`
|
||||
UpdateBy string `json:"update_by"`
|
||||
}
|
||||
|
||||
func (da *DashAnnotation) TableName() string {
|
||||
return "dash_annotation"
|
||||
}
|
||||
|
||||
func (da *DashAnnotation) DB2FE() error {
|
||||
return json.Unmarshal([]byte(da.Tags), &da.TagsJSON)
|
||||
}
|
||||
|
||||
func (da *DashAnnotation) FE2DB() error {
|
||||
b, err := json.Marshal(da.TagsJSON)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
da.Tags = string(b)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (da *DashAnnotation) Add(ctx *ctx.Context) error {
|
||||
if err := da.FE2DB(); err != nil {
|
||||
return err
|
||||
}
|
||||
return Insert(ctx, da)
|
||||
}
|
||||
|
||||
func (da *DashAnnotation) Update(ctx *ctx.Context) error {
|
||||
if err := da.FE2DB(); err != nil {
|
||||
return err
|
||||
}
|
||||
return DB(ctx).Model(da).Select("dashboard_id", "panel_id", "tags", "description", "config", "time_start", "time_end", "update_at", "update_by").Updates(da).Error
|
||||
}
|
||||
|
||||
func DashAnnotationDel(ctx *ctx.Context, id int64) error {
|
||||
return DB(ctx).Where("id = ?", id).Delete(&DashAnnotation{}).Error
|
||||
}
|
||||
|
||||
func DashAnnotationGet(ctx *ctx.Context, where string, args ...interface{}) (*DashAnnotation, error) {
|
||||
var lst []*DashAnnotation
|
||||
err := DB(ctx).Where(where, args...).Find(&lst).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(lst) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
err = lst[0].DB2FE()
|
||||
return lst[0], err
|
||||
}
|
||||
|
||||
func DashAnnotationGets(ctx *ctx.Context, dashboardId int64, from, to int64, limit int) ([]DashAnnotation, error) {
|
||||
session := DB(ctx).Where("dashboard_id = ? AND time_start <= ? AND time_end >= ?", dashboardId, to, from)
|
||||
|
||||
var lst []DashAnnotation
|
||||
err := session.Order("id").Limit(limit).Find(&lst).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := 0; i < len(lst); i++ {
|
||||
lst[i].DB2FE()
|
||||
}
|
||||
|
||||
return lst, nil
|
||||
}
|
||||
@@ -67,7 +67,7 @@ func MigrateTables(db *gorm.DB) error {
|
||||
&TaskRecord{}, &ChartShare{}, &Target{}, &Configs{}, &Datasource{}, &NotifyTpl{},
|
||||
&Board{}, &BoardBusigroup{}, &Users{}, &SsoConfig{}, &models.BuiltinMetric{},
|
||||
&models.MetricFilter{}, &models.NotificaitonRecord{},
|
||||
&models.TargetBusiGroup{}, &EsIndexPatternMigrate{}}
|
||||
&models.TargetBusiGroup{}, &EsIndexPatternMigrate{}, &DashAnnotation{}}
|
||||
|
||||
if isPostgres(db) {
|
||||
dts = append(dts, &models.PostgresBuiltinComponent{})
|
||||
@@ -327,3 +327,22 @@ type EsIndexPatternMigrate struct {
|
||||
func (EsIndexPatternMigrate) TableName() string {
|
||||
return "es_index_pattern"
|
||||
}
|
||||
|
||||
type DashAnnotation struct {
|
||||
Id int64 `gorm:"column:id;primaryKey;autoIncrement"`
|
||||
DashboardId int64 `gorm:"column:dashboard_id;not null"`
|
||||
PanelId string `gorm:"column:panel_id;type:varchar(191);not null"`
|
||||
Tags string `gorm:"column:tags;type:text"`
|
||||
Description string `gorm:"column:description;type:text"`
|
||||
Config string `gorm:"column:config;type:text"`
|
||||
TimeStart int64 `gorm:"column:time_start;not null;default:0"`
|
||||
TimeEnd int64 `gorm:"column:time_end;not null;default:0"`
|
||||
CreateAt int64 `gorm:"column:create_at;not null;default:0"`
|
||||
CreateBy string `gorm:"column:create_by;type:varchar(64);not null;default:''"`
|
||||
UpdateAt int64 `gorm:"column:update_at;not null;default:0"`
|
||||
UpdateBy string `gorm:"column:update_by;type:varchar(64);not null;default:''"`
|
||||
}
|
||||
|
||||
func (DashAnnotation) TableName() string {
|
||||
return "dash_annotation"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user