You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

main.go 9.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. package main
  2. import (
  3. "database/sql"
  4. "flag"
  5. "fmt"
  6. _ "github.com/mattn/go-sqlite3"
  7. "github.com/prometheus/client_golang/prometheus"
  8. "github.com/prometheus/client_golang/prometheus/promauto"
  9. "github.com/prometheus/client_golang/prometheus/promhttp"
  10. "math/rand"
  11. "os"
  12. "path/filepath"
  13. "strconv"
  14. "strings"
  15. "log"
  16. "net/http"
  17. "time"
  18. )
  19. var addr = flag.String("listen-address", ":7070", "The address to listen on for HTTP requests.")
  20. var metrics = []struct {
  21. name string
  22. label string
  23. note string
  24. labelValues string
  25. value float64
  26. }{
  27. {"metric1", "method,handler", "This is metric1", "a, b", 0},
  28. {"metric2", "method,handler", "This is metric2", "a, b", 0},
  29. {"Recall", "model_name", "Model Recall", "a", 0},
  30. {"Precision", "model_name", "Model Precision", "b", 0},
  31. }
  32. func recordTaskNumM(db *sql.DB) {
  33. go func() {
  34. for {
  35. rows, err := db.Query("SELECT a.id, a.name, a.task_num, b.task_attr FROM ll_task_grp as a left join ll_tasks as b where a.id=b.id;")
  36. if err != nil {
  37. fmt.Println(err)
  38. }
  39. for rows.Next() {
  40. var id int
  41. var name string
  42. var taskNum int
  43. var attr string
  44. err = rows.Scan(&id, &name, &taskNum, &attr)
  45. g, err := opsTaskTaskNum.GetMetricWithLabelValues(strconv.Itoa(id), name, attr)
  46. if err == nil {
  47. g.Set(float64(taskNum))
  48. }
  49. }
  50. time.Sleep(1 * time.Second)
  51. }
  52. }()
  53. }
  54. func recordTaskSampleMStatusM(db *sql.DB) {
  55. go func() {
  56. for {
  57. rows, err := db.Query("SELECT id, name, deploy, sample_num, task_num FROM ll_task_grp")
  58. if err != nil {
  59. fmt.Println(err)
  60. }
  61. for rows.Next() {
  62. var id int
  63. var name string
  64. var deploy bool
  65. var sampleNum int
  66. var taskNum int
  67. err = rows.Scan(&id, &name, &deploy, &sampleNum, &taskNum)
  68. g, err := opsTaskSampleNum.GetMetricWithLabelValues(strconv.Itoa(id), name)
  69. if err == nil {
  70. g.Set(float64(sampleNum))
  71. }
  72. g, err = opsDeployStatus.GetMetricWithLabelValues(strconv.Itoa(id), name)
  73. if err == nil {
  74. if deploy {
  75. g.Set(1)
  76. } else {
  77. g.Set(0)
  78. }
  79. }
  80. }
  81. time.Sleep(1 * time.Second)
  82. }
  83. }()
  84. }
  85. func recordKnownTasks(db *sql.DB) {
  86. go func() {
  87. for {
  88. rows, err := db.Query("SELECT count(*) as c from ll_task_models where is_current = 1")
  89. if err != nil {
  90. fmt.Println(err)
  91. }
  92. for rows.Next() {
  93. var c int
  94. err = rows.Scan(&c)
  95. g, err := opsKnowTaskNum.GetMetricWithLabelValues()
  96. if err == nil {
  97. g.Set(float64(c))
  98. }
  99. }
  100. time.Sleep(1 * time.Second)
  101. }
  102. }()
  103. }
  104. func recordTaskStatus(db *sql.DB) {
  105. go func() {
  106. for {
  107. rows, err := db.Query("SELECT task_id, model_url, is_current as c from ll_task_models")
  108. if err != nil {
  109. fmt.Println(err)
  110. }
  111. for rows.Next() {
  112. var taskId int
  113. var modelUrl string
  114. var isCurrent bool
  115. err = rows.Scan(&taskId, &modelUrl, &isCurrent)
  116. g, err := opsTaskStatus.GetMetricWithLabelValues(strconv.Itoa(taskId), modelUrl)
  117. if err == nil {
  118. if isCurrent {
  119. g.Set(1)
  120. } else {
  121. g.Set(0)
  122. }
  123. }
  124. }
  125. time.Sleep(1 * time.Second)
  126. }
  127. }()
  128. }
  129. func recordTaskRelationShip(db *sql.DB) {
  130. go func() {
  131. for {
  132. rows, err := db.Query("select grp_id, task_id, transfer_radio from ll_task_relation")
  133. if err != nil {
  134. fmt.Println(err)
  135. }
  136. for rows.Next() {
  137. var grpId int
  138. var taskId int
  139. var transferRatio float64
  140. err = rows.Scan(&grpId, &taskId, &transferRatio)
  141. g, err := opsTaskRelationShip.GetMetricWithLabelValues(strconv.Itoa(grpId), strconv.Itoa(taskId))
  142. if err == nil {
  143. g.Set(transferRatio)
  144. }
  145. }
  146. time.Sleep(1 * time.Second)
  147. }
  148. }()
  149. }
  150. func customMetrics(db *sql.DB, registry *prometheus.Registry) {
  151. // mock
  152. sql := "insert into metric (name, label, note, last_time) values (?, ?, ?, time('now'))"
  153. rows, err := db.Query("select count(*) from metric")
  154. if err != nil {
  155. fmt.Println(err)
  156. }
  157. mock := false
  158. for rows.Next() {
  159. var count int
  160. err = rows.Scan(&count)
  161. if err != nil {
  162. fmt.Println(err)
  163. }
  164. mock = count == 0
  165. }
  166. if mock {
  167. for i, metric := range metrics {
  168. _, err := db.Exec(sql, metric.name, metric.label, metric.note)
  169. if err != nil {
  170. fmt.Println(err)
  171. }
  172. _, err = db.Exec("insert into metric_value (metric_id, label_value, value, last_time) values (?, ?, ?, time('now'))",
  173. i, metric.labelValues, metric.value)
  174. if err != nil {
  175. fmt.Println(err)
  176. }
  177. }
  178. mockV := 1.0
  179. go func() {
  180. for {
  181. _, err := db.Exec("update metric_value set value=?", mockV)
  182. if err != nil {
  183. fmt.Println(err)
  184. }
  185. mockV = rand.Float64()
  186. time.Sleep(time.Second)
  187. }
  188. }()
  189. }
  190. // register metrics
  191. registeredMetrics := make([]*prometheus.GaugeVec, 0, 4)
  192. rows, err = db.Query("select name, label, note from metric order by id asc")
  193. if err != nil {
  194. fmt.Println(err)
  195. }
  196. for rows.Next() {
  197. var name string
  198. var label string
  199. var note string
  200. err = rows.Scan(&name, &label, &note)
  201. labels := strings.Split(label, ",")
  202. for i := range labels {
  203. labels[i] = strings.TrimSpace(labels[i])
  204. }
  205. met := promauto.NewGaugeVec(prometheus.GaugeOpts{
  206. Name: name,
  207. Help: note,
  208. }, labels)
  209. registry.MustRegister(met)
  210. registeredMetrics = append(registeredMetrics, met)
  211. }
  212. go func() {
  213. for {
  214. rows, err := db.Query("select metric_id, label_value, `value` from metric_value")
  215. if err != nil {
  216. fmt.Println(err)
  217. }
  218. for rows.Next() {
  219. var metricId int
  220. var labelValue string
  221. var value float64
  222. err = rows.Scan(&metricId, &labelValue, &value)
  223. labelValues := strings.Split(labelValue, ",")
  224. for i, _ := range labelValues {
  225. labelValues[i] = strings.TrimSpace(labelValues[i])
  226. }
  227. if len(registeredMetrics) <= metricId || registeredMetrics[metricId] == nil {
  228. continue
  229. }
  230. g, err := registeredMetrics[metricId].GetMetricWithLabelValues(labelValues...)
  231. if err == nil {
  232. g.Set(value)
  233. }
  234. }
  235. time.Sleep(time.Second)
  236. }
  237. }()
  238. }
  239. func fileScanner(p string, suffix string) {
  240. go func() {
  241. for {
  242. num := 0
  243. root := p
  244. err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
  245. if strings.HasSuffix(path, suffix) {
  246. num += 1
  247. }
  248. return nil
  249. })
  250. if err != nil {
  251. println(err)
  252. }
  253. g, err := opsFilesSuffixNum.GetMetricWithLabelValues()
  254. if err == nil {
  255. g.Set(float64(num))
  256. }
  257. num = 0
  258. time.Sleep(time.Second)
  259. }
  260. }()
  261. }
  262. var (
  263. // task metrics
  264. opsKnowTaskNum = promauto.NewGaugeVec(prometheus.GaugeOpts{
  265. Name: "know_task_num",
  266. Help: "Number of known tasks in the knowledge base",
  267. }, []string{})
  268. opsTaskSampleNum = promauto.NewGaugeVec(prometheus.GaugeOpts{
  269. Name: "task_sample_num",
  270. Help: "The total number of samples in task",
  271. }, []string{"id", "name"})
  272. opsTaskTaskNum = promauto.NewGaugeVec(prometheus.GaugeOpts{
  273. Name: "task_num",
  274. Help: "The total number of tasks",
  275. }, []string{"id", "name", "attr"})
  276. opsTaskRelationShip = promauto.NewGaugeVec(prometheus.GaugeOpts{
  277. Name: "task_relation_ship",
  278. Help: "Migration relationship between tasks",
  279. }, []string{"grp_id", "task_id"})
  280. opsTaskStatus = promauto.NewGaugeVec(prometheus.GaugeOpts{
  281. Name: "task_status",
  282. Help: "Whether the task can be deployed",
  283. }, []string{"task_id", "model_url"})
  284. opsDeployStatus = promauto.NewGaugeVec(prometheus.GaugeOpts{
  285. Name: "deploy_status",
  286. Help: "Enum(Waiting, OK, NotOK)",
  287. }, []string{"id", "name"})
  288. opsFilesSuffixNum = promauto.NewGaugeVec(prometheus.GaugeOpts{
  289. Name: "files_with_suffix_num",
  290. Help: "The number of files with suffix",
  291. }, []string{})
  292. )
  293. func main() {
  294. var scannerPath string
  295. var scannerSuffix string
  296. flag.StringVar(&scannerPath, "scanner-path", "-", "file scanner path")
  297. flag.StringVar(&scannerSuffix, "scanner-suffix", "", "file scanner suffix")
  298. flag.Parse()
  299. if scannerPath != "-" {
  300. fileScanner(scannerPath, scannerSuffix)
  301. }
  302. dbSrc := "kb.sqlite3"
  303. db, err := sql.Open("sqlite3", dbSrc)
  304. if err != nil {
  305. fmt.Printf("Can't open %s\n", dbSrc)
  306. return
  307. }
  308. dropTableMetric := "drop table metric"
  309. dropTableMetricValue := "drop table metric_value"
  310. _, err = db.Exec(dropTableMetric)
  311. if err != nil {
  312. println(err)
  313. }
  314. _, err = db.Exec(dropTableMetricValue)
  315. if err != nil {
  316. println(err)
  317. }
  318. createTableMetric := "create table if not exists metric(id int primary key, `name` text, label text, note text, last_time timestamp)"
  319. createTableMetricValue := "create table if not exists metric_value(id int primary key, metric_id int, label_value text, `value` float, last_time timestamp)"
  320. _, err = db.Exec(createTableMetric)
  321. if err != nil {
  322. println(err)
  323. }
  324. _, err = db.Exec(createTableMetricValue)
  325. if err != nil {
  326. println(err)
  327. }
  328. // Create a new registry.
  329. reg := prometheus.NewRegistry()
  330. recordTaskNumM(db)
  331. recordTaskSampleMStatusM(db)
  332. recordKnownTasks(db)
  333. recordTaskRelationShip(db)
  334. recordTaskStatus(db)
  335. customMetrics(db, reg)
  336. // Add Go module build info.
  337. reg.MustRegister(opsKnowTaskNum)
  338. reg.MustRegister(opsTaskSampleNum)
  339. reg.MustRegister(opsTaskTaskNum)
  340. reg.MustRegister(opsTaskRelationShip)
  341. reg.MustRegister(opsTaskStatus)
  342. reg.MustRegister(opsDeployStatus)
  343. reg.MustRegister(opsFilesSuffixNum)
  344. // Expose the registered metrics via HTTP.
  345. http.Handle("/metrics", promhttp.HandlerFor(
  346. reg,
  347. promhttp.HandlerOpts{
  348. // Opt into OpenMetrics to support exemplars.
  349. EnableOpenMetrics: true,
  350. },
  351. ))
  352. log.Fatal(http.ListenAndServe(*addr, nil))
  353. }