renderHeadCell.tsx 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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?:
  18. | QueryParameterNames.ENDPOINTS_SORT
  19. | QueryParameterNames.SPANS_SORT
  20. | typeof DEFAULT_SORT_PARAMETER_NAME;
  21. };
  22. const DEFAULT_SORT_PARAMETER_NAME = 'sort';
  23. const {SPAN_SELF_TIME, HTTP_RESPONSE_CONTENT_LENGTH} = SpanMetricsField;
  24. const {TIME_SPENT_PERCENTAGE, SPS, SPM, HTTP_ERROR_COUNT} = SpanFunction;
  25. export const SORTABLE_FIELDS = new Set([
  26. `avg(${SPAN_SELF_TIME})`,
  27. `p95(${SPAN_SELF_TIME})`,
  28. `p75(transaction.duration)`,
  29. `transaction.duration`,
  30. 'transaction',
  31. `count()`,
  32. `${SPS}()`,
  33. `${SPM}()`,
  34. `${TIME_SPENT_PERCENTAGE}()`,
  35. `${HTTP_ERROR_COUNT}()`,
  36. `avg(${HTTP_RESPONSE_CONTENT_LENGTH})`,
  37. ]);
  38. export const renderHeadCell = ({column, location, sort, sortParameterName}: Options) => {
  39. const {key, name} = column;
  40. const alignment = getAlignment(key);
  41. let newSortDirection: Sort['kind'] = 'desc';
  42. if (sort?.field === column.key) {
  43. if (sort.kind === 'desc') {
  44. newSortDirection = 'asc';
  45. }
  46. }
  47. const newSort = `${newSortDirection === 'desc' ? '-' : ''}${key}`;
  48. return (
  49. <SortLink
  50. align={alignment}
  51. canSort={Boolean(location && sort && SORTABLE_FIELDS.has(key))}
  52. direction={sort?.field === column.key ? sort.kind : undefined}
  53. title={name}
  54. generateSortLink={() => {
  55. return {
  56. ...location,
  57. query: {
  58. ...location?.query,
  59. [sortParameterName ?? DEFAULT_SORT_PARAMETER_NAME]: newSort,
  60. },
  61. };
  62. }}
  63. />
  64. );
  65. };
  66. export const getAlignment = (key: string): Alignments => {
  67. const result = parseFunction(key);
  68. if (result) {
  69. const outputType = aggregateFunctionOutputType(result.name, result.arguments[0]);
  70. if (outputType) {
  71. return fieldAlignment(key, outputType);
  72. }
  73. }
  74. return 'left';
  75. };