summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/serverless/components/area.vue
blob: 056b342cf3931c5be7a246354f28c5d2cb131e9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<script>
import { GlAreaChart } from '@gitlab/ui/dist/charts';
import dateFormat from 'dateformat';
import { debounceByAnimationFrame } from '~/lib/utils/common_utils';
import { X_INTERVAL } from '../constants';
import { validateGraphData } from '../utils';
import { __ } from '~/locale';

let debouncedResize;

export default {
  components: {
    GlAreaChart,
  },
  inheritAttrs: false,
  props: {
    graphData: {
      type: Object,
      required: true,
      validator: validateGraphData,
    },
    containerWidth: {
      type: Number,
      required: true,
    },
  },
  data() {
    return {
      tooltipPopoverTitle: '',
      tooltipPopoverContent: '',
      width: this.containerWidth,
    };
  },
  computed: {
    chartData() {
      return this.graphData.queries.reduce((accumulator, query) => {
        accumulator[query.unit] = query.result.reduce((acc, res) => acc.concat(res.values), []);
        return accumulator;
      }, {});
    },
    extractTimeData() {
      return this.chartData.requests.map((data) => data.time);
    },
    generateSeries() {
      return {
        name: __('Invocations'),
        type: 'line',
        data: this.chartData.requests.map((data) => [data.time, data.value]),
        symbolSize: 0,
      };
    },
    getInterval() {
      const { result } = this.graphData.queries[0];

      if (result.length === 0) {
        return 1;
      }

      const split = result[0].values.reduce(
        (acc, pair) => (pair.value > acc ? pair.value : acc),
        1,
      );

      return split < X_INTERVAL ? split : X_INTERVAL;
    },
    chartOptions() {
      return {
        xAxis: {
          name: 'time',
          type: 'time',
          axisLabel: {
            formatter: (date) => dateFormat(date, 'h:MM TT'),
          },
          data: this.extractTimeData,
          nameTextStyle: {
            padding: [18, 0, 0, 0],
          },
        },
        yAxis: {
          name: this.yAxisLabel,
          nameTextStyle: {
            padding: [0, 0, 36, 0],
          },
          splitNumber: this.getInterval,
        },
        legend: {
          formatter: this.xAxisLabel,
        },
        series: this.generateSeries,
      };
    },
    xAxisLabel() {
      return this.graphData.queries.map((query) => query.label).join(', ');
    },
    yAxisLabel() {
      const [query] = this.graphData.queries;
      return `${this.graphData.y_label} (${query.unit})`;
    },
  },
  watch: {
    containerWidth: 'onResize',
  },
  beforeDestroy() {
    window.removeEventListener('resize', debouncedResize);
  },
  created() {
    debouncedResize = debounceByAnimationFrame(this.onResize);
    window.addEventListener('resize', debouncedResize);
  },
  methods: {
    formatTooltipText(params) {
      const [seriesData] = params.seriesData;
      this.tooltipPopoverTitle = dateFormat(params.value, 'dd mmm yyyy, h:MMTT');
      this.tooltipPopoverContent = `${this.yAxisLabel}: ${seriesData.value[1]}`;
    },
    onResize() {
      const { width } = this.$refs.areaChart.$el.getBoundingClientRect();
      this.width = width;
    },
  },
};
</script>

<template>
  <div class="prometheus-graph">
    <div class="prometheus-graph-header">
      <h5 ref="graphTitle" class="prometheus-graph-title">{{ graphData.title }}</h5>
      <div ref="graphWidgets" class="prometheus-graph-widgets">
        <slot></slot>
      </div>
    </div>
    <gl-area-chart
      ref="areaChart"
      v-bind="$attrs"
      :data="[]"
      :option="chartOptions"
      :format-tooltip-text="formatTooltipText"
      :width="width"
      :include-legend-avg-max="false"
    >
      <template #tooltip-title>{{ tooltipPopoverTitle }}</template>
      <template #tooltip-content>{{ tooltipPopoverContent }}</template>
    </gl-area-chart>
  </div>
</template>