zeroFillSeries.tsx 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import moment from 'moment';
  2. import {Series, SeriesDataUnit} from 'sentry/types/echarts';
  3. export function zeroFillSeries(
  4. series: Series,
  5. interval: moment.Duration,
  6. startTime?: moment.Moment,
  7. endTime?: moment.Moment
  8. ): Series {
  9. if (!series?.data?.length) {
  10. return series;
  11. }
  12. const firstDatum = series.data[0];
  13. const lastDatum = series.data[series.data.length - 1];
  14. const dateFormat = moment(firstDatum.name).creationData().format?.toString();
  15. if (!dateFormat) {
  16. return series;
  17. }
  18. const newData: SeriesDataUnit[] = [];
  19. const startTimeNearestInterval = startTime && roundUpToNearest12HourInterval(startTime);
  20. const endTimeNearestInterval = endTime && roundDownToNearest12HourInterval(endTime);
  21. const seriesData = [
  22. ...(startTimeNearestInterval &&
  23. startTimeNearestInterval.diff(moment(firstDatum.name)) < 0
  24. ? [{value: 0, name: startTimeNearestInterval.format(dateFormat)}]
  25. : []),
  26. ...series.data,
  27. ...(endTimeNearestInterval && endTimeNearestInterval.diff(moment(lastDatum.name)) > 0
  28. ? [{value: 0, name: endTimeNearestInterval.format(dateFormat)}]
  29. : []),
  30. ];
  31. let currentDatum, nextDatum, lastSeenDate, nextDate, diff;
  32. for (let index = 0; index < seriesData.length - 1; index++) {
  33. // Push the first datapoint
  34. if (index === 0) {
  35. newData.push({
  36. ...seriesData[index],
  37. name: moment(seriesData[index].name).format(dateFormat),
  38. });
  39. }
  40. currentDatum = seriesData[index];
  41. nextDatum = seriesData[index + 1];
  42. lastSeenDate = moment(currentDatum.name);
  43. nextDate = moment(nextDatum.name);
  44. diff = moment.duration(nextDate.diff(lastSeenDate));
  45. while (diff.asMilliseconds() > interval.asMilliseconds()) {
  46. // The gap between the two datapoints is more than the intended interval!
  47. // We need to fill 0s
  48. lastSeenDate.add(interval);
  49. newData.push({
  50. value: 0,
  51. name: moment(lastSeenDate).format(dateFormat),
  52. });
  53. diff = moment.duration(moment(nextDatum.name).diff(lastSeenDate));
  54. }
  55. // Push the next datapoint
  56. newData.push({
  57. ...nextDatum,
  58. name: moment(nextDatum.name).format(dateFormat),
  59. });
  60. }
  61. return {
  62. ...series,
  63. data: newData,
  64. };
  65. }
  66. function roundUpToNearest12HourInterval(time: moment.Moment) {
  67. return roundDownToNearest12HourInterval(time.clone().add(12, 'hour').subtract(1, 'ms'));
  68. }
  69. function roundDownToNearest12HourInterval(time: moment.Moment) {
  70. const hour = time.hour();
  71. const nearestDay = time.clone().startOf('day');
  72. if (hour < 12) {
  73. return nearestDay;
  74. }
  75. return nearestDay.add(12, 'hour');
  76. }