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

add simple metrics ui

This commit is contained in:
sveisvei 2016-10-27 13:12:26 +02:00 committed by Ivar Conradi Østhus
parent e4f826a5a2
commit b375cb839a
11 changed files with 153 additions and 4 deletions

View File

@ -2,5 +2,8 @@
"extends": [
"finn",
"finn/node"
]
],
"rules": {
"no-shadow": 0
}
}

View File

@ -0,0 +1,31 @@
import React, { Component } from 'react';
import { List, ListItem, ListSubHeader, ListDivider } from 'react-toolbox/lib/list';
import Chip from 'react-toolbox/lib/chip';
class Metrics extends Component {
componentDidMount () {
this.props.fetchMetrics();
}
render () {
const { globalCount, apps, clientList } = this.props;
return (
<List>
<ListSubHeader caption={<span>Total of {globalCount} toggles checked from {apps.length} apps ({apps.join(', ')})</span>} />
<ListDivider />
{clientList.map(({ name, count, ping, appName }, i) =>
<ListItem
leftActions={[<Chip>{count}</Chip>]}
key={name + i}
caption={appName}
legend={`${name} pinged ${ping}`} />
)}
</List>
);
}
}
export default Metrics;

View File

@ -0,0 +1,39 @@
import { connect } from 'react-redux';
import Metrics from './metrics-component';
import { fetchMetrics } from '../../store/metrics-actions';
const mapStateToProps = (state) => {
const globalCount = state.metrics.get('globalCount');
const apps = state.metrics.get('apps').toArray();
const clients = state.metrics.get('clients').toJS();
const clientList = Object
.keys(clients)
.map((k) => {
const client = clients[k];
return {
name: k,
appName: client.appName,
count: client.count,
ping: new Date(client.ping),
};
})
.sort((a, b) => (a.ping > b.ping ? -1 : 1));
/*
Possible stuff to ask/answer:
* toggles in use but not in unleash-server
* nr of toggles using fallbackValue
* strategies implemented but not used
*/
return {
globalCount,
apps,
clientList,
};
};
const MetricsContainer = connect(mapStateToProps, { fetchMetrics })(Metrics);
export default MetricsContainer;

View File

@ -14,10 +14,11 @@ export default class UnleashNav extends Component {
return (
<List selectable ripple className={style.navigation}>
{createListItem('/features', 'Feature Toggles')}
{createListItem('/features', 'Feature toggles')}
{createListItem('/strategies', 'Strategies')}
{createListItem('/history', 'Event History')}
{createListItem('/archive', 'Archived Toggles')}
{createListItem('/history', 'Event history')}
{createListItem('/archive', 'Archived toggles')}
{createListItem('/metrics', 'Client metrics')}
<ListDivider />

View File

@ -0,0 +1,20 @@
const URI = '/metrics';
function throwIfNotSuccess (response) {
if (!response.ok) {
let error = new Error('API call failed');
error.status = response.status;
throw error;
}
return response;
}
function fetchAll () {
return fetch(URI)
.then(throwIfNotSuccess)
.then(response => response.json());
}
module.exports = {
fetchAll,
};

View File

@ -15,6 +15,7 @@ import Strategies from './page/strategies';
import CreateStrategies from './page/strategies/create';
import HistoryPage from './page/history';
import Archive from './page/archive';
import Metrics from './page/metrics';
const unleashStore = createStore(
store,
@ -35,6 +36,7 @@ ReactDOM.render(
<Route path="/strategies/create" component={CreateStrategies} />
<Route path="/history" component={HistoryPage} />
<Route path="/archive" component={Archive} />
<Route path="/metrics" component={Metrics} />
</Route>
</Router>
</Provider>, document.getElementById('app'));

View File

@ -0,0 +1,6 @@
import React from 'react';
import Metrics from '../../component/metrics/metrics-container';
const render = () => <Metrics />;
export default render;

View File

@ -5,6 +5,7 @@ import input from './input-store';
import history from './history-store'; // eslint-disable-line
import archive from './archive-store';
import error from './error-store';
import metrics from './metrics-store';
const unleashStore = combineReducers({
features,
@ -13,6 +14,7 @@ const unleashStore = combineReducers({
history,
archive,
error,
metrics,
});
export default unleashStore;

View File

@ -0,0 +1,20 @@
import api from '../data/metrics-api';
export const RECEIVE_METRICS = 'RECEIVE_METRICS';
export const ERROR_RECEIVE_METRICS = 'ERROR_RECEIVE_METRICS';
const receiveMetrics = (json) => ({
type: RECEIVE_METRICS,
value: json,
});
const errorReceiveMetrics = (statusCode) => ({
type: ERROR_RECEIVE_METRICS,
statusCode,
});
export function fetchMetrics () {
return dispatch => api.fetchAll()
.then(json => dispatch(receiveMetrics(json)))
.catch(error => dispatch(errorReceiveMetrics(error)));
}

View File

@ -0,0 +1,21 @@
import { fromJS } from 'immutable';
import { RECEIVE_METRICS } from './metrics-actions';
function getInitState () {
return fromJS({
totalCount: 0,
apps: [],
clients: {},
});
}
const historyStore = (state = getInitState(), action) => {
switch (action.type) {
case RECEIVE_METRICS:
return fromJS(action.value);
default:
return state;
}
};
export default historyStore;

View File

@ -73,6 +73,10 @@ module.exports = {
target: 'http://localhost:4242',
secure: false,
},
'/metrics': {
target: 'http://localhost:4242',
secure: false,
},
},
},
};