in controlplane/src/core/repositories/analytics/MetricsRepository.ts [168:336]
value: parseValue(v.value),
isPersisted: v.isPersisted,
})),
series: this.mapSeries(rangeInHours, seriesResponse, prevSeriesResponse),
},
};
}
/**
* Get latency metrics
*/
public async getLatencyMetrics({
rangeInHours,
granule,
dateRange,
prevDateRange,
organizationId,
graphId,
whereSql,
queryParams,
}: GetMetricsProps) {
flipDateRangeValuesIfNeeded(dateRange);
const queryLatency = (quantile: string, start: number, end: number) => {
return this.client.queryPromise<{ value: number }>(
`
WITH
toDateTime('${start}') AS startDate,
toDateTime('${end}') AS endDate
SELECT
func_rank(${quantile}, BucketCounts) as rank,
func_rank_bucket_lower_index(rank, BucketCounts) as b,
func_histogram_v2(
rank,
b,
BucketCounts,
anyLast(ExplicitBounds)
) as value,
-- Histogram aggregations
sumForEachMerge(BucketCounts) as BucketCounts
FROM ${this.client.database}.operation_latency_metrics_5_30
WHERE Timestamp >= startDate AND Timestamp <= endDate
AND OrganizationID = '${organizationId}'
AND FederatedGraphID = '${graphId}'
${whereSql ? `AND ${whereSql}` : ''}
`,
queryParams,
);
};
const p95 = queryLatency('0.95', dateRange.start, dateRange.end);
const prevP95 = queryLatency('0.95', prevDateRange.start, prevDateRange.end);
// get top 5 operations in last [range] hours
const queryTop5 = (quantile: string, start: number, end: number) => {
return this.client.queryPromise<{ hash: string; name: string; value: string; isPersisted: boolean }>(
`
WITH
toDateTime('${start}') AS startDate,
toDateTime('${end}') AS endDate
SELECT
OperationHash as hash,
OperationName as name,
IF(empty(OperationPersistedID), false, true) as isPersisted,
func_rank(${quantile}, BucketCounts) as rank,
func_rank_bucket_lower_index(rank, BucketCounts) as b,
round(func_histogram_v2(
rank,
b,
BucketCounts,
anyLast(ExplicitBounds)
), 2) as value,
-- Histogram aggregations
sumForEachMerge(BucketCounts) as BucketCounts
FROM ${this.client.database}.operation_latency_metrics_5_30
WHERE Timestamp >= startDate AND Timestamp <= endDate
AND OrganizationID = '${organizationId}'
AND FederatedGraphID = '${graphId}'
${whereSql ? `AND ${whereSql}` : ''}
GROUP BY OperationName, OperationHash, OperationPersistedID ORDER BY value DESC LIMIT 5
`,
queryParams,
);
};
const top5 = queryTop5('0.95', dateRange.start, dateRange.end);
// get time series of last [range] hours
const querySeries = (quantile: string, start: number, end: number) => {
return this.client.queryPromise<LatencySeries>(
`
WITH
toStartOfInterval(toDateTime('${start}'), INTERVAL ${granule} MINUTE) AS startDate,
toDateTime('${end}') AS endDate
SELECT
toStartOfInterval(Timestamp, INTERVAL ${granule} MINUTE) AS timestamp,
-- Default
func_rank(${quantile}, BucketCounts) as rank,
func_rank_bucket_lower_index(rank, BucketCounts) as b,
func_histogram_v2(
rank,
b,
BucketCounts,
anyLast(ExplicitBounds)
) as value,
-- P50
func_rank(0.50, BucketCounts) as rank50,
func_rank_bucket_lower_index(rank50, BucketCounts) as b50,
func_histogram_v2(
rank50,
b50,
BucketCounts,
anyLast(ExplicitBounds)
) as p50,
-- P90
func_rank(0.90, BucketCounts) as rank90,
func_rank_bucket_lower_index(rank90, BucketCounts) as b90,
func_histogram_v2(
rank90,
b90,
BucketCounts,
anyLast(ExplicitBounds)
) as p90,
-- P90
func_rank(0.99, BucketCounts) as rank99,
func_rank_bucket_lower_index(rank99, BucketCounts) as b99,
func_histogram_v2(
rank99,
b99,
BucketCounts,
anyLast(ExplicitBounds)
) as p99,
-- Histogram aggregations
sumForEachMerge(BucketCounts) as BucketCounts
FROM ${this.client.database}.operation_latency_metrics_5_30
WHERE timestamp >= startDate AND timestamp <= endDate
AND OrganizationID = '${organizationId}'
AND FederatedGraphID = '${graphId}'
${whereSql ? `AND ${whereSql}` : ''}
GROUP BY timestamp, ExplicitBounds
ORDER BY timestamp ASC WITH FILL FROM
toStartOfInterval(toDateTime('${start}'), INTERVAL ${granule} MINUTE)
TO
toDateTime('${end}')
STEP INTERVAL ${granule} minute
`,
queryParams,
);
};
const series = querySeries('0.95', dateRange.start, dateRange.end);
const prevSeries = querySeries('0.95', prevDateRange.start, prevDateRange.end);
const [p95Response, prevP95Response, top5Response, seriesResponse, prevSeriesResponse] = await Promise.all([
p95,
prevP95,
top5,
series,
prevSeries,
]);
return {
data: {
value: parseValue(p95Response[0]?.value),
previousValue: parseValue(prevP95Response[0]?.value),
top: top5Response.map((v) => ({