import * as React from 'react' ; import { connect , ConnectedComponent } from '../../connectedComponent' ; import { RouteComponentProps } from 'react-router' ; import { CanaryAnalysisResult , CanaryClassifierThresholdsConfig , CanaryConfig , CanaryExecutionRequest , CanaryExecutionStatusResponse , CanaryJudgeGroupScore , CanaryResult , MetricSetPair } from '../../../domain/Kayenta' ; import CanaryExecutorStore from '../../../stores/CanaryExecutorStore' ; import { kayentaApiService } from '../../../services' ; import { mapIfPresentOrElse , ofNullable } from '../../../util/OptionalUtils' ; import { CanaryRunResult } from './CanaryRunResult' ; import TerminalResult from '../../shared/TerminalResult' ; import log from '../../../util/LoggerFactory' ; import { boundMethod } from 'autobind-decorator' ; import ConfigEditorStore from '../../../stores/ConfigEditorStore' ; import ReportStore from '../../../stores/ReportStore' ; import { observer } from 'mobx-react' ; import TitledSection from '../../../layout/titledSection' ; import CanaryMetadataSection from './CanaryMetadataSection' ; import ListStore from '../../../stores/ListStore' ; import { DisplayableError } from '../../../domain/Referee' ; import './CanaryReportViewer.scss' ; import logo from '../../../assets/logo.svg' ; interface PathParams { executionId : string ; } interface Props extends RouteComponentProps < PathParams > { } interface Stores { canaryExecutorStore : CanaryExecutorStore ; configEditorStore : ConfigEditorStore ; reportStore : ReportStore ; errorStore : ListStore < DisplayableError > ; } interface State { canaryExecutionStatusResponse ? : CanaryExecutionStatusResponse ; } /**
 * The smart top level component for viewing a report of the /canary results.
 */ @ connect ( 'configEditorStore' , 'canaryExecutorStore' , 'reportStore' , 'errorStore' ) @ observer export default class CanaryReportViewer extends ConnectedComponent < Props , Stores , State > { constructor ( props , context ) { super ( props , context ) ; this . state = { } ; } async componentDidMount ( ) { let canaryExecutionStatusResponse = undefined ; const executionId = this . props . match . params . executionId ; try { canaryExecutionStatusResponse = await kayentaApiService . fetchCanaryExecutionStatusResponse ( executionId ) ; this . stores . reportStore . updateFromCanaryResponse ( canaryExecutionStatusResponse ) ; } catch ( e ) { log . error ( `Failed to fetch the canaryExecutionStatusResponse for id: ${ executionId }` ) ; this . stores . errorStore . push ( { heading : `Failed to fetch the canaryExecutionStatusResponse for id: ${ executionId }` , content : ( < div > We are unable to find a canary run for id : { executionId } . Please confirm this id is correct . < /div>) } ) ; throw e ; } ofNullable ( this . stores . reportStore . canaryExecutionStatusResponse ) . ifPresent ( async ( response ) => { let canaryConfig = undefined ; if ( response . config !== undefined ) { this . stores . configEditorStore . setCanaryConfigObject ( response . config ) ; } if ( ! this . stores . configEditorStore . canaryConfigObject ) { canaryConfig = await kayentaApiService . fetchCanaryConfig ( ofNullable ( response . canaryConfigId ) . orElseThrow ( ( ) => new Error ( 'Expected either a canary config id or canary config object to be present' ) ) ) ; this . stores . configEditorStore . setCanaryConfigObject ( canaryConfig ) ; } if ( this . stores . reportStore . metricSetPairListId ) { const metricSetPairList = await kayentaApiService . fetchMetricSetPairList ( this . stores . reportStore . metricSetPairListId ) ; this . stores . reportStore . setMetricSetPairList ( metricSetPairList ) ; } } ) ; this . setState ( { canaryExecutionStatusResponse } ) ; } @ boundMethod handleGoToConfigButtonClick ( config , canaryExecutionRequestObject ) { this . stores . configEditorStore . setCanaryConfigObject ( config ) ; this . stores . canaryExecutorStore . setCanaryExecutionRequestObject ( canaryExecutionRequestObject ) ; this . props . history . push ( '/config/edit' ) ; } render ( ) { const { configEditorStore , reportStore } = this . stores ; return mapIfPresentOrElse ( ofNullable ( this . state . canaryExecutionStatusResponse ) , canaryExecutionStatusResponse => { if ( canaryExecutionStatusResponse . complete && canaryExecutionStatusResponse . status !== 'terminal' ) { return ( < CanaryRunResult application = { ofNullable ( canaryExecutionStatusResponse . application ) . orElse ( 'ad-hoc' ) as string } metricSourceType = { configEditorStore . metricSourceType as string } metricsAccountName = { canaryExecutionStatusResponse . metricsAccountName as string } storageAccountName = { canaryExecutionStatusResponse . storageAccountName as string } lifetime = { reportStore . lifetime as number } result = { reportStore . canaryResult as CanaryResult } canaryConfig = { configEditorStore . canaryConfigObject as CanaryConfig } thresholds = { reportStore . thresholds as CanaryClassifierThresholdsConfig } selectedMetric = { reportStore . selectedMetric as string } canaryAnalysisResultByIdMap = { reportStore . canaryAnalysisResultByIdMap as KvMap < CanaryAnalysisResult > } idListByMetricGroupNameMap = { reportStore . idListByMetricGroupNameMap as KvMap < string [ ] > } groupScoreByMetricGroupNameMap = { reportStore . groupScoreByMetricGroupNameMap as KvMap < CanaryJudgeGroupScore > } metricSetPairsByIdMap = { reportStore . metricSetPairsByIdMap as KvMap < MetricSetPair > } classificationCountMap = { reportStore . classificationCountMap as Map < string , number > } metricGroupNamesDescByWeight = { configEditorStore . metricGroupNamesDescByWeight as string [ ] } executionRequest = { canaryExecutionStatusResponse . canaryExecutionRequest as CanaryExecutionRequest } displayMetricOverview = { reportStore . displayMetricOverview as boolean } handleOverviewSelection = { reportStore . handleOverviewSelection } handleMetricSelection = { reportStore . handleMetricSelection } handleGoToConfigButtonClick = { this . handleGoToConfigButtonClick } / > ) ; } else if ( ! canaryExecutionStatusResponse . complete ) { } else { return ( < div className = "terminal-canary-wrapper" > < TitledSection title = "Canary Report" / > < CanaryMetadataSection application = { reportStore . application as string } metricsAccountName = { reportStore . metricsAccountName as string } storageAccountName = { reportStore . storageAccountName as string } canaryConfig = { configEditorStore . canaryConfigObject as CanaryConfig } executionRequest = { canaryExecutionStatusResponse . canaryExecutionRequest as CanaryExecutionRequest } handleGoToConfigButtonClick = { this . handleGoToConfigButtonClick } / > < TerminalResult exception = { ofNullable ( this . stores . reportStore . canaryExecutionStatusResponse ) . get ( ) . exception } /> < /div>); } } , ( ) => ( < div className = "img-container" > < img id = "logo" src = { logo } alt = "" / > < /div>)); } }