extractor_test.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package alerting
  2. import (
  3. "testing"
  4. "github.com/grafana/grafana/pkg/bus"
  5. "github.com/grafana/grafana/pkg/components/simplejson"
  6. m "github.com/grafana/grafana/pkg/models"
  7. . "github.com/smartystreets/goconvey/convey"
  8. )
  9. func TestAlertRuleExtraction(t *testing.T) {
  10. Convey("Parsing alert rules from dashboard json", t, func() {
  11. Convey("Parsing and validating alerts from dashboards", func() {
  12. json := `{
  13. "id": 57,
  14. "title": "Graphite 4",
  15. "originalTitle": "Graphite 4",
  16. "tags": [
  17. "graphite"
  18. ],
  19. "rows": [
  20. {
  21. "panels": [
  22. {
  23. "title": "Active desktop users",
  24. "editable": true,
  25. "type": "graph",
  26. "id": 3,
  27. "targets": [
  28. {
  29. "refId": "A",
  30. "target": "aliasByNode(statsd.fakesite.counters.session_start.desktop.count, 4)"
  31. }
  32. ],
  33. "datasource": null,
  34. "alert": {
  35. "name": "name1",
  36. "description": "desc1",
  37. "scheduler": 1,
  38. "enabled": true,
  39. "critical": {
  40. "level": 20,
  41. "op": ">"
  42. },
  43. "frequency": "60s",
  44. "query": {
  45. "from": "5m",
  46. "refId": "A",
  47. "to": "now"
  48. },
  49. "transform": {
  50. "method": "avg",
  51. "type": "aggregation"
  52. },
  53. "warning": {
  54. "level": 10,
  55. "op": ">"
  56. }
  57. }
  58. },
  59. {
  60. "title": "Active mobile users",
  61. "id": 4,
  62. "targets": [
  63. {
  64. "refId": "A",
  65. "target": "aliasByNode(statsd.fakesite.counters.session_start.mobile.count, 4)"
  66. }
  67. ],
  68. "datasource": "graphite2",
  69. "alert": {
  70. "name": "name2",
  71. "description": "desc2",
  72. "scheduler": 0,
  73. "enabled": true,
  74. "critical": {
  75. "level": 20,
  76. "op": ">"
  77. },
  78. "frequency": "60s",
  79. "query": {
  80. "from": "5m",
  81. "refId": "A",
  82. "to": "now"
  83. },
  84. "transform": {
  85. "method": "avg",
  86. "name": "aggregation"
  87. },
  88. "warning": {
  89. "level": 10,
  90. "op": ">"
  91. }
  92. }
  93. }
  94. ],
  95. "title": "Row"
  96. },
  97. {
  98. "collapse": false,
  99. "editable": true,
  100. "height": "250px",
  101. "panels": [
  102. {
  103. "datasource": "InfluxDB",
  104. "id": 2,
  105. "targets": [
  106. {
  107. "dsType": "influxdb",
  108. "groupBy": [
  109. {
  110. "params": [
  111. "$interval"
  112. ],
  113. "type": "time"
  114. },
  115. {
  116. "params": [
  117. "null"
  118. ],
  119. "type": "fill"
  120. }
  121. ],
  122. "measurement": "cpu",
  123. "policy": "default",
  124. "query": "SELECT mean(\"value\") FROM \"cpu\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
  125. "refId": "A",
  126. "resultFormat": "table",
  127. "select": [
  128. [
  129. {
  130. "params": [
  131. "value"
  132. ],
  133. "type": "field"
  134. },
  135. {
  136. "params": [],
  137. "type": "mean"
  138. }
  139. ]
  140. ],
  141. "tags": [],
  142. "target": ""
  143. }
  144. ],
  145. "title": "Broken influxdb panel",
  146. "transform": "table",
  147. "type": "table",
  148. "alert": {
  149. "deleted": true
  150. }
  151. }
  152. ],
  153. "title": "New row"
  154. }
  155. ]
  156. }`
  157. dashJson, err := simplejson.NewJson([]byte(json))
  158. So(err, ShouldBeNil)
  159. dash := m.NewDashboardFromJson(dashJson)
  160. extractor := NewDashAlertExtractor(dash, 1)
  161. // mock data
  162. defaultDs := &m.DataSource{Id: 12, OrgId: 2, Name: "I am default", IsDefault: true}
  163. graphite2Ds := &m.DataSource{Id: 15, OrgId: 2, Name: "graphite2"}
  164. bus.AddHandler("test", func(query *m.GetDataSourcesQuery) error {
  165. query.Result = []*m.DataSource{defaultDs, graphite2Ds}
  166. return nil
  167. })
  168. bus.AddHandler("test", func(query *m.GetDataSourceByNameQuery) error {
  169. if query.Name == defaultDs.Name {
  170. query.Result = defaultDs
  171. }
  172. if query.Name == graphite2Ds.Name {
  173. query.Result = graphite2Ds
  174. }
  175. return nil
  176. })
  177. alerts, err := extractor.GetRuleModels()
  178. Convey("Get rules without error", func() {
  179. So(err, ShouldBeNil)
  180. })
  181. Convey("all properties have been set", func() {
  182. So(len(alerts), ShouldEqual, 2)
  183. for _, v := range alerts {
  184. So(v.DashboardId, ShouldEqual, 57)
  185. So(v.Name, ShouldNotBeEmpty)
  186. So(v.Description, ShouldNotBeEmpty)
  187. }
  188. Convey("should extract scheduler property", func() {
  189. So(alerts[0].Scheduler, ShouldEqual, 1)
  190. So(alerts[1].Scheduler, ShouldEqual, 0)
  191. })
  192. Convey("should extract panel idc", func() {
  193. So(alerts[0].PanelId, ShouldEqual, 3)
  194. So(alerts[1].PanelId, ShouldEqual, 4)
  195. })
  196. Convey("should extract name and desc", func() {
  197. So(alerts[0].Name, ShouldEqual, "name1")
  198. So(alerts[0].Description, ShouldEqual, "desc1")
  199. So(alerts[1].Name, ShouldEqual, "name2")
  200. So(alerts[1].Description, ShouldEqual, "desc2")
  201. })
  202. })
  203. })
  204. })
  205. }