dashboard/new-dashboard/src/components/common/sideBar/InfoSidebarPerformance.ts (297 lines of code) (raw):
import { computedAsync } from "@vueuse/core"
import type { DefaultLabelFormatterCallbackParams as CallbackDataParams } from "echarts"
import type { OptionDataValue } from "../../../shared/echarts-types"
import { computed, Ref } from "vue"
import { Accident, AccidentsConfigurator } from "../../../configurators/accidents/AccidentsConfigurator"
import { ServerWithCompressConfigurator } from "../../../configurators/ServerWithCompressConfigurator"
import { dbTypeStore } from "../../../shared/dbTypes"
import { findDeltaInData, getDifferenceString } from "../../../util/Delta"
import { useSettingsStore } from "../../settings/settingsStore"
import { ValueUnit } from "../chart"
import { durationAxisPointerFormatter, getValueFormatterByMeasureName, isDurationFormatterApplicable, nsToMs, timeFormatWithoutSeconds } from "../formatter"
import { encodeRison } from "../rison"
import { buildUrl, DataSeries, DBType, InfoData } from "./InfoSidebar"
function filterUniqueByName(objects: CallbackDataParams[] | null): CallbackDataParams[] {
const seen = new Set()
return objects?.filter((item) => {
const duplicate = seen.has(item.seriesName)
seen.add(item.seriesName)
return !duplicate
}) as CallbackDataParams[]
}
export function getBuildId(dataSeries: (number | string)[][]): number[] | undefined
export function getBuildId(dataSeries: (number | string)[]): number | undefined
export function getBuildId(dataSeries: (number | string)[] | (number | string)[][]): number | number[] | undefined {
const dbType = dbTypeStore().dbType
let buildId: number | undefined
if (
dbType == DBType.INTELLIJ_DEV ||
dbType == DBType.PERF_UNIT_TESTS ||
dbType == DBType.FLEET_PERF ||
dbType == DBType.DIOGEN ||
dbType == DBType.QODANA ||
dbType == DBType.TOOLBOX
) {
buildId = dataSeries[5] as number
}
if (dbType == DBType.FLEET || dbType == DBType.STARTUP_TESTS) {
buildId = dataSeries[4] as number
}
if (dbType == DBType.STARTUP_TESTS_DEV) {
buildId = dataSeries[4] as number
}
if (dbType == DBType.JBR) {
buildId = dataSeries[5] as number
}
if (dbType == DBType.INTELLIJ) {
buildId = dataSeries[5] as number
}
if (dbType == DBType.BAZEL) {
buildId = dataSeries[5] as number
}
if (dbType == DBType.UNKNOWN) {
console.error("Unknown type of DB")
}
return buildId
}
export function getAccidentBuild(params: CallbackDataParams): string | undefined {
const dbType = dbTypeStore().dbType
if (dbType == DBType.INTELLIJ_DEV || dbType == DBType.PERF_UNIT_TESTS || dbType == DBType.FLEET_PERF || dbType == DBType.DIOGEN || dbType == DBType.TOOLBOX) {
return getBuildId(params.value as number[])?.toString()
}
if (dbType == DBType.FLEET || dbType == DBType.STARTUP_TESTS) {
return getFullBuildId(params)
}
if (dbType == DBType.STARTUP_TESTS_DEV) {
return getBuildId(params.value as number[])?.toString()
}
if (dbType == DBType.INTELLIJ) {
return getFullBuildId(params)
}
if (dbType == DBType.BAZEL) {
return getBuildId(params.value as number[])?.toString()
}
if (dbType == DBType.UNKNOWN) {
console.error("Unknown type of DB")
}
return undefined
}
export function getFullBuildId(params: CallbackDataParams): string | undefined {
const dbType = dbTypeStore().dbType
const dataSeries = params.value as OptionDataValue[]
let buildVersion: number | undefined
let buildNum1: number | undefined
let buildNum2: number | undefined
let buildNumber: string | undefined
if (dbType == DBType.FLEET || dbType == DBType.STARTUP_TESTS) {
buildVersion = dataSeries[7] as number
buildNum1 = dataSeries[8] as number
buildNum2 = dataSeries[9] as number
}
if (dbType == DBType.JBR) {
buildNumber = dataSeries[7] as string
}
if (dbType == DBType.INTELLIJ) {
buildVersion = dataSeries[8] as number
buildNum1 = dataSeries[9] as number
buildNum2 = dataSeries[10] as number
}
if (dbType == DBType.UNKNOWN) {
console.error("Unknown type of DB")
}
return buildVersion == undefined ? buildNumber : `${buildVersion}.${buildNum1}${buildNum2 == 0 ? "" : `.${buildNum2}`}`
}
export function getBasicInfo(params: CallbackDataParams, valueUnit: ValueUnit) {
const seriesName = params.seriesName as string
const dataSeries = params.value as OptionDataValue[]
const dateMs = dataSeries[0] as number
let projectName: string = params.seriesName as string
let machineName: string | undefined
let metricName: string | undefined
let installerId: number | undefined
let type: ValueUnit | undefined = valueUnit
let branch: string | undefined
let mode: string | undefined
const dbType = dbTypeStore().dbType
if (dbType == DBType.FLEET_PERF) {
metricName = dataSeries[2] as string
if (dataSeries[3] == "c") {
type = "counter"
}
machineName = dataSeries[4] as string
projectName = dataSeries[6] as string
branch = dataSeries[7] as string
}
if (dbType == DBType.INTELLIJ_DEV || dbType == DBType.PERF_UNIT_TESTS || dbType == DBType.DIOGEN || dbType == DBType.QODANA || dbType == DBType.TOOLBOX) {
metricName = dataSeries[2] as string
if (dataSeries[3] == "c") {
type = "counter"
}
machineName = dataSeries[4] as string
projectName = dataSeries[6] as string
branch = dataSeries[7] as string
if (dbType == DBType.INTELLIJ_DEV) {
mode = dataSeries[8] as string
}
}
if (dbType == DBType.FLEET || dbType == DBType.STARTUP_TESTS) {
metricName = dataSeries[2] as string
if (!isDurationFormatterApplicable(metricName)) {
type = "counter"
}
machineName = dataSeries[3] as string
projectName = dataSeries[5] as string
installerId = dataSeries[6] as number
branch = dataSeries[10] as string
}
if (dbType == DBType.STARTUP_TESTS_DEV) {
metricName = dataSeries[2] as string
if (!isDurationFormatterApplicable(metricName)) {
type = "counter"
}
machineName = dataSeries[3] as string
projectName = dataSeries[5] as string
branch = dataSeries[6] as string
}
if (dbType == DBType.JBR) {
metricName = dataSeries[2] as string
if (dataSeries[3] == "c") {
type = "counter"
}
machineName = dataSeries[4] as string
projectName = dataSeries[6] as string
branch = dataSeries[8] as string
}
if (dbType == DBType.INTELLIJ) {
metricName = dataSeries[2] as string
if (dataSeries[3] == "c") {
type = "counter"
}
machineName = dataSeries[4] as string
projectName = dataSeries[6] as string
installerId = dataSeries[7] as number
branch = dataSeries[11] as string
mode = dataSeries[12] as string
}
if (dbType == DBType.BAZEL) {
metricName = dataSeries[2] as string
if (dataSeries[3] == "c") {
type = "counter"
}
machineName = dataSeries[4] as string
projectName = dataSeries[6] as string
branch = dataSeries[7] as string
}
if (dbType == DBType.UNKNOWN) {
console.error("Unknown type of DB")
}
const buildId: number | undefined = getBuildId(params.value as (string | number)[])
const changesUrl = installerId == undefined ? `${buildUrl(buildId as number)}&buildTab=changes` : `${buildUrl(installerId)}&buildTab=changes`
const artifactsUrl = `${buildUrl(buildId as number)}&tab=artifacts`
const installerUrl = installerId == undefined ? undefined : `${buildUrl(installerId)}&tab=artifacts`
return {
seriesName,
build: getFullBuildId(params),
artifactsUrl,
changesUrl,
installerUrl,
date: timeFormatWithoutSeconds.format(dateMs),
machineName: machineName as string,
projectName,
title: "Details",
installerId,
buildId: buildId as number,
branch,
metricName,
type,
mode,
}
}
function getInfoWithAccidentsAndDescription(params: CallbackDataParams, valueUnit: ValueUnit, accidents: Ref<Map<string, Accident[]> | undefined> | undefined) {
const basicInfo = getBasicInfo(params, valueUnit)
const accidentBuild = getAccidentBuild(params)
const filteredAccidents = computed(() => {
if (accidentBuild == undefined) return []
const testAccident = accidents?.value?.get(basicInfo.projectName + "_" + accidentBuild) ?? []
const metricAccident = basicInfo.metricName == undefined ? [] : (accidents?.value?.get(basicInfo.projectName + "/" + basicInfo.metricName + "_" + accidentBuild) ?? [])
const buildAccident = accidents?.value?.get(`_${accidentBuild}`) ?? []
return [...testAccident, ...buildAccident, ...metricAccident]
})
const description = computedAsync(async () => {
return await getDescriptionFromMetaDb(basicInfo.projectName, "master")
}) as Ref<Description | null>
return {
...basicInfo,
accidents: filteredAccidents,
description,
}
}
function getInfo(params: CallbackDataParams, valueUnit: ValueUnit, accidents: Ref<Map<string, Accident[]> | undefined> | undefined) {
return getInfoWithAccidentsAndDescription(params, valueUnit, accidents)
}
export function getInfoDataFrom(
params: CallbackDataParams | CallbackDataParams[],
valueUnit: ValueUnit,
accidentsConfigurator: AccidentsConfigurator | null,
chartDataUrl: string
): InfoData {
const accidents = accidentsConfigurator?.value
if (Array.isArray(params) && params.length > 1) {
const filteredParams = filterUniqueByName(params)
const info = getInfo(params[0], valueUnit, accidents)
const series: DataSeries[] = []
for (const param of filteredParams) {
const currentSeriesData = param.value as OptionDataValue[]
const value = currentSeriesData[1] as number
const showValue = getValueFormatterByMeasureName(param.seriesName as string)(value)
series.push({ metricName: param.seriesName as string, value: showValue, color: param.color as string, rawValue: value })
}
return { ...info, series, deltaPrevious: undefined, deltaNext: undefined, chartDataUrl, buildIdPrevious: undefined, buildIdNext: undefined }
} else {
if (Array.isArray(params)) {
params = params[0]
}
const info = getInfo(params, valueUnit, accidents)
const dataSeries = params.value as OptionDataValue[]
const value: number = useSettingsStore().scaling ? (dataSeries.at(-1) as number) : (dataSeries[1] as number)
const showValue: string = durationAxisPointerFormatter(valueUnit == "ns" ? nsToMs(value) : value, info.type)
const delta = findDeltaInData(dataSeries)
let deltaPrevious: string | undefined
let deltaNext: string | undefined
let buildIdPrevious: number | undefined
let buildIdNext: number | undefined
if (delta != undefined) {
if (delta.prev != null) {
deltaPrevious = getDifferenceString(value, delta.prev, valueUnit == "ms", info.type)
buildIdPrevious = delta.prevBuildId
}
if (delta.next != null) {
deltaNext = getDifferenceString(value, delta.next, valueUnit == "ms", info.type)
buildIdNext = delta.nextBuildId
}
}
return {
...info,
deltaNext,
deltaPrevious,
series: [{ metricName: info.metricName, value: showValue, color: params.color as string, rawValue: value }],
chartDataUrl,
buildIdPrevious,
buildIdNext,
}
}
}
class Description {
constructor(
readonly project: string,
readonly branch: string,
readonly url: string,
readonly methodName: string,
readonly description: string
) {}
}
async function getDescriptionFromMetaDb(project: string | undefined, branch: string): Promise<Description | null> {
const description_url = ServerWithCompressConfigurator.DEFAULT_SERVER_URL + "/api/meta/description/"
const response = await fetch(description_url + encodeRison({ project, branch }))
return response.ok ? ((await response.json()) as Description) : null
}