1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-12-22 19:07:54 +01:00

add simple metrics to features

This commit is contained in:
sveisvei 2016-11-05 11:50:34 +01:00 committed by Ivar Conradi Østhus
parent 26220fde09
commit 17ec5da59e
11 changed files with 107 additions and 7 deletions

View File

@ -29,7 +29,6 @@ module.exports = class TTLList extends EventEmitter {
let done = false;
// TODO: might use internal linkedlist
this.cache.forEachReverse((entry, index) => {
console.log(now.format(), entry.ttl.format());
if (done) {
return;
} else if (now.isBefore(entry.ttl)) {

View File

@ -23,7 +23,7 @@ module.exports = function (app, config) {
res.json(metrics.getMetricsOverview());
});
app.get('/toggle-metrics', (req, res) => {
app.get('/metrics/features', (req, res) => {
res.json(metrics.getTogglesMetrics());
});

View File

@ -8,7 +8,7 @@ import Chip from 'react-toolbox/lib/chip';
import style from './feature.scss';
const Feature = ({ feature, onFeatureClick, onFeatureRemove }) => {
const Feature = ({ feature, onFeatureClick, onFeatureRemove, metrics = { yes: 0, no: 0, hasData: false } }) => {
const { name, description, enabled, strategies } = feature;
const actions = [
@ -20,6 +20,7 @@ const Feature = ({ feature, onFeatureClick, onFeatureRemove }) => {
];
const leftActions = [
<Chip><span className={style.yes}>{metrics.yes}</span> / <span className={style.no}>{metrics.no}</span></Chip>,
<Switch key="left-actions" onChange={() => onFeatureClick(feature)} checked={enabled} />,
];

View File

@ -6,3 +6,11 @@
color: #aaa !important;
cursor: pointer;
}
.yes {
color: green;
}
.no {
color: red;
}

View File

@ -9,7 +9,9 @@ export default class FeatureListComponent extends React.Component {
onFeatureClick: PropTypes.func.isRequired,
onFeatureRemove: PropTypes.func.isRequired,
features: PropTypes.array.isRequired,
fetchFeatureToggles: PropTypes.array.isRequired,
featureMetrics: PropTypes.object.isRequired,
fetchFeatureToggles: PropTypes.func.isRequired,
fetchFeatureMetrics: PropTypes.func.isRequired,
};
}
@ -19,16 +21,24 @@ export default class FeatureListComponent extends React.Component {
componentDidMount () {
this.props.fetchFeatureToggles();
this.props.fetchFeatureMetrics();
this.timer = setInterval(() => {
this.props.fetchFeatureMetrics();
}, 5000);
}
componentWillUnmount () {
clearInterval(this.timer);
}
render () {
const { features, onFeatureClick, onFeatureRemove } = this.props;
const { features, onFeatureClick, onFeatureRemove, featureMetrics } = this.props;
return (
<List>
<ListSubHeader caption="Feature toggles" />
{features.map((feature, i) =>
<Feature key={i} feature={feature} onFeatureClick={onFeatureClick} onFeatureRemove={onFeatureRemove}/>
<Feature key={i} metrics={featureMetrics[feature.name]} feature={feature} onFeatureClick={onFeatureClick} onFeatureRemove={onFeatureRemove}/>
)}
<ListDivider />
<ListItem

View File

@ -1,15 +1,19 @@
import { connect } from 'react-redux';
import { toggleFeature, fetchFeatureToggles, removeFeatureToggle } from '../../store/feature-actions';
import { fetchFeatureMetrics } from '../../store/feature-metrics-actions';
import FeatureListComponent from './list-component';
const mapStateToProps = (state) => ({
features: state.features.toJS(),
featureMetrics: state.featureMetrics.toJS(),
});
const mapDispatchToProps = {
onFeatureClick: toggleFeature,
onFeatureRemove: removeFeatureToggle,
fetchFeatureToggles,
fetchFeatureMetrics,
};
const FeatureListContainer = connect(

View File

@ -13,7 +13,7 @@ class Metrics extends Component {
return (
<List>
<ListSubHeader caption={<span>Total of {globalCount} toggles checked from {apps.length} apps ({apps.join(', ')})</span>} />
<ListSubHeader caption={<span>Total of {globalCount} toggles </span>} />
<ListDivider />
{clientList.map(({ name, count, ping, appName }, i) =>
<ListItem

View File

@ -0,0 +1,30 @@
import api from './feature-metrics-api';
export const START_FETCH_FEATURE_METRICS = 'START_FETCH_FEATURE_METRICS';
export const RECEIVE_FEATURE_METRICS = 'RECEIVE_FEATURE_METRICS';
export const ERROR_FETCH_FEATURE_TOGGLES = 'ERROR_FETCH_FEATURE_TOGGLES';
function receiveFeatureMetrics (json) {
return {
type: RECEIVE_FEATURE_METRICS,
metrics: json,
receivedAt: Date.now(),
};
}
function dispatchAndThrow (dispatch, type) {
return (error) => {
dispatch({ type, error, receivedAt: Date.now() });
throw error;
};
}
export function fetchFeatureMetrics () {
return dispatch => {
dispatch({ type: START_FETCH_FEATURE_METRICS });
return api.fetchFeatureMetrics()
.then(json => dispatch(receiveFeatureMetrics(json)))
.catch(dispatchAndThrow(dispatch, ERROR_FETCH_FEATURE_TOGGLES));
};
}

View File

@ -0,0 +1,29 @@
const defaultErrorMessage = 'Unexptected exception when talking to unleash-api';
function throwIfNotSuccess (response) {
if (!response.ok) {
if (response.status > 400 && response.status < 404) {
return new Promise((resolve, reject) => {
response.json().then(body => {
const errorMsg = body && body.length > 0 ? body[0].msg : defaultErrorMessage;
let error = new Error(errorMsg);
error.statusCode = response.status;
reject(error);
});
});
} else {
return Promise.reject(new Error(defaultErrorMessage));
}
}
return Promise.resolve(response);
}
function fetchFeatureMetrics () {
return fetch('/metrics/features')
.then(throwIfNotSuccess)
.then(response => response.json());
}
module.exports = {
fetchFeatureMetrics,
};

View File

@ -0,0 +1,17 @@
import { Map as $Map } from 'immutable';
import {
RECEIVE_FEATURE_METRICS,
} from './feature-metrics-actions';
const metrics = (state = new $Map(), action) => {
switch (action.type) {
case RECEIVE_FEATURE_METRICS:
return new $Map(action.metrics);
default:
return state;
}
};
export default metrics;

View File

@ -1,5 +1,6 @@
import { combineReducers } from 'redux';
import features from './feature-store';
import featureMetrics from './feature-metrics-store';
import strategies from './strategy-store';
import input from './input-store';
import history from './history-store'; // eslint-disable-line
@ -11,6 +12,7 @@ import clientInstances from './client-instance-store';
const unleashStore = combineReducers({
features,
featureMetrics,
strategies,
input,
history,