Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically update metric plots for in-progress runs #2099 #5017

Merged
merged 21 commits into from Dec 2, 2021
Expand Up @@ -2,18 +2,19 @@ import React from 'react';
import { connect } from 'react-redux';
import Utils from '../../common/utils/Utils';
import RequestStateWrapper from '../../common/components/RequestStateWrapper';
import { getMetricHistoryApi } from '../actions';
import { getMetricHistoryApi, getRunApi } from '../actions';
import PropTypes from 'prop-types';
import _ from 'lodash';
import { MetricsPlotView } from './MetricsPlotView';
import { getRunTags } from '../reducers/Reducers';
import { getRunTags, getRunInfo } from '../reducers/Reducers';
import {
MetricsPlotControls,
X_AXIS_WALL,
X_AXIS_RELATIVE,
X_AXIS_STEP,
} from './MetricsPlotControls';
import qs from 'qs';
import { message } from 'antd';
import { withRouter } from 'react-router-dom';
import Routes from '../routes';
import { RunLinksPopover } from './RunLinksPopover';
Expand All @@ -34,9 +35,11 @@ export class MetricsPlotPanel extends React.Component {
// An array of { metricKey, history, runUuid, runDisplayName }
metricsWithRunInfoAndHistory: PropTypes.arrayOf(PropTypes.object).isRequired,
getMetricHistoryApi: PropTypes.func.isRequired,
getRunApi: PropTypes.func.isRequired,
location: PropTypes.object.isRequired,
history: PropTypes.object.isRequired,
runDisplayNames: PropTypes.arrayOf(PropTypes.string).isRequired,
allRunsCompleted: PropTypes.bool.isRequired,
};

// The fields below are exposed as instance attributes rather than component state so that they
Expand All @@ -63,6 +66,8 @@ export class MetricsPlotPanel extends React.Component {
// a single-click event.
SINGLE_CLICK_EVENT_DELAY_MS = this.MAX_DOUBLE_CLICK_INTERVAL_MS + 10;

DURATION_BETWEEN_HISTORY_UPDATES_MS = 3000;

constructor(props) {
super(props);
this.state = {
Expand All @@ -71,11 +76,45 @@ export class MetricsPlotPanel extends React.Component {
popoverX: 0,
popoverY: 0,
popoverRunItems: [],
timerId: null,
};
this.displayPopover = false;
this.intervalId = null;
this.loadMetricHistory(this.props.runUuids, this.getUrlState().selectedMetricKeys);
}

clearIntervalIfExists = () => {
if (this.intervalId) {
clearInterval(this.intervalId);
}
};

componentDidMount() {
if (!this.props.allRunsCompleted) {
this.intervalId = setInterval(() => {
const { runUuids } = this.props;
// Use `message` for demo purposes.
message.success({
content: 'Updated',
duration: 0.5,
style: {
marginTop: '20vh',
},
});
harupy marked this conversation as resolved.
Show resolved Hide resolved
this.loadMetricHistory(runUuids, this.getUrlState().selectedMetricKeys);
if (this.props.allRunsCompleted) {
message.success('All runs completed');
this.clearIntervalIfExists();
}
runUuids.forEach(this.props.getRunApi);
}, this.DURATION_BETWEEN_HISTORY_UPDATES_MS);
}
}

componentWillUnmount() {
this.clearIntervalIfExists();
}

getUrlState() {
return Utils.getMetricPlotStateFromUrl(this.props.location.search);
}
Expand Down Expand Up @@ -459,6 +498,18 @@ export class MetricsPlotPanel extends React.Component {
}, 300);
};

checkOnRunUnfinished() {
const { runs } = this.props;

let boolean = false;
runs &&
runs.forEach((run) => {
if (run.getStatus() === 'RUNNING') boolean = true;
});

return boolean;
}

harupy marked this conversation as resolved.
Show resolved Hide resolved
render() {
const { experimentId, runUuids, runDisplayNames, distinctMetricKeys, location } = this.props;
const { popoverVisible, popoverX, popoverY, popoverRunItems } = this.state;
Expand Down Expand Up @@ -534,6 +585,9 @@ const mapStateToProps = (state, ownProps) => {
return latestMetrics ? Object.keys(latestMetrics) : [];
});
const distinctMetricKeys = [...new Set(metricKeys)].sort();
const allRunsCompleted = runUuids
.map((runUuid) => getRunInfo(runUuid, state))
.every(({ status }) => status !== 'RUNNING');

const runDisplayNames = [];

Expand Down Expand Up @@ -561,9 +615,10 @@ const mapStateToProps = (state, ownProps) => {
latestMetricsByRunUuid,
distinctMetricKeys,
metricsWithRunInfoAndHistory,
allRunsCompleted,
};
};

const mapDispatchToProps = { getMetricHistoryApi };
const mapDispatchToProps = { getMetricHistoryApi, getRunApi };

export default withRouter(connect(mapStateToProps, mapDispatchToProps)(MetricsPlotPanel));