renderHeadCell.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import type {Location} from 'history';
  2. import type {GridColumnHeader} from 'sentry/components/gridEditable';
  3. import type {Alignments} from 'sentry/components/gridEditable/sortLink';
  4. import SortLink from 'sentry/components/gridEditable/sortLink';
  5. import type {Sort} from 'sentry/utils/discover/fields';
  6. import {
  7. aggregateFunctionOutputType,
  8. fieldAlignment,
  9. parseFunction,
  10. } from 'sentry/utils/discover/fields';
  11. import {SpanFunction, SpanMetricsField} from 'sentry/views/starfish/types';
  12. import type {QueryParameterNames} from 'sentry/views/starfish/views/queryParameters';
  13. type Options = {
  14. column: GridColumnHeader<string>;
  15. location?: Location;
  16. sort?: Sort;
  17. sortParameterName?: QueryParameterNames | typeof DEFAULT_SORT_PARAMETER_NAME;
  18. };
  19. const DEFAULT_SORT_PARAMETER_NAME = 'sort';
  20. const {SPAN_SELF_TIME, HTTP_RESPONSE_CONTENT_LENGTH} = SpanMetricsField;
  21. const {TIME_SPENT_PERCENTAGE, SPS, SPM, HTTP_ERROR_COUNT, HTTP_RESPONSE_RATE} =
  22. SpanFunction;
  23. export const SORTABLE_FIELDS = new Set([
  24. `avg(${SPAN_SELF_TIME})`,
  25. `p95(${SPAN_SELF_TIME})`,
  26. `p75(transaction.duration)`,
  27. `transaction.duration`,
  28. 'transaction',
  29. `count()`,
  30. `${SPS}()`,
  31. `${SPM}()`,
  32. `${TIME_SPENT_PERCENTAGE}()`,
  33. `${HTTP_ERROR_COUNT}()`,
  34. `${HTTP_RESPONSE_RATE}(2)`,
  35. `${HTTP_RESPONSE_RATE}(4)`,
  36. `${HTTP_RESPONSE_RATE}(5)`,
  37. `avg(${HTTP_RESPONSE_CONTENT_LENGTH})`,
  38. ]);
  39. export const renderHeadCell = ({column, location, sort, sortParameterName}: Options) => {
  40. const {key, name} = column;
  41. const alignment = getAlignment(key);
  42. let newSortDirection: Sort['kind'] = 'desc';
  43. if (sort?.field === column.key) {
  44. if (sort.kind === 'desc') {
  45. newSortDirection = 'asc';
  46. }
  47. }
  48. const newSort = `${newSortDirection === 'desc' ? '-' : ''}${key}`;
  49. return (
  50. <SortLink
  51. align={alignment}
  52. canSort={Boolean(location && sort && SORTABLE_FIELDS.has(key))}
  53. direction={sort?.field === column.key ? sort.kind : undefined}
  54. title={name}
  55. generateSortLink={() => {
  56. return {
  57. ...location,
  58. query: {
  59. ...location?.query,
  60. [sortParameterName ?? DEFAULT_SORT_PARAMETER_NAME]: newSort,
  61. },
  62. };
  63. }}
  64. />
  65. );
  66. };
  67. export const getAlignment = (key: string): Alignments => {
  68. const result = parseFunction(key);
  69. if (result) {
  70. const outputType = aggregateFunctionOutputType(result.name, result.arguments[0]);
  71. if (outputType) {
  72. return fieldAlignment(key, outputType);
  73. }
  74. }
  75. return 'left';
  76. };