common.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. from dataclasses import dataclass, field
  2. from enum import Enum
  3. from typing import Any, Dict, List, Optional
  4. from ray.util.annotations import DeveloperAPI
  5. @DeveloperAPI
  6. @dataclass
  7. class GridPos:
  8. x: int
  9. y: int
  10. w: int
  11. h: int
  12. GRAPH_TARGET_TEMPLATE = {
  13. "exemplar": True,
  14. "expr": "0",
  15. "interval": "",
  16. "legendFormat": "",
  17. "queryType": "randomWalk",
  18. "refId": "A",
  19. }
  20. HEATMAP_TARGET_TEMPLATE = {
  21. "format": "heatmap",
  22. "fullMetaSearch": False,
  23. "includeNullMetadata": True,
  24. "instant": False,
  25. "range": True,
  26. "useBackend": False,
  27. }
  28. HISTOGRAM_BAR_CHART_TARGET_TEMPLATE = {
  29. "exemplar": True,
  30. "format": "heatmap",
  31. "fullMetaSearch": False,
  32. "includeNullMetadata": True,
  33. "instant": True,
  34. "range": False,
  35. "useBackend": False,
  36. }
  37. @DeveloperAPI
  38. class TargetTemplate(Enum):
  39. GRAPH = GRAPH_TARGET_TEMPLATE
  40. HEATMAP = HEATMAP_TARGET_TEMPLATE
  41. HISTOGRAM_BAR_CHART = HISTOGRAM_BAR_CHART_TARGET_TEMPLATE
  42. @DeveloperAPI
  43. @dataclass
  44. class Target:
  45. """Defines a Grafana target (time-series query) within a panel.
  46. A panel will have one or more targets. By default, all targets are rendered as
  47. stacked area charts, with the exception of legend="MAX", which is rendered as
  48. a blue dotted line. Any legend="FINISHED|FAILED|DEAD|REMOVED" series will also be
  49. rendered hidden by default.
  50. Attributes:
  51. expr: The prometheus query to evaluate.
  52. legend: The legend string to format for each time-series.
  53. """
  54. expr: str
  55. legend: str
  56. template: Optional[TargetTemplate] = TargetTemplate.GRAPH
  57. HEATMAP_TEMPLATE = {
  58. "datasource": r"${datasource}",
  59. "description": "<Description>",
  60. "fieldConfig": {"defaults": {}, "overrides": []},
  61. "id": 12,
  62. "options": {
  63. "calculate": False,
  64. "cellGap": 1,
  65. "cellValues": {"unit": "none"},
  66. "color": {
  67. "exponent": 0.5,
  68. "fill": "dark-orange",
  69. "min": 0,
  70. "mode": "scheme",
  71. "reverse": False,
  72. "scale": "exponential",
  73. "scheme": "Spectral",
  74. "steps": 64,
  75. },
  76. "exemplars": {"color": "rgba(255,0,255,0.7)"},
  77. "filterValues": {"le": 1e-9},
  78. "legend": {"show": True},
  79. "rowsFrame": {"layout": "auto", "value": "Value"},
  80. "tooltip": {"mode": "single", "showColorScale": False, "yHistogram": True},
  81. "yAxis": {"axisPlacement": "left", "reverse": False, "unit": "none"},
  82. },
  83. "pluginVersion": "11.2.0",
  84. "targets": [],
  85. "title": "<Title>",
  86. "type": "heatmap",
  87. "yaxes": [
  88. {
  89. "$$hashKey": "object:628",
  90. "format": "units",
  91. "label": "",
  92. "logBase": 1,
  93. "max": None,
  94. "min": "0",
  95. "show": True,
  96. },
  97. {
  98. "$$hashKey": "object:629",
  99. "format": "short",
  100. "label": None,
  101. "logBase": 1,
  102. "max": None,
  103. "min": None,
  104. "show": True,
  105. },
  106. ],
  107. }
  108. GRAPH_PANEL_TEMPLATE = {
  109. "aliasColors": {},
  110. "bars": False,
  111. "dashLength": 10,
  112. "dashes": False,
  113. "datasource": r"${datasource}",
  114. "description": "<Description>",
  115. "fieldConfig": {"defaults": {}, "overrides": []},
  116. # Setting height and width is important here to ensure the default panel has some size to it.
  117. "gridPos": {"h": 8, "w": 12, "x": 0, "y": 0},
  118. "fill": 10,
  119. "fillGradient": 0,
  120. "hiddenSeries": False,
  121. "id": 26,
  122. "legend": {
  123. "alignAsTable": True,
  124. "avg": True,
  125. "current": True,
  126. "hideEmpty": False,
  127. "hideZero": True,
  128. "max": True,
  129. "min": False,
  130. "rightSide": False,
  131. "show": True,
  132. "sort": "current",
  133. "sortDesc": True,
  134. "total": False,
  135. "values": True,
  136. },
  137. "lines": True,
  138. "linewidth": 1,
  139. "nullPointMode": None,
  140. "options": {"alertThreshold": True},
  141. "percentage": False,
  142. "pluginVersion": "7.5.17",
  143. "pointradius": 2,
  144. "points": False,
  145. "renderer": "flot",
  146. # These series overrides are necessary to make the "MAX" and "MAX + PENDING" dotted lines
  147. # instead of stacked filled areas.
  148. "seriesOverrides": [
  149. {
  150. "$$hashKey": "object:2987",
  151. "alias": "MAX",
  152. "dashes": True,
  153. "color": "#1F60C4",
  154. "fill": 0,
  155. "stack": False,
  156. },
  157. {
  158. "$$hashKey": "object:78",
  159. "alias": "/FINISHED|FAILED|DEAD|REMOVED|Failed Nodes:/",
  160. "hiddenSeries": True,
  161. },
  162. {
  163. "$$hashKey": "object:2987",
  164. "alias": "MAX + PENDING",
  165. "dashes": True,
  166. "color": "#777777",
  167. "fill": 0,
  168. "stack": False,
  169. },
  170. ],
  171. "spaceLength": 10,
  172. "stack": True,
  173. "steppedLine": False,
  174. "targets": [],
  175. "thresholds": [],
  176. "timeFrom": None,
  177. "timeRegions": [],
  178. "timeShift": None,
  179. "title": "<Title>",
  180. "tooltip": {"shared": True, "sort": 0, "value_type": "individual"},
  181. "type": "graph",
  182. "xaxis": {
  183. "buckets": None,
  184. "mode": "time",
  185. "name": None,
  186. "show": True,
  187. "values": [],
  188. },
  189. "yaxes": [
  190. {
  191. "$$hashKey": "object:628",
  192. "format": "units",
  193. "label": "",
  194. "logBase": 1,
  195. "max": None,
  196. "min": "0",
  197. "show": True,
  198. },
  199. {
  200. "$$hashKey": "object:629",
  201. "format": "short",
  202. "label": None,
  203. "logBase": 1,
  204. "max": None,
  205. "min": None,
  206. "show": True,
  207. },
  208. ],
  209. "yaxis": {"align": False, "alignLevel": None},
  210. }
  211. STAT_PANEL_TEMPLATE = {
  212. "datasource": r"${datasource}",
  213. "fieldConfig": {
  214. "defaults": {
  215. "color": {"mode": "thresholds"},
  216. "mappings": [],
  217. "min": 0,
  218. "thresholds": {
  219. "mode": "percentage",
  220. "steps": [
  221. {"color": "super-light-yellow", "value": None},
  222. {"color": "super-light-green", "value": 50},
  223. {"color": "green", "value": 100},
  224. ],
  225. },
  226. "unit": "short",
  227. },
  228. "overrides": [],
  229. },
  230. "id": 78,
  231. "options": {
  232. "colorMode": "value",
  233. "graphMode": "area",
  234. "justifyMode": "auto",
  235. "orientation": "auto",
  236. "reduceOptions": {"calcs": ["lastNotNull"], "fields": "", "values": False},
  237. "text": {},
  238. "textMode": "auto",
  239. },
  240. "pluginVersion": "7.5.17",
  241. "targets": [],
  242. "timeFrom": None,
  243. "timeShift": None,
  244. "title": "<Title>",
  245. "type": "stat",
  246. "yaxes": [
  247. {
  248. "$$hashKey": "object:628",
  249. "format": "Tokens",
  250. "label": "",
  251. "logBase": 1,
  252. "max": None,
  253. "min": "0",
  254. "show": True,
  255. },
  256. {
  257. "$$hashKey": "object:629",
  258. "format": "short",
  259. "label": None,
  260. "logBase": 1,
  261. "max": None,
  262. "min": None,
  263. "show": True,
  264. },
  265. ],
  266. }
  267. GAUGE_PANEL_TEMPLATE = {
  268. "datasource": r"${datasource}",
  269. "fieldConfig": {
  270. "defaults": {
  271. "color": {"mode": "continuous-YlBl"},
  272. "mappings": [],
  273. "thresholds": {
  274. "mode": "percentage",
  275. "steps": [{"color": "rgb(230, 230, 230)", "value": None}],
  276. },
  277. "unit": "short",
  278. },
  279. "overrides": [],
  280. },
  281. "id": 10,
  282. "options": {
  283. "reduceOptions": {"calcs": ["lastNotNull"], "fields": "", "values": False},
  284. "showThresholdLabels": False,
  285. "showThresholdMarkers": False,
  286. "text": {"titleSize": 12},
  287. },
  288. "pluginVersion": "7.5.17",
  289. "targets": [],
  290. "title": "<Title>",
  291. "type": "gauge",
  292. "yaxes": [
  293. {
  294. "$$hashKey": "object:628",
  295. "format": "Tokens",
  296. "label": "",
  297. "logBase": 1,
  298. "max": None,
  299. "min": "0",
  300. "show": True,
  301. },
  302. {
  303. "$$hashKey": "object:629",
  304. "format": "short",
  305. "label": None,
  306. "logBase": 1,
  307. "max": None,
  308. "min": None,
  309. "show": True,
  310. },
  311. ],
  312. }
  313. PIE_CHART_TEMPLATE = {
  314. "datasource": r"${datasource}",
  315. "description": "<Description>",
  316. "fieldConfig": {"defaults": {}, "overrides": []},
  317. "id": 26,
  318. "options": {
  319. "displayLabels": [],
  320. "legend": {
  321. "displayMode": "table",
  322. "placement": "right",
  323. "values": ["percent", "value"],
  324. },
  325. "pieType": "pie",
  326. "reduceOptions": {"calcs": ["lastNotNull"], "fields": "", "values": False},
  327. "text": {},
  328. },
  329. "pluginVersion": "7.5.17",
  330. "targets": [],
  331. "timeFrom": None,
  332. "timeShift": None,
  333. "title": "<Title>",
  334. "type": "piechart",
  335. "yaxes": [
  336. {
  337. "$$hashKey": "object:628",
  338. "format": "units",
  339. "label": "",
  340. "logBase": 1,
  341. "max": None,
  342. "min": "0",
  343. "show": True,
  344. },
  345. {
  346. "$$hashKey": "object:629",
  347. "format": "short",
  348. "label": None,
  349. "logBase": 1,
  350. "max": None,
  351. "min": None,
  352. "show": True,
  353. },
  354. ],
  355. }
  356. BAR_CHART_PANEL_TEMPLATE = {
  357. "aliasColors": {},
  358. "dashLength": 10,
  359. "dashes": False,
  360. "datasource": r"${datasource}",
  361. "description": "<Description>",
  362. "fieldConfig": {"defaults": {}, "overrides": []},
  363. # Setting height and width is important here to ensure the default panel has some size to it.
  364. "gridPos": {"h": 8, "w": 12, "x": 0, "y": 0},
  365. "hiddenSeries": False,
  366. "id": 26,
  367. "legend": {
  368. "alignAsTable": True,
  369. "avg": False,
  370. "current": True,
  371. "hideEmpty": False,
  372. "hideZero": True,
  373. "max": False,
  374. "min": False,
  375. "rightSide": False,
  376. "show": False,
  377. "sort": "current",
  378. "sortDesc": True,
  379. "total": False,
  380. "values": True,
  381. },
  382. "lines": False,
  383. "linewidth": 1,
  384. "bars": True,
  385. "nullPointMode": None,
  386. "options": {
  387. "alertThreshold": True,
  388. "legend": {
  389. "showLegend": False,
  390. "displayMode": "table",
  391. "placement": "bottom",
  392. },
  393. },
  394. "percentage": False,
  395. "pluginVersion": "7.5.17",
  396. "pointradius": 2,
  397. "points": False,
  398. "renderer": "flot",
  399. "spaceLength": 10,
  400. "stack": True,
  401. "steppedLine": False,
  402. "targets": [],
  403. "thresholds": [],
  404. "timeFrom": None,
  405. "timeRegions": [],
  406. "timeShift": None,
  407. "title": "<Title>",
  408. "tooltip": {"shared": True, "sort": 0, "value_type": "individual"},
  409. "type": "graph",
  410. "xaxis": {
  411. "buckets": None,
  412. "mode": "series",
  413. "name": None,
  414. "show": True,
  415. "values": [
  416. "total",
  417. ],
  418. },
  419. "yaxes": [
  420. {
  421. "$$hashKey": "object:628",
  422. "format": "units",
  423. "label": "",
  424. "logBase": 1,
  425. "max": None,
  426. "min": "0",
  427. "show": True,
  428. },
  429. {
  430. "$$hashKey": "object:629",
  431. "format": "short",
  432. "label": None,
  433. "logBase": 1,
  434. "max": None,
  435. "min": None,
  436. "show": True,
  437. },
  438. ],
  439. "yaxis": {"align": False, "alignLevel": None},
  440. }
  441. TABLE_PANEL_TEMPLATE = {
  442. "datasource": r"${datasource}",
  443. "description": "<Description>",
  444. "fieldConfig": {
  445. "defaults": {
  446. "custom": {
  447. "align": "auto",
  448. "displayMode": "auto",
  449. },
  450. "mappings": [],
  451. },
  452. "overrides": [],
  453. },
  454. "gridPos": {"h": 8, "w": 12, "x": 0, "y": 0},
  455. "id": 26,
  456. "options": {
  457. "showHeader": True,
  458. "footer": {
  459. "show": False,
  460. "reducer": ["sum"],
  461. "fields": "",
  462. },
  463. },
  464. "pluginVersion": "7.5.17",
  465. "targets": [],
  466. "title": "<Title>",
  467. "type": "table",
  468. "transformations": [{"id": "organize", "options": {}}],
  469. }
  470. @DeveloperAPI
  471. class PanelTemplate(Enum):
  472. GRAPH = GRAPH_PANEL_TEMPLATE
  473. HEATMAP = HEATMAP_TEMPLATE
  474. PIE_CHART = PIE_CHART_TEMPLATE
  475. STAT = STAT_PANEL_TEMPLATE
  476. GAUGE = GAUGE_PANEL_TEMPLATE
  477. BAR_CHART = BAR_CHART_PANEL_TEMPLATE
  478. TABLE = TABLE_PANEL_TEMPLATE
  479. @DeveloperAPI
  480. @dataclass
  481. class Panel:
  482. """Defines a Grafana panel (graph) for the Ray dashboard page.
  483. A panel contains one or more targets (time-series queries).
  484. Attributes:
  485. title: Short name of the graph. Note: please keep this in sync with the title
  486. definitions in Metrics.tsx.
  487. description: Long form description of the graph.
  488. id: Integer id used to reference the graph from Metrics.tsx.
  489. unit: The unit to display on the y-axis of the graph.
  490. targets: List of query targets.
  491. fill: Whether or not the graph will be filled by a color.
  492. stack: Whether or not the lines in the graph will be stacked.
  493. linewidth: Width of the lines in the graph.
  494. grid_pos: Grid position of the panel.
  495. template: The panel template to use.
  496. hideXAxis: Whether to hide the x-axis.
  497. thresholds: Custom threshold configuration for stat/gauge panels.
  498. Example: [
  499. {"color": "green", "value": None},
  500. {"color": "yellow", "value": 70},
  501. {"color": "red", "value": 90}
  502. ]
  503. value_mappings: Value mappings for displaying text instead of numbers.
  504. Used for status panels.
  505. color_mode: Color mode for stat panels ("value", "background", "none").
  506. legend_mode: Legend display mode ("list", "table", "hidden").
  507. min_val: Minimum value for gauge/graph y-axis.
  508. max_val: Maximum value for gauge/graph y-axis.
  509. reduce_calc: Reduce calculation method for stat panels (default: "lastNotNull").
  510. heatmap_color_scheme: Color scheme for heatmap panels (e.g., "Spectral", "RdYlGn").
  511. heatmap_color_reverse: Whether to reverse the heatmap color scheme.
  512. heatmap_yaxis_label: Y-axis label for heatmap panels.
  513. """
  514. title: str
  515. description: str
  516. id: int
  517. unit: str
  518. targets: List[Target]
  519. fill: int = 10
  520. stack: bool = True
  521. linewidth: int = 1
  522. grid_pos: Optional[GridPos] = None
  523. template: Optional[PanelTemplate] = PanelTemplate.GRAPH
  524. hideXAxis: bool = False
  525. thresholds: Optional[List[Dict[str, Any]]] = None
  526. value_mappings: Optional[List[Dict[str, Any]]] = None
  527. color_mode: Optional[str] = None
  528. legend_mode: Optional[str] = None
  529. min_val: Optional[float] = None
  530. max_val: Optional[float] = None
  531. reduce_calc: Optional[str] = None
  532. heatmap_color_scheme: Optional[str] = None
  533. heatmap_color_reverse: Optional[bool] = None
  534. heatmap_yaxis_label: Optional[str] = None
  535. @DeveloperAPI
  536. @dataclass
  537. class Row:
  538. """Defines a Grafana row that can contain multiple panels.
  539. Attributes:
  540. title: The title of the row
  541. panels: List of panels contained in this row
  542. collapsed: Whether the row should be collapsed by default
  543. """
  544. title: str
  545. id: int
  546. panels: List[Panel]
  547. collapsed: bool = False
  548. @DeveloperAPI
  549. @dataclass
  550. class DashboardConfig:
  551. # This dashboard name is an internal key used to determine which env vars
  552. # to check for customization
  553. name: str
  554. # The uid of the dashboard json if not overridden by a user
  555. default_uid: str
  556. # The global filters applied to all graphs in this dashboard. Users can
  557. # add additional global_filters on top of this.
  558. standard_global_filters: List[str]
  559. base_json_file_name: str
  560. # Panels can be specified in `panels`, or nested within `rows`.
  561. # If both are specified, panels will be rendered before rows.
  562. panels: List[Panel] = field(default_factory=list)
  563. rows: List[Row] = field(default_factory=list)
  564. def __post_init__(self):
  565. if not self.panels and not self.rows:
  566. raise ValueError("At least one of panels or rows must be specified")