Commit 1638c6be by bergquist

enable partial tag matches for annotations

parent 19c7dd98
......@@ -14,16 +14,17 @@ import (
func GetAnnotations(c *m.ReqContext) Response {
query := &annotations.ItemQuery{
From: c.QueryInt64("from"),
To: c.QueryInt64("to"),
OrgId: c.OrgId,
UserId: c.QueryInt64("userId"),
AlertId: c.QueryInt64("alertId"),
DashboardId: c.QueryInt64("dashboardId"),
PanelId: c.QueryInt64("panelId"),
Limit: c.QueryInt64("limit"),
Tags: c.QueryStrings("tags"),
Type: c.Query("type"),
From: c.QueryInt64("from"),
To: c.QueryInt64("to"),
OrgId: c.OrgId,
UserId: c.QueryInt64("userId"),
AlertId: c.QueryInt64("alertId"),
DashboardId: c.QueryInt64("dashboardId"),
PanelId: c.QueryInt64("panelId"),
Limit: c.QueryInt64("limit"),
Tags: c.QueryStrings("tags"),
Type: c.Query("type"),
PartialMatch: c.QueryBool("partialMatch"),
}
repo := annotations.GetRepository()
......
......@@ -21,6 +21,7 @@ type ItemQuery struct {
RegionId int64 `json:"regionId"`
Tags []string `json:"tags"`
Type string `json:"type"`
PartialMatch bool `json:"partialMatch"`
Limit int64 `json:"limit"`
}
......
......@@ -211,7 +211,12 @@ func (r *SqlAnnotationRepo) Find(query *annotations.ItemQuery) ([]*annotations.I
)
`, strings.Join(keyValueFilters, " OR "))
sql.WriteString(fmt.Sprintf(" AND (%s) = %d ", tagsSubQuery, len(tags)))
if query.PartialMatch {
sql.WriteString(fmt.Sprintf(" AND (%s) > 0 ", tagsSubQuery))
} else {
sql.WriteString(fmt.Sprintf(" AND (%s) = %d ", tagsSubQuery, len(tags)))
}
}
}
......
......@@ -78,7 +78,31 @@ func TestAnnotations(t *testing.T) {
So(err, ShouldBeNil)
So(annotation2.Id, ShouldBeGreaterThan, 0)
Convey("Can query for annotation", func() {
globalAnnotation1 := &annotations.Item{
OrgId: 1,
UserId: 1,
Text: "deploy",
Type: "",
Epoch: 15,
Tags: []string{"deploy"},
}
err = repo.Save(globalAnnotation1)
So(err, ShouldBeNil)
So(globalAnnotation1.Id, ShouldBeGreaterThan, 0)
globalAnnotation2 := &annotations.Item{
OrgId: 1,
UserId: 1,
Text: "rollback",
Type: "",
Epoch: 17,
Tags: []string{"rollback"},
}
err = repo.Save(globalAnnotation2)
So(err, ShouldBeNil)
So(globalAnnotation2.Id, ShouldBeGreaterThan, 0)
Convey("Can query for annotation by dashboard id", func() {
items, err := repo.Find(&annotations.ItemQuery{
OrgId: 1,
DashboardId: 1,
......@@ -165,7 +189,7 @@ func TestAnnotations(t *testing.T) {
OrgId: 1,
DashboardId: 1,
From: 1,
To: 15,
To: 15, //this will exclude the second test annotation
Tags: []string{"outage", "error"},
})
......@@ -173,6 +197,19 @@ func TestAnnotations(t *testing.T) {
So(items, ShouldHaveLength, 1)
})
Convey("Should find two annotations using partial match", func() {
items, err := repo.Find(&annotations.ItemQuery{
OrgId: 1,
From: 1,
To: 25,
PartialMatch: true,
Tags: []string{"rollback", "deploy"},
})
So(err, ShouldBeNil)
So(items, ShouldHaveLength, 2)
})
Convey("Should find one when all key value tag filters does match", func() {
items, err := repo.Find(&annotations.ItemQuery{
OrgId: 1,
......
......@@ -40,6 +40,7 @@ class GrafanaDatasource {
to: options.range.to.valueOf(),
limit: options.annotation.limit,
tags: options.annotation.tags,
partialMatch: options.annotation.partialMatch,
};
if (options.annotation.type === 'dashboard') {
......
......@@ -2,7 +2,7 @@
<div class="gf-form-group">
<div class="gf-form-inline">
<div class="gf-form">
<span class="gf-form-label width-8">
<span class="gf-form-label width-9">
Filter by
<info-popover mode="right-normal">
<ul>
......@@ -11,18 +11,11 @@
</ul>
</info-popover>
</span>
<div class="gf-form-select-wrapper width-9">
<div class="gf-form-select-wrapper width-8">
<select class="gf-form-input" ng-model="ctrl.annotation.type" ng-options="f.value as f.text for f in ctrl.types">
</select>
</div>
</div>
<div class="gf-form" ng-if="ctrl.annotation.type === 'tags'">
<span class="gf-form-label">Tags</span>
<bootstrap-tagsinput ng-model="ctrl.annotation.tags" tagclass="label label-tag" placeholder="add tags">
</bootstrap-tagsinput>
</div>
<div class="gf-form">
<span class="gf-form-label">Max limit</span>
<div class="gf-form-select-wrapper">
......@@ -31,6 +24,22 @@
</div>
</div>
</div>
<div class="gf-form-inline">
<div class="gf-form" ng-if="ctrl.annotation.type === 'tags'">
<gf-form-switch
class="gf-form"
label="Partial match"
label-class="width-9"
checked="ctrl.annotation.partialMatch"
on-change="ctrl.refresh()"
tooltip="By default Grafana will only show annotation that matches all tags in the query. Enabling this will make Grafana return any annotation with the tags you specify."></gf-form-switch>
</div>
<div class="gf-form" ng-if="ctrl.annotation.type === 'tags'">
<span class="gf-form-label">Tags</span>
<bootstrap-tagsinput ng-model="ctrl.annotation.tags" tagclass="label label-tag" placeholder="add tags">
</bootstrap-tagsinput>
</div>
</div>
</div>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment