diff --git a/pkg/api/annotations.go b/pkg/api/annotations.go index 300fa7f2cdc..be069f2b07e 100644 --- a/pkg/api/annotations.go +++ b/pkg/api/annotations.go @@ -1,6 +1,10 @@ package api import ( + "fmt" + "strings" + "time" + "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/components/simplejson" "github.com/grafana/grafana/pkg/middleware" @@ -78,6 +82,60 @@ func PostAnnotation(c *middleware.Context, cmd dtos.PostAnnotationsCmd) Response return ApiSuccess("Annotation added") } +type GraphiteAnnotationError struct { + message string +} + +func (e *GraphiteAnnotationError) Error() string { + return e.message +} + +func formatGraphiteAnnotation(what string, data string) string { + return fmt.Sprintf("%s\n%s", what, data) +} + +func PostGraphiteAnnotation(c *middleware.Context, cmd dtos.PostGraphiteAnnotationsCmd) Response { + repo := annotations.GetRepository() + + if cmd.When == 0 { + cmd.When = time.Now().Unix() + } + text := formatGraphiteAnnotation(cmd.What, cmd.Data) + + // Support tags in prior to Graphite 0.10.0 format (string of tags separated by space) + var tagsArray []string + switch tags := cmd.Tags.(type) { + case string: + tagsArray = strings.Split(tags, " ") + case []interface{}: + for _, t := range tags { + if tagStr, ok := t.(string); ok { + tagsArray = append(tagsArray, tagStr) + } else { + err := &GraphiteAnnotationError{"tag should be a string"} + return ApiError(500, "Failed to save Graphite annotation", err) + } + } + default: + err := &GraphiteAnnotationError{"unsupported tags format"} + return ApiError(500, "Failed to save Graphite annotation", err) + } + + item := annotations.Item{ + OrgId: c.OrgId, + UserId: c.UserId, + Epoch: cmd.When, + Text: text, + Tags: tagsArray, + } + + if err := repo.Save(&item); err != nil { + return ApiError(500, "Failed to save Graphite annotation", err) + } + + return ApiSuccess("Graphite Annotation added") +} + func UpdateAnnotation(c *middleware.Context, cmd dtos.UpdateAnnotationsCmd) Response { annotationId := c.ParamsInt64(":annotationId") diff --git a/pkg/api/api.go b/pkg/api/api.go index 802d6e2d028..8c91120facc 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -292,6 +292,7 @@ func (hs *HttpServer) registerRoutes() { annotationsRoute.Delete("/:annotationId", wrap(DeleteAnnotationById)) annotationsRoute.Put("/:annotationId", bind(dtos.UpdateAnnotationsCmd{}), wrap(UpdateAnnotation)) annotationsRoute.Delete("/region/:regionId", wrap(DeleteAnnotationRegion)) + annotationsRoute.Post("/graphite", bind(dtos.PostGraphiteAnnotationsCmd{}), wrap(PostGraphiteAnnotation)) }, reqEditorRole) // error test diff --git a/pkg/api/dtos/annotations.go b/pkg/api/dtos/annotations.go index ee5f6915b66..c917b0d9feb 100644 --- a/pkg/api/dtos/annotations.go +++ b/pkg/api/dtos/annotations.go @@ -29,3 +29,10 @@ type DeleteAnnotationsCmd struct { AnnotationId int64 `json:"annotationId"` RegionId int64 `json:"regionId"` } + +type PostGraphiteAnnotationsCmd struct { + When int64 `json:"when"` + What string `json:"what"` + Data string `json:"data"` + Tags interface{} `json:"tags"` +} diff --git a/public/app/features/annotations/annotation_tooltip.ts b/public/app/features/annotations/annotation_tooltip.ts index c8c95b38392..c950d3edd55 100644 --- a/public/app/features/annotations/annotation_tooltip.ts +++ b/public/app/features/annotations/annotation_tooltip.ts @@ -66,7 +66,7 @@ export function annotationTooltipDirective($sanitize, dashboardSrv, contextSrv, tooltip += '