extractor_test.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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. "handler": 1,
  38. "enabled": true,
  39. "critical": {
  40. "value": 20,
  41. "op": ">"
  42. },
  43. "frequency": "60s",
  44. "query": {
  45. "from": "5m",
  46. "refId": "A",
  47. "to": "now"
  48. },
  49. "transform": {
  50. "type": "avg",
  51. "name": "aggregation"
  52. },
  53. "warn": {
  54. "value": 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. "handler": 0,
  73. "enabled": true,
  74. "critical": {
  75. "value": 20,
  76. "op": ">"
  77. },
  78. "frequency": "60s",
  79. "query": {
  80. "from": "5m",
  81. "refId": "A",
  82. "to": "now"
  83. },
  84. "transform": {
  85. "type": "avg",
  86. "name": "aggregation"
  87. },
  88. "warn": {
  89. "value": 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. "alert": {
  106. "name": "name2",
  107. "description": "desc2",
  108. "enabled": false,
  109. "critical": {
  110. "level": 20,
  111. "op": ">"
  112. },
  113. "warn": {
  114. "level": 10,
  115. "op": ">"
  116. }
  117. },
  118. "targets": [
  119. {
  120. "dsType": "influxdb",
  121. "groupBy": [
  122. {
  123. "params": [
  124. "$interval"
  125. ],
  126. "type": "time"
  127. },
  128. {
  129. "params": [
  130. "null"
  131. ],
  132. "type": "fill"
  133. }
  134. ],
  135. "measurement": "cpu",
  136. "policy": "default",
  137. "query": "SELECT mean(\"value\") FROM \"cpu\" WHERE $timeFilter GROUP BY time($interval) fill(null)",
  138. "refId": "A",
  139. "resultFormat": "table",
  140. "select": [
  141. [
  142. {
  143. "params": [
  144. "value"
  145. ],
  146. "type": "field"
  147. },
  148. {
  149. "params": [],
  150. "type": "mean"
  151. }
  152. ]
  153. ],
  154. "tags": [],
  155. "target": ""
  156. }
  157. ],
  158. "title": "Broken influxdb panel",
  159. "transform": "table",
  160. "type": "table"
  161. }
  162. ],
  163. "title": "New row"
  164. }
  165. ]
  166. }`
  167. dashJson, err := simplejson.NewJson([]byte(json))
  168. So(err, ShouldBeNil)
  169. dash := m.NewDashboardFromJson(dashJson)
  170. extractor := NewDashAlertExtractor(dash, 1)
  171. // mock data
  172. defaultDs := &m.DataSource{Id: 12, OrgId: 2, Name: "I am default", IsDefault: true}
  173. graphite2Ds := &m.DataSource{Id: 15, OrgId: 2, Name: "graphite2"}
  174. bus.AddHandler("test", func(query *m.GetDataSourcesQuery) error {
  175. query.Result = []*m.DataSource{defaultDs, graphite2Ds}
  176. return nil
  177. })
  178. bus.AddHandler("test", func(query *m.GetDataSourceByNameQuery) error {
  179. if query.Name == defaultDs.Name {
  180. query.Result = defaultDs
  181. }
  182. if query.Name == graphite2Ds.Name {
  183. query.Result = graphite2Ds
  184. }
  185. return nil
  186. })
  187. alerts, err := extractor.GetAlerts()
  188. Convey("Get rules without error", func() {
  189. So(err, ShouldBeNil)
  190. })
  191. Convey("all properties have been set", func() {
  192. So(len(alerts), ShouldEqual, 2)
  193. for _, v := range alerts {
  194. So(v.DashboardId, ShouldEqual, 57)
  195. So(v.Name, ShouldNotBeEmpty)
  196. So(v.Description, ShouldNotBeEmpty)
  197. }
  198. Convey("should extract handler property", func() {
  199. So(alerts[0].Handler, ShouldEqual, 1)
  200. So(alerts[1].Handler, ShouldEqual, 0)
  201. })
  202. Convey("should extract frequency in seconds", func() {
  203. So(alerts[0].Frequency, ShouldEqual, 60)
  204. So(alerts[1].Frequency, ShouldEqual, 60)
  205. })
  206. Convey("should extract panel idc", func() {
  207. So(alerts[0].PanelId, ShouldEqual, 3)
  208. So(alerts[1].PanelId, ShouldEqual, 4)
  209. })
  210. Convey("should extract name and desc", func() {
  211. So(alerts[0].Name, ShouldEqual, "name1")
  212. So(alerts[0].Description, ShouldEqual, "desc1")
  213. So(alerts[1].Name, ShouldEqual, "name2")
  214. So(alerts[1].Description, ShouldEqual, "desc2")
  215. })
  216. })
  217. })
  218. })
  219. }