Skip to content

Commit

Permalink
fix(analytics): trend range text in multi-entity queries [MA-3250]
Browse files Browse the repository at this point in the history
In the case where we can't query a trend (either because the props said
not to or because we're doing a multi-entity query), it doesn't make sense
to render any trend text.
  • Loading branch information
adorack committed Oct 18, 2024
1 parent 4fb71b4 commit 17e7bbb
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 20 deletions.
134 changes: 119 additions & 15 deletions packages/analytics/analytics-metric-provider/sandbox/App.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
<template>
<div>
<select v-model="timeframeSelection">
<option value="">
None
</option>
<option value="15m">
15 minutes
</option>
<option value="6h">
6 hours
</option>
<option value="24h">
1 day
</option>
</select>
</div>
<h4>Global props, Large cards</h4>
<div>
<SandboxBridgeInjector :query-bridge="globalBridge">
Expand Down Expand Up @@ -52,15 +68,76 @@
</MetricsProvider>
</SandboxBridgeInjector>
</div>

<h4>Table View</h4>
<div>
<SandboxBridgeInjector :query-bridge="timeframeProviderBridge">
<MetricsProvider
v-slot="{ timeframe }"
v-bind="timeframeProviderProps"
>
<div>
<button
type="button"
@click="randomizeData"
>
Randomize Data
</button>
</div>
<div>Provider timeframe text: {{ timeframe.display }}</div>
<table style="width: 50%">
<tr>
<th>Name</th>
<th>Traffic</th>
<th>Errors</th>
<th>Latency</th>
</tr>
<tr>
<td>Blah</td>
<td>
<MetricsConsumer
v-slot="{ cardValues }"
lookup-key="blah😀😀"
>
{{ cardValues.trafficCard.currentValue }}
</MetricsConsumer>
</td>
<td>
<MetricsConsumer
v-slot="{ cardValues }"
lookup-key="blah😀😀"
>
{{ cardValues.errorRateFormatted }}
</MetricsConsumer>
</td>
<td>
<MetricsConsumer
v-slot="{ cardValues }"
lookup-key="blah😀😀"
>
{{ cardValues.latencyCard.currentValue }}
</MetricsConsumer>
</td>
</tr>
</table>
</MetricsProvider>
</SandboxBridgeInjector>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import MetricsConsumer from '../src/components/MetricsConsumer.vue'
import MetricsProvider from '../src/components/MetricsProvider.vue'
import type { MockOptions } from '../src/mockExploreResponse'
import { mockExploreResponse } from '../src/mockExploreResponse'
import axios from 'axios'
import type { AnalyticsBridge, ExploreFilter, ExploreQuery } from '@kong-ui-public/analytics-utilities'
import { TimeframeKeys, TimePeriods } from '@kong-ui-public/analytics-utilities'
import type {
AnalyticsBridge,
DatasourceAwareQuery,
ExploreFilter,
ExploreQuery,
} from '@kong-ui-public/analytics-utilities'
import { TimePeriods } from '@kong-ui-public/analytics-utilities'
import { MetricCardSize } from '../src/enums'
import SandboxBridgeInjector from './SandboxBridgeInjector.vue'
Expand All @@ -69,6 +146,8 @@ const refreshInterval = 60 * 1000
// Need to have a local proxy running forwarding traffic to konnect api to hit real data.
const USE_REAL_DATA = false
const timeframeSelection = ref('15m')
const makeQueryBridge = (opts?: MockOptions): AnalyticsBridge => {
const options = {
Expand All @@ -81,13 +160,13 @@ const makeQueryBridge = (opts?: MockOptions): AnalyticsBridge => {
}
return {
queryFn: (query: ExploreQuery) => {
queryFn: (query: DatasourceAwareQuery) => {
if (USE_REAL_DATA) {
options.data = query
return axios.request(options).then(res => res.data)
} else {
return Promise.resolve(mockExploreResponse(query, opts))
return Promise.resolve(mockExploreResponse(query.query as ExploreQuery, opts))
}
},
Expand All @@ -107,43 +186,68 @@ const makeQueryBridge = (opts?: MockOptions): AnalyticsBridge => {
}
}
const overrideTimeframe = computed(() => {
if (timeframeSelection.value) {
return TimePeriods.get(timeframeSelection.value)
}
return undefined
})
// Query stats for an entire org, no grouping or filtering.
const globalProviderProps = {
const globalProviderProps = computed(() => ({
refreshInterval,
overrideTimeframe: TimePeriods.get(TimeframeKeys.SIX_HOUR),
overrideTimeframe: overrideTimeframe.value,
longCardTitles: false,
description: 'Generic Description',
containerTitle: 'Analytics',
}
}))
const globalBridge = makeQueryBridge()
// Query stats for an entire org, but also apply a filter.
const filteredProviderProps = {
const filteredProviderProps = computed(() => ({
refreshInterval,
overrideTimeframe: TimePeriods.get(TimeframeKeys.SIX_HOUR),
overrideTimeframe: overrideTimeframe.value,
additionalFilter: [{
dimension: 'application',
type: 'in',
values: ['app1'],
} as ExploreFilter],
}
}))
// Query stats for a single entity, no grouping.
const singleProviderProps = {
const singleProviderProps = computed(() => ({
refreshInterval,
overrideTimeframe: overrideTimeframe.value,
dimension: 'route',
filterValue: 'blah',
}
}))
const singleProviderBridge = makeQueryBridge({ dimensionNames: ['blah'] })
// Query stats for multiple entities.
const multiProviderProps = {
const multiProviderProps = computed(() => ({
refreshInterval,
dimension: 'route',
overrideTimeframe: TimePeriods.get(TimeframeKeys.CURRENT_MONTH),
}
overrideTimeframe: overrideTimeframe.value,
}))
const multiProviderBridge = makeQueryBridge({ dimensionNames: ['blah😀😀', 'arrgh'] })
// Query stats with adjustable timeframe
const filterCounter = ref(0)
const randomizeData = () => {
filterCounter.value += 1
}
const timeframeProviderProps = computed(() => ({
refreshInterval,
dimension: 'route',
overrideTimeframe: overrideTimeframe.value,
additionalFilter: [{ dimension: 'control_plane', operator: '=', value: '' + filterCounter.value }],
}))
const timeframeProviderBridge = makeQueryBridge({ dimensionNames: ['blah😀😀', 'arrgh'], deterministic: false })
</script>
<style lang="scss">
body {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type { MetricFetcherOptions } from '../types'
import { MAX_ANALYTICS_REQUEST_RETRIES } from '../constants'
import composables from '.'
import { useSwrvState } from '@kong-ui-public/core'
import { TimeframeKeys, TimePeriods } from '@kong-ui-public/analytics-utilities'

export const DEFAULT_KEY = Symbol('default')
export type MappedMetrics = Record<string | typeof DEFAULT_KEY, Record<string | typeof DEFAULT_KEY, number>>
Expand Down Expand Up @@ -168,8 +167,8 @@ export default function useMetricFetcher(opts: MetricFetcherOptions): FetcherRes
return opts.withTrend.value
// @ts-ignore - dynamic i18n key
? i18n.t(`trendRange.${opts.timeframe.value.key}`)
// @ts-ignore - dynamic i18n key
: i18n.t(`trendRange.${TimePeriods.get(TimeframeKeys.ONE_DAY)?.key}`)
// If we're unable to query with a trend, we can't render a meaningful trend range description.
: ''
}
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const fromUnixTimeMs = (t: number) => new Date(t)
export interface MockOptions {
dimensionNames?: string[]
injectErrors?: 'latency' | 'traffic' | 'all'
deterministic?: boolean
}

export const mockExploreResponseFromCypress = (
Expand Down Expand Up @@ -67,7 +68,11 @@ export const mockExploreResponse = (
if (body.dimensions?.includes('status_code_grouped')) {
ALL_STATUS_CODE_GROUPS.forEach(code => {
const event = metrics.reduce((accum, agg) => {
accum[agg] = (numRecords - i) * 1000 + 100 * j + 1
if (opts?.deterministic ?? true) {
accum[agg] = (numRecords - i) * 1000 + 100 * j + 1
} else {
accum[agg] = Math.round(Math.random() * 1000)
}
return accum
}, { ...eventValue, status_code_grouped: code })

Expand All @@ -88,7 +93,11 @@ export const mockExploreResponse = (
? fromUnixTimeMs(start).toISOString()
: fromUnixTimeMs(start + granularity).toISOString(),
event: metrics.reduce((accum, agg) => {
accum[agg] = (numRecords - i) * 1000 + (100 * j) + 1
if (opts?.deterministic ?? true) {
accum[agg] = (numRecords - i) * 1000 + (100 * j) + 1
} else {
accum[agg] = Math.round(Math.random() * 1000)
}
return accum
}, { ...eventValue }),
})
Expand Down

0 comments on commit 17e7bbb

Please sign in to comment.