flamegraphTheme.tsx 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. import {
  2. makeColorMapByApplicationFrame,
  3. makeColorMapByFrequency,
  4. makeColorMapByLibrary,
  5. makeColorMapByRecursion,
  6. makeColorMapBySymbolName,
  7. makeColorMapBySystemFrame,
  8. makeColorMapBySystemVsApplicationFrame,
  9. makeStackToColor,
  10. } from 'sentry/utils/profiling/colors/utils';
  11. import {FlamegraphColorCodings} from 'sentry/utils/profiling/flamegraph/flamegraphStateProvider/reducers/flamegraphPreferences';
  12. import {FlamegraphFrame} from 'sentry/utils/profiling/flamegraphFrame';
  13. import {Frame} from 'sentry/utils/profiling/frame';
  14. import {darkTheme, lightTheme} from 'sentry/utils/theme';
  15. import {makeColorBucketTheme} from '../speedscope';
  16. const MONOSPACE_FONT = `ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono', 'Roboto Mono',
  17. 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro', 'Fira Mono', 'Droid Sans Mono',
  18. 'Courier New', monospace`;
  19. const FRAME_FONT = lightTheme.text.familyMono;
  20. // Luma chroma hue settings
  21. export interface LCH {
  22. C_0: number;
  23. C_d: number;
  24. L_0: number;
  25. L_d: number;
  26. }
  27. // Color can be rgb or rgba. I want to probably eliminate rgb and just use rgba, but we would be allocating 25% more memory,
  28. // and I'm not sure about the impact we'd need. There is a tradeoff between memory and runtime performance checks that I'll need to evaluate at some point.
  29. export type ColorChannels = [number, number, number] | [number, number, number, number];
  30. export type ColorMapFn = (
  31. frames: ReadonlyArray<FlamegraphFrame>,
  32. colorBucket: FlamegraphTheme['COLORS']['COLOR_BUCKET'],
  33. theme: FlamegraphTheme,
  34. sortByKey?: (a: FlamegraphFrame, b: FlamegraphFrame) => number
  35. ) => Map<FlamegraphFrame['frame']['key'], ColorChannels>;
  36. export interface FlamegraphTheme {
  37. // @TODO, most colors are defined as strings, which is a mistake as we loose a lot of functionality and impose constraints.
  38. // They should instead be defined as arrays of numbers so we can use them with glsl and avoid unnecessary parsing
  39. COLORS: {
  40. BAR_LABEL_FONT_COLOR: string;
  41. COLOR_BUCKET: (t: number) => ColorChannels;
  42. COLOR_MAPS: Record<FlamegraphColorCodings[number], ColorMapFn>;
  43. CURSOR_CROSSHAIR: string;
  44. DIFFERENTIAL_DECREASE: ColorChannels;
  45. DIFFERENTIAL_INCREASE: ColorChannels;
  46. FOCUSED_FRAME_BORDER_COLOR: string;
  47. FRAME_APPLICATION_COLOR: ColorChannels;
  48. FRAME_GRAYSCALE_COLOR: ColorChannels;
  49. FRAME_SYSTEM_COLOR: ColorChannels;
  50. GRID_FRAME_BACKGROUND_COLOR: string;
  51. GRID_LINE_COLOR: string;
  52. HIGHLIGHTED_LABEL_COLOR: ColorChannels;
  53. HOVERED_FRAME_BORDER_COLOR: string;
  54. LABEL_FONT_COLOR: string;
  55. MINIMAP_POSITION_OVERLAY_BORDER_COLOR: string;
  56. MINIMAP_POSITION_OVERLAY_COLOR: string;
  57. // Nice color picker for GLSL colors - https://keiwando.com/color-picker/
  58. SAMPLE_TICK_COLOR: ColorChannels;
  59. SEARCH_RESULT_FRAME_COLOR: string;
  60. SEARCH_RESULT_SPAN_COLOR: string;
  61. SELECTED_FRAME_BORDER_COLOR: string;
  62. SPAN_COLOR_BUCKET: (t: number) => ColorChannels;
  63. SPAN_FALLBACK_COLOR: [number, number, number, number];
  64. SPAN_FRAME_BORDER: string;
  65. SPAN_FRAME_LINE_PATTERN: string;
  66. SPAN_FRAME_LINE_PATTERN_BACKGROUND: string;
  67. STACK_TO_COLOR: (
  68. frames: ReadonlyArray<FlamegraphFrame>,
  69. colorMapFn: ColorMapFn,
  70. colorBucketFn: FlamegraphTheme['COLORS']['COLOR_BUCKET'],
  71. theme: FlamegraphTheme
  72. ) => {
  73. colorBuffer: Array<number>;
  74. colorMap: Map<Frame['key'], ColorChannels>;
  75. };
  76. UI_FRAME_COLOR_FROZEN: [number, number, number, number];
  77. UI_FRAME_COLOR_SLOW: [number, number, number, number];
  78. };
  79. FONTS: {
  80. FONT: string;
  81. FRAME_FONT: string;
  82. };
  83. SIZES: {
  84. BAR_FONT_SIZE: number;
  85. BAR_HEIGHT: number;
  86. BAR_PADDING: number;
  87. FLAMEGRAPH_DEPTH_OFFSET: number;
  88. GRID_LINE_WIDTH: number;
  89. HIGHLIGHTED_FRAME_BORDER_WIDTH;
  90. HOVERED_FRAME_BORDER_WIDTH: number;
  91. INTERNAL_SAMPLE_TICK_LINE_WIDTH: number;
  92. LABEL_FONT_PADDING: number;
  93. LABEL_FONT_SIZE: number;
  94. MAX_SPANS_HEIGHT: number;
  95. MINIMAP_HEIGHT: number;
  96. MINIMAP_POSITION_OVERLAY_BORDER_WIDTH: number;
  97. SPANS_BAR_HEIGHT: number;
  98. SPANS_DEPTH_OFFSET: number;
  99. SPANS_FONT_SIZE: number;
  100. TIMELINE_HEIGHT: number;
  101. TOOLTIP_FONT_SIZE: number;
  102. UI_FRAMES_HEIGHT: number;
  103. };
  104. }
  105. // Luma chroma hue settings for light theme
  106. export const LCH_LIGHT = {
  107. C_0: 0.25,
  108. C_d: 0.2,
  109. L_0: 0.8,
  110. L_d: 0.15,
  111. };
  112. // Luma chroma hue settings for dark theme
  113. export const LCH_DARK = {
  114. C_0: 0.2,
  115. C_d: 0.1,
  116. L_0: 0.2,
  117. L_d: 0.1,
  118. };
  119. const SPAN_LCH_LIGHT = {
  120. C_0: 0.3,
  121. C_d: 0.25,
  122. L_0: 0.8,
  123. L_d: 0.15,
  124. };
  125. const SPANS_LCH_DARK = {
  126. C_0: 0.3,
  127. C_d: 0.15,
  128. L_0: 0.2,
  129. L_d: 0.1,
  130. };
  131. const SIZES: FlamegraphTheme['SIZES'] = {
  132. BAR_FONT_SIZE: 11,
  133. BAR_HEIGHT: 20,
  134. BAR_PADDING: 4,
  135. FLAMEGRAPH_DEPTH_OFFSET: 12,
  136. HOVERED_FRAME_BORDER_WIDTH: 2,
  137. HIGHLIGHTED_FRAME_BORDER_WIDTH: 3,
  138. GRID_LINE_WIDTH: 2,
  139. INTERNAL_SAMPLE_TICK_LINE_WIDTH: 1,
  140. LABEL_FONT_PADDING: 6,
  141. LABEL_FONT_SIZE: 10,
  142. MINIMAP_HEIGHT: 100,
  143. MINIMAP_POSITION_OVERLAY_BORDER_WIDTH: 2,
  144. SPANS_BAR_HEIGHT: 20,
  145. SPANS_DEPTH_OFFSET: 3,
  146. SPANS_FONT_SIZE: 11,
  147. MAX_SPANS_HEIGHT: 160,
  148. TIMELINE_HEIGHT: 20,
  149. TOOLTIP_FONT_SIZE: 12,
  150. UI_FRAMES_HEIGHT: 60,
  151. };
  152. const FONTS: FlamegraphTheme['FONTS'] = {
  153. FONT: MONOSPACE_FONT,
  154. FRAME_FONT,
  155. };
  156. export const LightFlamegraphTheme: FlamegraphTheme = {
  157. SIZES,
  158. COLORS: {
  159. BAR_LABEL_FONT_COLOR: '#000',
  160. COLOR_BUCKET: makeColorBucketTheme(LCH_LIGHT),
  161. SPAN_COLOR_BUCKET: makeColorBucketTheme(SPAN_LCH_LIGHT, 140, 220),
  162. COLOR_MAPS: {
  163. 'by symbol name': makeColorMapBySymbolName,
  164. 'by system frame': makeColorMapBySystemFrame,
  165. 'by application frame': makeColorMapByApplicationFrame,
  166. 'by library': makeColorMapByLibrary,
  167. 'by recursion': makeColorMapByRecursion,
  168. 'by frequency': makeColorMapByFrequency,
  169. 'by system vs application frame': makeColorMapBySystemVsApplicationFrame,
  170. },
  171. CURSOR_CROSSHAIR: '#bbbbbb',
  172. DIFFERENTIAL_DECREASE: [0.309, 0.2058, 0.98],
  173. DIFFERENTIAL_INCREASE: [0.98, 0.2058, 0.4381],
  174. FOCUSED_FRAME_BORDER_COLOR: lightTheme.focus,
  175. FRAME_GRAYSCALE_COLOR: [0.5, 0.5, 0.6, 0.1],
  176. FRAME_APPLICATION_COLOR: [0.1, 0.1, 0.8, 0.2],
  177. FRAME_SYSTEM_COLOR: [0.7, 0.1, 0.1, 0.2],
  178. SPAN_FALLBACK_COLOR: [0, 0, 0, 0.1],
  179. GRID_FRAME_BACKGROUND_COLOR: 'rgb(250, 249, 251, 1)', // theme.backgroundSecondary
  180. GRID_LINE_COLOR: '#e5e7eb',
  181. HIGHLIGHTED_LABEL_COLOR: [240, 240, 0, 1],
  182. HOVERED_FRAME_BORDER_COLOR: 'rgba(0, 0, 0, 0.8)',
  183. LABEL_FONT_COLOR: '#1f233a',
  184. MINIMAP_POSITION_OVERLAY_BORDER_COLOR: 'rgba(0,0,0, 0.2)',
  185. MINIMAP_POSITION_OVERLAY_COLOR: 'rgba(0,0,0,0.1)',
  186. SAMPLE_TICK_COLOR: [255, 0, 0, 0.5],
  187. // Yellow 200
  188. UI_FRAME_COLOR_SLOW: [0.96, 0.69, 0.0, 0.55],
  189. // Red 200 but stronger opacity
  190. UI_FRAME_COLOR_FROZEN: [0.96, 0.329, 0.349, 0.8],
  191. SEARCH_RESULT_FRAME_COLOR: 'vec4(0.99, 0.70, 0.35, 1.0)',
  192. SEARCH_RESULT_SPAN_COLOR: '#fdb359',
  193. SELECTED_FRAME_BORDER_COLOR: lightTheme.blue400,
  194. SPAN_FRAME_LINE_PATTERN: '#dedae3',
  195. SPAN_FRAME_LINE_PATTERN_BACKGROUND: '#f4f2f7',
  196. SPAN_FRAME_BORDER: 'rgba(200, 200, 200, 1)',
  197. STACK_TO_COLOR: makeStackToColor([0, 0, 0, 0.035]),
  198. },
  199. FONTS,
  200. };
  201. export const DarkFlamegraphTheme: FlamegraphTheme = {
  202. SIZES,
  203. COLORS: {
  204. BAR_LABEL_FONT_COLOR: 'rgb(255 255 255 / 80%)',
  205. COLOR_BUCKET: makeColorBucketTheme(LCH_DARK),
  206. SPAN_COLOR_BUCKET: makeColorBucketTheme(SPANS_LCH_DARK, 140, 220),
  207. COLOR_MAPS: {
  208. 'by symbol name': makeColorMapBySymbolName,
  209. 'by system frame': makeColorMapBySystemFrame,
  210. 'by application frame': makeColorMapByApplicationFrame,
  211. 'by library': makeColorMapByLibrary,
  212. 'by recursion': makeColorMapByRecursion,
  213. 'by frequency': makeColorMapByFrequency,
  214. 'by system vs application frame': makeColorMapBySystemVsApplicationFrame,
  215. },
  216. CURSOR_CROSSHAIR: '#828285',
  217. DIFFERENTIAL_DECREASE: [0.309, 0.2058, 0.98],
  218. DIFFERENTIAL_INCREASE: [0.98, 0.2058, 0.4381],
  219. FOCUSED_FRAME_BORDER_COLOR: darkTheme.focus,
  220. FRAME_GRAYSCALE_COLOR: [0.5, 0.5, 0.5, 0.4],
  221. FRAME_APPLICATION_COLOR: [0.1, 0.1, 0.8, 0.4],
  222. FRAME_SYSTEM_COLOR: [0.7, 0.1, 0.1, 0.5],
  223. SPAN_FALLBACK_COLOR: [1, 1, 1, 0.3],
  224. GRID_FRAME_BACKGROUND_COLOR: 'rgb(26, 20, 31,1)',
  225. GRID_LINE_COLOR: '#222227',
  226. HIGHLIGHTED_LABEL_COLOR: [136, 50, 0, 1],
  227. HOVERED_FRAME_BORDER_COLOR: 'rgba(255, 255, 255, 0.8)',
  228. LABEL_FONT_COLOR: 'rgba(255, 255, 255, 0.8)',
  229. MINIMAP_POSITION_OVERLAY_BORDER_COLOR: 'rgba(255,255,255, 0.35)',
  230. MINIMAP_POSITION_OVERLAY_COLOR: 'rgba(255,255,255,0.1)',
  231. SAMPLE_TICK_COLOR: [255, 0, 0, 0.5],
  232. // Yellow 200
  233. UI_FRAME_COLOR_SLOW: [0.96, 0.69, 0.0, 0.6],
  234. // Red 200 but stronger opacity
  235. UI_FRAME_COLOR_FROZEN: [0.96, 0.329, 0.349, 0.5],
  236. SEARCH_RESULT_FRAME_COLOR: 'vec4(0.99, 0.70, 0.35, 0.7)',
  237. SPAN_FRAME_LINE_PATTERN: '#594b66',
  238. SPAN_FRAME_LINE_PATTERN_BACKGROUND: '#1a1724',
  239. SELECTED_FRAME_BORDER_COLOR: lightTheme.blue400,
  240. SEARCH_RESULT_SPAN_COLOR: '#b9834a',
  241. SPAN_FRAME_BORDER: '#57575b',
  242. STACK_TO_COLOR: makeStackToColor([1, 1, 1, 0.1]),
  243. },
  244. FONTS,
  245. };