diff --git a/package.json b/package.json index 68c1cd0d98..2ff86f238e 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "eslint-plugin-react": "7.1.0", "husky": "^0.13.3", "lint-staged": "^3.4.0", + "prettier": "^1.5.3", "react-scripts": "^0.9.5", "sets-equal": "^1.0.0", "sinon": "^1.17.5", @@ -38,7 +39,6 @@ "json-markup": "^1.0.0", "lodash": "^4.17.2", "moment": "^2.14.1", - "prettier": "^0.22.0", "prop-types": "^15.5.10", "query-string": "^4.2.3", "react": "^15.5.0", @@ -78,7 +78,7 @@ "coverage": "npm run test -- --coverage", "lint": "npm run eslint && npm run prettier && npm run flow", "eslint": "eslint .", - "prettier": "prettier --single-quote --trailing-comma es5 --write \"src/**/*.js\"", + "prettier": "prettier --single-quote --trailing-comma es5 --print-width 110 --write \"src/**/*.js\"", "flow": "flow; test $? -eq 0 -o $? -eq 2", "set-homepage": "json -I -f package.json -e 'this.homepage=process.env.HOMEPAGE'", "clear-homepage": "json -I -f package.json -e 'delete this.homepage'", diff --git a/src/actions/jaeger-api.js b/src/actions/jaeger-api.js index 45d2afc976..6e9b024591 100644 --- a/src/actions/jaeger-api.js +++ b/src/actions/jaeger-api.js @@ -37,8 +37,7 @@ export const searchTraces = createAction( query => ({ query }) ); -export const fetchServices = createAction('@JAEGER_API/FETCH_SERVICES', () => - JaegerAPI.fetchServices()); +export const fetchServices = createAction('@JAEGER_API/FETCH_SERVICES', () => JaegerAPI.fetchServices()); export const fetchServiceOperations = createAction( '@JAEGER_API/FETCH_SERVICE_OPERATIONS', @@ -46,7 +45,6 @@ export const fetchServiceOperations = createAction( serviceName => ({ serviceName }) ); -export const fetchDependencies = createAction( - '@JAEGER_API/FETCH_DEPENDENCIES', - () => JaegerAPI.fetchDependencies() +export const fetchDependencies = createAction('@JAEGER_API/FETCH_DEPENDENCIES', () => + JaegerAPI.fetchDependencies() ); diff --git a/src/actions/jaeger-api.test.js b/src/actions/jaeger-api.test.js index 3ca77f7f66..80ce1193ef 100644 --- a/src/actions/jaeger-api.test.js +++ b/src/actions/jaeger-api.test.js @@ -104,10 +104,7 @@ it('@JAEGER_API/FETCH_SERVICES should return a promise', () => { it('@JAEGER_API/FETCH_SERVICE_OPERATIONS should call the JaegerAPI', () => { const api = JaegerAPI; const mock = sinon.mock(api); - const called = mock - .expects('fetchServiceOperations') - .once() - .withExactArgs('service'); + const called = mock.expects('fetchServiceOperations').once().withExactArgs('service'); jaegerApiActions.fetchServiceOperations('service'); expect(called.verify()).toBeTruthy(); mock.restore(); diff --git a/src/api/jaeger.js b/src/api/jaeger.js index fb8ec2865d..63357c9287 100644 --- a/src/api/jaeger.js +++ b/src/api/jaeger.js @@ -34,9 +34,7 @@ function getJSON(url, query) { return response .json() .then(({ errors = [] }) => { - throw new Error( - errors.length > 0 ? errors[0].msg : 'An unknown error occurred.' - ); + throw new Error(errors.length > 0 ? errors[0].msg : 'An unknown error occurred.'); }) .catch( (/* err */) => { @@ -50,9 +48,7 @@ function getJSON(url, query) { } export const DEFAULT_API_ROOT = '/api/'; -export const DEFAULT_DEPENDENCY_LOOKBACK = moment - .duration(1, 'weeks') - .asMilliseconds(); +export const DEFAULT_DEPENDENCY_LOOKBACK = moment.duration(1, 'weeks').asMilliseconds(); const JaegerAPI = { apiRoot: DEFAULT_API_ROOT, @@ -68,10 +64,7 @@ const JaegerAPI = { fetchServiceOperations(serviceName) { return getJSON(`${this.apiRoot}services/${serviceName}/operations`); }, - fetchDependencies( - endTs = new Date().getTime(), - lookback = DEFAULT_DEPENDENCY_LOOKBACK - ) { + fetchDependencies(endTs = new Date().getTime(), lookback = DEFAULT_DEPENDENCY_LOOKBACK) { return getJSON(`${this.apiRoot}dependencies`, { endTs, lookback }); }, }; diff --git a/src/api/jaeger.test.js b/src/api/jaeger.test.js index 5f894d40af..5db73918b6 100644 --- a/src/api/jaeger.test.js +++ b/src/api/jaeger.test.js @@ -29,8 +29,10 @@ jest.mock('isomorphic-fetch', () => resolve({ status: 200, data: () => Promise.resolve({ data: null }), - })) - )); + }) + ) + ) +); const fetchMock = require('isomorphic-fetch'); @@ -49,8 +51,7 @@ it('fetchTrace() should resolve the whole response', () => { }) ); - return JaegerAPI.fetchTrace('trace-id').then(resp => - expect(resp.data).toBe(generatedTraces)); + return JaegerAPI.fetchTrace('trace-id').then(resp => expect(resp.data).toBe(generatedTraces)); }); it('fetchTrace() should reject with a bad status code', () => { diff --git a/src/components/App/NotFound.js b/src/components/App/NotFound.js index 9d04d18e15..70a01208a4 100644 --- a/src/components/App/NotFound.js +++ b/src/components/App/NotFound.js @@ -27,17 +27,23 @@ export default function NotFound({ error }) {
-

{'404'}

+

+ {'404'} +

{"Looks like you tried to access something that doesn't exist."}

{error &&
-

{error.toString()}

+

+ {error.toString()} +

}
- {'Back home'} + + {'Back home'} +
diff --git a/src/components/App/TopNav.js b/src/components/App/TopNav.js index deb9f72bf0..0bb68015a9 100644 --- a/src/components/App/TopNav.js +++ b/src/components/App/TopNav.js @@ -46,9 +46,11 @@ export default function TopNav() {
- {NAV_LINKS.map(({ key, to, text }) => ( - {text} - ))} + {NAV_LINKS.map(({ key, to, text }) => + + {text} + + )} ); diff --git a/src/components/App/index.js b/src/components/App/index.js index 3afb82562a..60d408f5ae 100644 --- a/src/components/App/index.js +++ b/src/components/App/index.js @@ -70,10 +70,7 @@ export default class JaegerUIApp extends Component { - + diff --git a/src/components/DependencyGraph/DependencyForceGraph.js b/src/components/DependencyGraph/DependencyForceGraph.js index 0a04086af3..4f7907ff9a 100644 --- a/src/components/DependencyGraph/DependencyForceGraph.js +++ b/src/components/DependencyGraph/DependencyForceGraph.js @@ -19,18 +19,13 @@ // THE SOFTWARE. import React, { Component } from 'react'; -import { - InteractiveForceGraph, - ForceGraphNode, - ForceGraphLink, -} from 'react-vis-force'; +import { InteractiveForceGraph, ForceGraphNode, ForceGraphLink } from 'react-vis-force'; import { window } from 'global'; import { debounce } from 'lodash'; import { nodesPropTypes, linksPropTypes } from '../../propTypes/dependencies'; -const chargeStrength = ({ radius = 5, orphan }) => - orphan ? -20 * radius : -12 * radius; +const chargeStrength = ({ radius = 5, orphan }) => (orphan ? -20 * radius : -12 * radius); export default class DependencyForceGraph extends Component { static get propTypes() { @@ -102,14 +97,7 @@ export default class DependencyForceGraph extends Component { nodeAttrs={['orphan']} highlightDependencies > - {nodes.map(({ - labelStyle, - labelClass, - showLabel, - opacity, - fill, - ...node - }) => ( + {nodes.map(({ labelStyle, labelClass, showLabel, opacity, fill, ...node }) => - ))} - {links.map(({ opacity, ...link }) => ( - ${link.target}`} - opacity={opacity} - link={link} - /> - ))} + )} + {links.map(({ opacity, ...link }) => + ${link.target}`} opacity={opacity} link={link} /> + )} ); diff --git a/src/components/DependencyGraph/index.js b/src/components/DependencyGraph/index.js index f9129c1867..468a1245c7 100644 --- a/src/components/DependencyGraph/index.js +++ b/src/components/DependencyGraph/index.js @@ -26,9 +26,7 @@ import { Menu } from 'semantic-ui-react'; import './DependencyGraph.css'; import * as jaegerApiActions from '../../actions/jaeger-api'; -import { - formatDependenciesAsNodesAndLinks, -} from '../../selectors/dependencies'; +import { formatDependenciesAsNodesAndLinks } from '../../selectors/dependencies'; import NotFound from '../App/NotFound'; import { nodesPropTypes, linksPropTypes } from '../../propTypes/dependencies'; @@ -80,17 +78,13 @@ export default class DependencyGraphPage extends Component { return (
-
- No service dependencies found. -
+
No service dependencies found.
); } - const GRAPH_TYPE_OPTIONS = [ - { type: 'FORCE_DIRECTED', name: 'Force Directed Graph' }, - ]; + const GRAPH_TYPE_OPTIONS = [{ type: 'FORCE_DIRECTED', name: 'Force Directed Graph' }]; if (serviceCalls.length <= 100) { GRAPH_TYPE_OPTIONS.push({ type: 'DAG', name: 'DAG' }); @@ -98,13 +92,13 @@ export default class DependencyGraphPage extends Component { return (
- {GRAPH_TYPE_OPTIONS.map(option => ( + {GRAPH_TYPE_OPTIONS.map(option => this.handleGraphTypeChange(option.type)} /> - ))} + )}
- {graphType === 'FORCE_DIRECTED' && - } + {graphType === 'FORCE_DIRECTED' && } {graphType === 'DAG' && }
@@ -147,7 +140,4 @@ function mapDispatchToProps(dispatch) { return { fetchDependencies }; } -export const ConnectedDependencyGraphPage = connect( - mapStateToProps, - mapDispatchToProps -)(DependencyGraphPage); +export const ConnectedDependencyGraphPage = connect(mapStateToProps, mapDispatchToProps)(DependencyGraphPage); diff --git a/src/components/SearchTracePage/SearchDropdownInput.js b/src/components/SearchTracePage/SearchDropdownInput.js index fca7974a29..27d094fff9 100644 --- a/src/components/SearchTracePage/SearchDropdownInput.js +++ b/src/components/SearchTracePage/SearchDropdownInput.js @@ -38,10 +38,7 @@ export default class SearchDropdownInput extends Component { }; } componentWillReceiveProps(nextProps) { - if ( - this.props.items.map(i => i.text).join(',') !== - nextProps.items.map(i => i.text).join(',') - ) { + if (this.props.items.map(i => i.text).join(',') !== nextProps.items.map(i => i.text).join(',')) { this.setState({ items: nextProps.items, currentItems: nextProps.items.slice(0, nextProps.maxResults), @@ -50,9 +47,7 @@ export default class SearchDropdownInput extends Component { } onSearch(items, v) { const { maxResults } = this.props; - return this.state.items - .filter(i => i.text.startsWith(v)) - .slice(0, maxResults); + return this.state.items.filter(i => i.text.startsWith(v)).slice(0, maxResults); } render() { const { input: { value, onChange } } = this.props; diff --git a/src/components/SearchTracePage/TraceResultsScatterPlot.js b/src/components/SearchTracePage/TraceResultsScatterPlot.js index 4552569348..0871169d2c 100644 --- a/src/components/SearchTracePage/TraceResultsScatterPlot.js +++ b/src/components/SearchTracePage/TraceResultsScatterPlot.js @@ -39,16 +39,8 @@ function TraceResultsScatterPlot(props) { width={containerWidth} height={200} > - moment(t).format('hh:mm:ss a')} - /> - formatDuration(t, 'milliseconds')} - /> + moment(t).format('hh:mm:ss a')} /> + formatDuration(t, 'milliseconds')} /> diff --git a/src/components/SearchTracePage/TraceSearchForm.js b/src/components/SearchTracePage/TraceSearchForm.js index 0a82d07548..cf05638342 100644 --- a/src/components/SearchTracePage/TraceSearchForm.js +++ b/src/components/SearchTracePage/TraceSearchForm.js @@ -31,9 +31,7 @@ import SearchDropdownInput from './SearchDropdownInput'; import * as jaegerApiActions from '../../actions/jaeger-api'; import { formatDate, formatTime } from '../../utils/date'; -export function getUnixTimeStampInMSFromForm( - { startDate, startDateTime, endDate, endDateTime } -) { +export function getUnixTimeStampInMSFromForm({ startDate, startDateTime, endDate, endDateTime }) { const start = `${startDate} ${startDateTime}`; const end = `${endDate} ${endDateTime}`; return { @@ -81,16 +79,9 @@ export function convertQueryParamsToFormDates({ start, end }) { } export function TraceSearchFormComponent(props) { - const { - selectedService = '-', - selectedLookback, - handleSubmit, - submitting, - services, - } = props; + const { selectedService = '-', selectedLookback, handleSubmit, submitting, services } = props; const selectedServicePayload = services.find(s => s.name === selectedService); - const operationsForService = (selectedServicePayload && - selectedServicePayload.operations) || []; + const operationsForService = (selectedServicePayload && selectedServicePayload.operations) || []; const noSelectedService = selectedService === '-' || !selectedService; return (
@@ -101,9 +92,7 @@ export function TraceSearchFormComponent(props) { name="service" component={SearchDropdownInput} className="ui dropdown" - items={services - .concat({ name: '-' }) - .map(s => ({ text: s.name, value: s.name }))} + items={services.concat({ name: '-' }).map(s => ({ text: s.name, value: s.name }))} />
@@ -113,9 +102,7 @@ export function TraceSearchFormComponent(props) { name="operation" component={SearchDropdownInput} className="ui dropdown" - items={operationsForService - .concat('all') - .map(op => ({ text: op, value: op }))} + items={operationsForService.concat('all').map(op => ({ text: op, value: op }))} /> } @@ -150,12 +137,7 @@ export function TraceSearchFormComponent(props) {
- +
@@ -168,12 +150,7 @@ export function TraceSearchFormComponent(props) {
- +
@@ -185,23 +162,13 @@ export function TraceSearchFormComponent(props) {
- +
- +
@@ -209,19 +176,10 @@ export function TraceSearchFormComponent(props) {
- +
- @@ -282,9 +240,7 @@ const mapStateToProps = state => { } let traceIDs; if (traceIDParams) { - traceIDs = traceIDParams instanceof Array - ? traceIDParams.join(',') - : traceIDParams; + traceIDs = traceIDParams instanceof Array ? traceIDParams.join(',') : traceIDParams; } return { destroyOnUnmount: false, @@ -332,8 +288,7 @@ const mapDispatchToProps = dispatch => { let end; if (lookback !== 'custom') { const unit = lookback.split('').pop(); - start = moment().subtract(parseInt(lookback, 10), unit).valueOf() * - 1000; + start = moment().subtract(parseInt(lookback, 10), unit).valueOf() * 1000; end = moment().valueOf() * 1000; } else { const times = getUnixTimeStampInMSFromForm({ diff --git a/src/components/SearchTracePage/TraceSearchForm.test.js b/src/components/SearchTracePage/TraceSearchForm.test.js index 3ad99f6a33..7b0177dc41 100644 --- a/src/components/SearchTracePage/TraceSearchForm.test.js +++ b/src/components/SearchTracePage/TraceSearchForm.test.js @@ -32,18 +32,13 @@ const { } = require('./TraceSearchForm'); const defaultProps = { - services: [ - { name: 'svcA', operations: ['A', 'B'] }, - { name: 'svcB', operations: ['A', 'B'] }, - ], + services: [{ name: 'svcA', operations: ['A', 'B'] }, { name: 'svcB', operations: ['A', 'B'] }], dataCenters: ['dc1'], }; it(' only shows operations when a service is selected', () => { let wrapper; - wrapper = shallow( - - ); + wrapper = shallow(); expect(wrapper.find('.search-form--operation').length).toBe(1); wrapper = shallow(); diff --git a/src/components/SearchTracePage/TraceSearchResult.js b/src/components/SearchTracePage/TraceSearchResult.js index de3cb98918..f0fa6fd20b 100644 --- a/src/components/SearchTracePage/TraceSearchResult.js +++ b/src/components/SearchTracePage/TraceSearchResult.js @@ -33,19 +33,9 @@ const getBackgroundStyle = durationPercent => 90deg, rgba(17, 147, 154, .3) ${durationPercent}%, whitesmoke ${durationPercent - 100}%)`; export default function TraceSearchResult({ trace, durationPercent = 100 }) { - const { - duration, - services, - timestamp, - numberOfErredSpans, - numberOfSpans, - traceName, - } = trace; + const { duration, services, timestamp, numberOfErredSpans, numberOfSpans, traceName } = trace; return ( -
+
}
- {sortBy(services, s => s.name).map(service => ( + {sortBy(services, s => s.name).map(service =>
- ))} + )}
- {moment(timestamp).format('hh:mm:ss a')} - {' '} - ( + {moment(timestamp).format('hh:mm:ss a')} ( {moment(timestamp).fromNow()} ) diff --git a/src/components/SearchTracePage/TraceSearchResult.test.js b/src/components/SearchTracePage/TraceSearchResult.test.js index 33c019e049..98b318f7b5 100644 --- a/src/components/SearchTracePage/TraceSearchResult.test.js +++ b/src/components/SearchTracePage/TraceSearchResult.test.js @@ -38,14 +38,9 @@ const testTraceProps = { }; it(' should render base case correctly', () => { - const wrapper = shallow( - - ); + const wrapper = shallow(); - const numberOfSpanText = wrapper - .find('.trace-search-result--spans') - .first() - .text(); + const numberOfSpanText = wrapper.find('.trace-search-result--spans').first().text(); const numberOfServicesTags = wrapper.find(TraceServiceTag).length; expect(numberOfSpanText).toBe('5 spans'); expect(numberOfServicesTags).toBe(1); diff --git a/src/components/SearchTracePage/TraceServiceTag.js b/src/components/SearchTracePage/TraceServiceTag.js index ecd8d8c080..c6c96de49c 100644 --- a/src/components/SearchTracePage/TraceServiceTag.js +++ b/src/components/SearchTracePage/TraceServiceTag.js @@ -25,10 +25,7 @@ import colorGenerator from '../../utils/color-generator'; export default function TraceServiceTag({ service }) { const { name, numberOfApperancesInTrace } = service; return ( -
+
{name} ({numberOfApperancesInTrace})
); diff --git a/src/components/SearchTracePage/index.js b/src/components/SearchTracePage/index.js index a8d9b3bcce..aef24cf6a1 100644 --- a/src/components/SearchTracePage/index.js +++ b/src/components/SearchTracePage/index.js @@ -47,16 +47,11 @@ import getLastXformCacher from '../../utils/get-last-xform-cacher'; /** * Contains the dropdown to sort and filter trace search results */ -let TraceResultsFilterForm = () => ( +let TraceResultsFilterForm = () =>
- + @@ -64,17 +59,14 @@ let TraceResultsFilterForm = () => (
-
-); +
; TraceResultsFilterForm = reduxForm({ form: 'traceResultsFilters', initialValues: { sortBy: MOST_RECENT, }, })(TraceResultsFilterForm); -const traceResultsFiltersFormSelector = formValueSelector( - 'traceResultsFilters' -); +const traceResultsFiltersFormSelector = formValueSelector('traceResultsFilters'); export default class SearchTracePage extends Component { componentDidMount() { @@ -98,14 +90,8 @@ export default class SearchTracePage extends Component { return (
- -
+ +

Find Traces

@@ -121,10 +107,7 @@ export default class SearchTracePage extends Component {
} {isHomepage && !hasTraceResults && -
+
presentation
@@ -133,9 +116,7 @@ export default class SearchTracePage extends Component { !hasTraceResults && !loading && !errorMessage && -
- No trace results. Try another query. -
} +
No trace results. Try another query.
} {hasTraceResults && !loading &&
@@ -153,15 +134,10 @@ export default class SearchTracePage extends Component { }} />
-
+
- {numberOfTraceResults} - {' '} - Trace + {numberOfTraceResults} Trace {numberOfTraceResults > 1 && 's'}
@@ -173,19 +149,16 @@ export default class SearchTracePage extends Component {
    - {traceResults.map(trace => ( + {traceResults.map(trace =>
  • - ))} + )}
} @@ -227,11 +200,7 @@ const stateTraceXformer = getLastXformCacher(stateTrace => { }); const stateServicesXformer = getLastXformCacher(stateServices => { - const { - services: serviceList, - operationsForService: opsBySvc, - error: serviceError, - } = stateServices.toJS(); + const { services: serviceList, operationsForService: opsBySvc, error: serviceError } = stateServices.toJS(); const services = serviceList.map(name => ({ name, operations: opsBySvc[name] || [], @@ -247,9 +216,7 @@ function mapStateToProps(state) { const { services, serviceError } = stateServicesXformer(state.services); const sortBy = traceResultsFiltersFormSelector(state, 'sortBy'); const traceResultsSorted = getSortedTraceResults(traces, sortBy); - const errorMessage = serviceError || traceError - ? `${serviceError || ''} ${traceError || ''}` - : ''; + const errorMessage = serviceError || traceError ? `${serviceError || ''} ${traceError || ''}` : ''; return { isHomepage, @@ -265,17 +232,11 @@ function mapStateToProps(state) { } function mapDispatchToProps(dispatch) { - const { searchTraces, fetchServices } = bindActionCreators( - jaegerApiActions, - dispatch - ); + const { searchTraces, fetchServices } = bindActionCreators(jaegerApiActions, dispatch); return { searchTraces, fetchServices, }; } -export const ConnectedSearchTracePage = connect( - mapStateToProps, - mapDispatchToProps -)(SearchTracePage); +export const ConnectedSearchTracePage = connect(mapStateToProps, mapDispatchToProps)(SearchTracePage); diff --git a/src/components/SearchTracePage/index.test.js b/src/components/SearchTracePage/index.test.js index f6852b976a..8168bc0c83 100644 --- a/src/components/SearchTracePage/index.test.js +++ b/src/components/SearchTracePage/index.test.js @@ -30,25 +30,18 @@ const SCATTER_PLOT = 'SCATTER_PLOT'; const defaultProps = { sortTracesBy: 'LONGEST_FIRST', traceResultsChartType: SCATTER_PLOT, - traceResults: [ - { traceID: 'a', spans: [], processes: {} }, - { traceID: 'b', spans: [], processes: {} }, - ], + traceResults: [{ traceID: 'a', spans: [], processes: {} }, { traceID: 'b', spans: [], processes: {} }], numberOfTraceResults: 0, maxTraceDuration: 100, }; it('should show default message when there are no results', () => { - const wrapper = shallow( - - ); + const wrapper = shallow(); expect(wrapper.find('.trace-search--no-results').length).toBe(1); }); it('renders the a SCATTER_PLOT chart', () => { - const wrapper = shallow( - - ); + const wrapper = shallow(); expect(wrapper.find(TraceResultsScatterPlot).length).toBe(1); }); diff --git a/src/components/SpanGraph/SpanGraphSpan.js b/src/components/SpanGraph/SpanGraphSpan.js index f8ee787d85..df9b6b4212 100644 --- a/src/components/SpanGraph/SpanGraphSpan.js +++ b/src/components/SpanGraph/SpanGraphSpan.js @@ -24,15 +24,8 @@ import shallowCompare from 'react-addons-shallow-compare'; import spanPropTypes from '../../propTypes/span'; import colorGenerator from '../../utils/color-generator'; -import { - getPercentageOfDuration, - getPercentageOfInterval, -} from '../../utils/date'; -import { - getSpanTimestamp, - getSpanDuration, - getSpanServiceName, -} from '../../selectors/span'; +import { getPercentageOfDuration, getPercentageOfInterval } from '../../utils/date'; +import { getSpanTimestamp, getSpanDuration, getSpanServiceName } from '../../selectors/span'; export const MIN_SPAN_WIDTH = 0.2; // in percent @@ -74,30 +67,28 @@ export default class SpanGraphSpan extends Component { const topOffset = index * (rowHeight + rowPadding * 2) + rowPadding * 2; const spanTimestamp = getSpanTimestamp(span); const spanDuration = getSpanDuration(span); - const leftOffset = getPercentageOfInterval( - spanTimestamp, - initialTimestamp, - totalDuration - ); + const leftOffset = getPercentageOfInterval(spanTimestamp, initialTimestamp, totalDuration); const width = getPercentageOfDuration(spanDuration, totalDuration); // wrap all "onWhatever" handlers to pass the span along as the first argument. // attach any other props to the spreadable object - const handlerFilter = name => - typeof rest[name] === 'function' && name.substr(0, 2) === 'on'; - const handlers = Object.keys(rest).filter(handlerFilter).reduce(( - obj, - fnName - ) => - Object.assign(obj, { - [fnName]: (...args) => rest[fnName](span, ...args), - }), {}); + const handlerFilter = name => typeof rest[name] === 'function' && name.substr(0, 2) === 'on'; + const handlers = Object.keys(rest).filter(handlerFilter).reduce( + (obj, fnName) => + Object.assign(obj, { + [fnName]: (...args) => rest[fnName](span, ...args), + }), + {} + ); const spreadable = Object.keys(rest) .filter(name => !handlerFilter(name)) .reduce((obj, name) => Object.assign(obj, { [name]: rest[name] }), {}); return ( - {label && {label}} + {label && + + {label} + } should calculate the top offset for the index', () => { expect(rect.prop('y')).toBe(14); // (4 * (15 + 6)) + 6. - wrapper = shallow( - - ); + wrapper = shallow(); rect = wrapper.find('rect').first(); expect(rect.prop('y')).toBe(90); @@ -133,9 +131,7 @@ it(' should decorate handlers with the span', () => { expect(passedEvent).toEqual(event); } - const wrapper = shallow( - - ); + const wrapper = shallow(); const rect = wrapper.find('rect').first(); rect.props().onClick(event); diff --git a/src/components/SpanGraph/SpanGraphTick.js b/src/components/SpanGraph/SpanGraphTick.js index ef4e132fec..e41307028f 100644 --- a/src/components/SpanGraph/SpanGraphTick.js +++ b/src/components/SpanGraph/SpanGraphTick.js @@ -47,12 +47,7 @@ export default class SpanGraphTick extends Component { } render() { - const { - color, - initialTimestamp, - tick, - totalDuration, - } = this.props; + const { color, initialTimestamp, tick, totalDuration } = this.props; const { timestamp, width = DEFAULT_TICK_WIDTH, ...rest } = tick; const timeSinceSpanStart = timestamp - initialTimestamp; const x = getPercentageOfDuration(timeSinceSpanStart, totalDuration); diff --git a/src/components/SpanGraph/SpanGraphTick.test.js b/src/components/SpanGraph/SpanGraphTick.test.js index c79e7b7a97..e0c7f920da 100644 --- a/src/components/SpanGraph/SpanGraphTick.test.js +++ b/src/components/SpanGraph/SpanGraphTick.test.js @@ -119,10 +119,7 @@ it(' should push the x value over if this is at the totalDurati it(' should spread unhandled tick properties', () => { const wrapper = shallow( - + ); const line = wrapper.find('line').first(); expect(line.prop('stroke')).toBe('black'); @@ -136,12 +133,7 @@ it(' should make the width of the tick based on the tick defini line = wrapper.find('line').first(); expect(line.prop('strokeWidth')).toBe(3); - wrapper = shallow( - - ); + wrapper = shallow(); line = wrapper.find('line').first(); expect(line.prop('strokeWidth')).toBe(8); }); diff --git a/src/components/SpanGraph/SpanGraphTickHeader.js b/src/components/SpanGraph/SpanGraphTickHeader.js index 467d4ff60f..a0777e902b 100644 --- a/src/components/SpanGraph/SpanGraphTickHeader.js +++ b/src/components/SpanGraph/SpanGraphTickHeader.js @@ -38,7 +38,8 @@ export default class SpanGraphTickHeader extends Component { render() { const { ticks, trace } = this.props; - return trace && + return ( + trace &&
{ticks.map(tick => { const leftOffset = getPercentageOfInterval( @@ -47,9 +48,7 @@ export default class SpanGraphTickHeader extends Component { getTraceDuration(trace) ); - const style = Math.ceil(leftOffset) === 100 - ? { right: '0%' } - : { left: `${leftOffset}%` }; + const style = Math.ceil(leftOffset) === 100 ? { right: '0%' } : { left: `${leftOffset}%` }; return ( ); })} -
; +
+ ); } } diff --git a/src/components/SpanGraph/SpanGraphTickHeader.test.js b/src/components/SpanGraph/SpanGraphTickHeader.test.js index b570af3a51..4fd956117c 100644 --- a/src/components/SpanGraph/SpanGraphTickHeader.test.js +++ b/src/components/SpanGraph/SpanGraphTickHeader.test.js @@ -76,8 +76,5 @@ it(' should place the middle ticks at proper intervals', }); it(' should not explode if no trace is present', () => { - expect(() => - shallow( - - )).not.toThrow(); + expect(() => shallow()).not.toThrow(); }); diff --git a/src/components/SpanGraph/SpanGraphTickHeaderLabel.test.js b/src/components/SpanGraph/SpanGraphTickHeaderLabel.test.js index d1cff36132..fff37d23ec 100644 --- a/src/components/SpanGraph/SpanGraphTickHeaderLabel.test.js +++ b/src/components/SpanGraph/SpanGraphTickHeaderLabel.test.js @@ -51,9 +51,7 @@ it(' should render the duration as text', () => { const wrapper = shallow(); const div = wrapper.find('div').first(); - expect(div.prop('children')).toBe( - formatDurationForTrace({ trace, duration }) - ); + expect(div.prop('children')).toBe(formatDurationForTrace({ trace, duration })); }); it(' should pass the style through', () => { diff --git a/src/components/SpanGraph/index.js b/src/components/SpanGraph/index.js index 55c437cd5a..6339bd6d97 100644 --- a/src/components/SpanGraph/index.js +++ b/src/components/SpanGraph/index.js @@ -27,49 +27,40 @@ import SpanGraphSpan from './SpanGraphSpan'; import tracePropTypes from '../../propTypes/trace'; import spanPropTypes from '../../propTypes/span'; import spanGraphTickPropTypes from '../../propTypes/spanGraphTick'; -import { - getTraceId, - getTraceDuration, - getTraceTimestamp, - getTraceSpans, -} from '../../selectors/trace'; +import { getTraceId, getTraceDuration, getTraceTimestamp, getTraceSpans } from '../../selectors/trace'; import { getSpanId } from '../../selectors/span'; -export default function SpanGraph( - { - trace, - getSpanLabel, - rowHeight, - rowPadding, - ticks, - spans = getTraceSpans(trace), - onSpanClick, - children, - ...rest - } -) { +export default function SpanGraph({ + trace, + getSpanLabel, + rowHeight, + rowPadding, + ticks, + spans = getTraceSpans(trace), + onSpanClick, + children, + ...rest +}) { let childElements = children; // grab handler functions for spans (such as onSpanClick) off of the // rest of the props and build an object with them to be applied to the spans const spanHandlerFilter = name => - typeof rest[name] === 'function' && - name.substr(0, 2) === 'on' && - name.substr(-4) === 'Span'; + typeof rest[name] === 'function' && name.substr(0, 2) === 'on' && name.substr(-4) === 'Span'; const spreadable = Object.keys(rest) .filter(name => !spanHandlerFilter(name)) .reduce((obj, name) => Object.assign(obj, { [name]: rest[name] }), {}); if (!childElements) { - const spanHandlers = Object.keys(rest).filter(spanHandlerFilter).reduce(( - obj, - fnName - ) => - Object.assign(obj, { - [fnName.substr(0, fnName.length - 'Span'.length)]: rest[fnName], - }), {}); + const spanHandlers = Object.keys(rest).filter(spanHandlerFilter).reduce( + (obj, fnName) => + Object.assign(obj, { + [fnName.substr(0, fnName.length - 'Span'.length)]: rest[fnName], + }), + {} + ); - childElements = spans.map((span, idx) => ( + childElements = spans.map((span, idx) => onSpanClick(span.spanID)} key={`trace-${getTraceId(trace)}-span-${getSpanId(span)}`} @@ -82,7 +73,7 @@ export default function SpanGraph( rowPadding={rowPadding} {...spanHandlers} /> - )); + ); } const height = (rowHeight + rowPadding * 2) * Children.count(childElements); @@ -95,14 +86,14 @@ export default function SpanGraph( style={{ marginBottom: -2 * rowPadding }} {...spreadable} > - {ticks.map((tick, idx) => ( + {ticks.map((tick, idx) => - ))} + )} {childElements} diff --git a/src/components/SpanGraph/index.test.js b/src/components/SpanGraph/index.test.js index 1b10f8afd2..93d2f45126 100644 --- a/src/components/SpanGraph/index.test.js +++ b/src/components/SpanGraph/index.test.js @@ -95,9 +95,7 @@ it(' should attach "onSomethingSpan" handlers with to the spans expect(true).toBeTruthy(); } - const wrapper = shallow( - - ); + const wrapper = shallow(); wrapper.find(SpanGraphSpan).first().props().onClick(); }); diff --git a/src/components/TracePage/TimelineScrubber.js b/src/components/TracePage/TimelineScrubber.js index 687db148e0..86d9a2f42f 100644 --- a/src/components/TracePage/TimelineScrubber.js +++ b/src/components/TracePage/TimelineScrubber.js @@ -30,23 +30,17 @@ const HANDLE_HEIGHT = 20; const HANDLE_TOP_OFFSET = 0; const LINE_WIDTH = 2; -export default function TimelineScrubber( - { - trace, - timestamp, - onMouseDown, - handleTopOffset = HANDLE_TOP_OFFSET, - handleWidth = HANDLE_WIDTH, - handleHeight = HANDLE_HEIGHT, - } -) { +export default function TimelineScrubber({ + trace, + timestamp, + onMouseDown, + handleTopOffset = HANDLE_TOP_OFFSET, + handleWidth = HANDLE_WIDTH, + handleHeight = HANDLE_HEIGHT, +}) { const initialTimestamp = getTraceTimestamp(trace); const totalDuration = getTraceDuration(trace); - const xPercentage = getPercentageOfInterval( - timestamp, - initialTimestamp, - totalDuration - ); + const xPercentage = getPercentageOfInterval(timestamp, initialTimestamp, totalDuration); return ( @@ -74,11 +68,7 @@ export default function TimelineScrubber( cx={`${xPercentage}%`} cy={'50%'} /> - + should contain the proper svg components', () => { }); it(' should calculate the correct x% for a timestamp', () => { - const timestamp = getTraceDuration(generatedTrace) * 0.5 + - getTraceTimestamp(generatedTrace); + const timestamp = getTraceDuration(generatedTrace) * 0.5 + getTraceTimestamp(generatedTrace); - const wrapper = shallow( - - ); + const wrapper = shallow(); const line = wrapper.find('line').first(); const rect = wrapper.find('rect').first(); diff --git a/src/components/TracePage/TracePageHeader.js b/src/components/TracePage/TracePageHeader.js index c513ab8d43..ac495ee033 100644 --- a/src/components/TracePage/TracePageHeader.js +++ b/src/components/TracePage/TracePageHeader.js @@ -41,11 +41,7 @@ function MoreTraceOptionsDropdown({ traceID }) { - + View Trace JSON @@ -68,8 +64,7 @@ export const HEADER_ITEMS = [ { key: 'duration', title: 'Duration', - renderer: trace => - formatDurationForTrace({ trace, duration: getTraceDuration(trace) }), + renderer: trace => formatDurationForTrace({ trace, duration: getTraceDuration(trace) }), }, { key: 'service-count', @@ -103,9 +98,7 @@ export default function TracePageHeader(

onSlimViewClicked()}> @@ -129,12 +122,16 @@ export default function TracePageHeader(

{!slimView &&
- {HEADER_ITEMS.map(({ renderer, title, ...itemProps }) => ( + {HEADER_ITEMS.map(({ renderer, title, ...itemProps }) =>
- {title}:{' '} - {renderer(trace)} + + {title}:{' '} + + + {renderer(trace)} +
- ))} + )}
} ); diff --git a/src/components/TracePage/TracePageHeader.test.js b/src/components/TracePage/TracePageHeader.test.js index d568f9a726..d0905c39a6 100644 --- a/src/components/TracePage/TracePageHeader.test.js +++ b/src/components/TracePage/TracePageHeader.test.js @@ -38,44 +38,30 @@ const defaultOptions = { }; it(' should render a
', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); expect(wrapper.find('header').length).toBe(1); }); it(' should render an empty
if no trace present', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); expect(wrapper.matchesElement(
)).toBeTruthy(); }); it(' should render the trace title', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); const h2 = wrapper.find('h2').first(); expect(h2.contains(getTraceName(defaultProps.trace))).toBeTruthy(); }); it(' should render the header items', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); wrapper.find('.horizontal .item').forEach((item, idx) => { expect(item.contains(HEADER_ITEMS[idx].title)).toBeTruthy(); - expect( - item.contains(HEADER_ITEMS[idx].renderer(defaultProps.trace)) - ).toBeTruthy(); + expect(item.contains(HEADER_ITEMS[idx].renderer(defaultProps.trace))).toBeTruthy(); }); }); diff --git a/src/components/TracePage/TracePageTimeline.js b/src/components/TracePage/TracePageTimeline.js index 1f3bee3236..2105c7ea39 100644 --- a/src/components/TracePage/TracePageTimeline.js +++ b/src/components/TracePage/TracePageTimeline.js @@ -76,15 +76,9 @@ export default class TracePageTimeline extends Component { } shouldComponentUpdate( - { - trace: newTrace, - }, - { - currentlyDragging: newCurrentlyDragging, - }, - { - timeRangeFilter: newTimeRangeFilter, - } + { trace: newTrace }, + { currentlyDragging: newCurrentlyDragging }, + { timeRangeFilter: newTimeRangeFilter } ) { const { trace } = this.props; const { currentlyDragging } = this.state; @@ -94,10 +88,12 @@ export default class TracePageTimeline extends Component { const newLeftBound = newTimeRangeFilter[0]; const newRightBound = newTimeRangeFilter[1]; - return getTraceId(trace) !== getTraceId(newTrace) || + return ( + getTraceId(trace) !== getTraceId(newTrace) || leftBound !== newLeftBound || rightBound !== newRightBound || - currentlyDragging !== newCurrentlyDragging; + currentlyDragging !== newCurrentlyDragging + ); } onMouseMove({ clientX }) { @@ -177,17 +173,12 @@ export default class TracePageTimeline extends Component { let leftInactive; if (leftBound) { - leftInactive = getPercentageOfInterval( - leftBound, - initialTimestamp, - traceDuration - ); + leftInactive = getPercentageOfInterval(leftBound, initialTimestamp, traceDuration); } let rightInactive; if (rightBound) { - rightInactive = 100 - - getPercentageOfInterval(rightBound, initialTimestamp, traceDuration); + rightInactive = 100 - getPercentageOfInterval(rightBound, initialTimestamp, traceDuration); } return ( @@ -243,8 +234,7 @@ export default class TracePageTimeline extends Component { handleWidth={8} handleHeight={30} handleTopOffset={10} - onMouseDown={(...args) => - this.startDragging('leftBound', ...args)} + onMouseDown={(...args) => this.startDragging('leftBound', ...args)} />} {rightBound && - this.startDragging('rightBound', ...args)} + onMouseDown={(...args) => this.startDragging('rightBound', ...args)} />}
diff --git a/src/components/TracePage/TracePageTimeline.test.js b/src/components/TracePage/TracePageTimeline.test.js index 91e6801ed6..fedb4c0d91 100644 --- a/src/components/TracePage/TracePageTimeline.test.js +++ b/src/components/TracePage/TracePageTimeline.test.js @@ -29,10 +29,8 @@ import TimelineScrubber from './TimelineScrubber'; import traceGenerator from '../../../src/demo/trace-generators'; const listeners = {}; -const addEventListener = sinon.spy((name, fn) => - Object.assign(listeners, { [name]: fn })); -const removeEventListener = sinon.spy((name, fn) => - Object.assign(listeners, { [name]: fn })); +const addEventListener = sinon.spy((name, fn) => Object.assign(listeners, { [name]: fn })); +const removeEventListener = sinon.spy((name, fn) => Object.assign(listeners, { [name]: fn })); const clearListeners = () => Object.keys(listeners).forEach(key => { delete listeners[key]; @@ -85,28 +83,19 @@ const defaultOptions = { }; it(' should render a ', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); expect(wrapper.find(SpanGraph).length).toBe(1); }); it(' should render a ', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); expect(wrapper.find(SpanGraphTickHeader).length).toBe(1); }); it(' should just return a
if no trace is present', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); expect(wrapper.matchesElement(
)).toBeTruthy(); }); @@ -122,13 +111,7 @@ it(' should render a filtering box if leftBound exists', () expect( wrapper.containsMatchingElement( - + ) ).toBeTruthy(); }); @@ -144,22 +127,13 @@ it(' should render a filtering box if rightBound exists', ( expect( wrapper.containsMatchingElement( - + ) ).toBeTruthy(); }); it(' should render handles for the timeRangeFilter', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); expect( wrapper.containsMatchingElement( @@ -174,39 +148,25 @@ it(' should render handles for the timeRangeFilter', () => }); it(' should call startDragging for the leftBound handle', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); const event = { clientX: 50 }; sinon.stub(wrapper.instance(), 'startDragging'); - wrapper.find('#trace-page-timeline__left-bound-handle').prop('onMouseDown')( - event - ); + wrapper.find('#trace-page-timeline__left-bound-handle').prop('onMouseDown')(event); - expect( - wrapper.instance().startDragging.calledWith('leftBound', event) - ).toBeTruthy(); + expect(wrapper.instance().startDragging.calledWith('leftBound', event)).toBeTruthy(); }); it(' should call startDragging for the rightBound handle', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); const event = { clientX: 50 }; sinon.stub(wrapper.instance(), 'startDragging'); - wrapper.find('#trace-page-timeline__right-bound-handle').prop('onMouseDown')( - event - ); + wrapper.find('#trace-page-timeline__right-bound-handle').prop('onMouseDown')(event); - expect( - wrapper.instance().startDragging.calledWith('rightBound', event) - ).toBeTruthy(); + expect(wrapper.instance().startDragging.calledWith('rightBound', event)).toBeTruthy(); }); it(' should render without handles if no filtering', () => { @@ -230,10 +190,7 @@ it(' should timeline-sort the trace before rendering', () = defaultProps.trace.spans[1], ]; - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); const spanGraph = wrapper.find(SpanGraph).first(); expect(spanGraph.prop('spans')).toEqual(sortedTraceSpans); @@ -250,10 +207,7 @@ it(' should create ticks and pass them to components', () = { timestamp: timestamp + 50000, width: 2 }, ]; - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); const spanGraph = wrapper.find(SpanGraph).first(); const spanGraphTickHeader = wrapper.find(SpanGraphTickHeader).first(); @@ -262,40 +216,28 @@ it(' should create ticks and pass them to components', () = }); it(' should calculate the rowHeight', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); const spanGraph = wrapper.find(SpanGraph).first(); expect(spanGraph.prop('rowHeight')).toBe(50 / 3); }); it(' should pass the props through to SpanGraph', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); const spanGraph = wrapper.find(SpanGraph).first(); expect(spanGraph.prop('rowPadding')).toBe(0); }); it(' should pass the props through to SpanGraphTickHeader', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); const spanGraphTickHeader = wrapper.find(SpanGraphTickHeader).first(); expect(spanGraphTickHeader.prop('trace')).toEqual(defaultProps.trace); }); it('TracePageTimeline.shouldComponentUpdate should return true for new timeRange', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); expect( wrapper.instance().shouldComponentUpdate(defaultProps, wrapper.state(), { @@ -305,10 +247,7 @@ it('TracePageTimeline.shouldComponentUpdate should return true for new timeRange }); it('TracePageTimeline.shouldComponentUpdate should return true for new traces', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); expect( wrapper @@ -322,10 +261,7 @@ it('TracePageTimeline.shouldComponentUpdate should return true for new traces', }); it('TracePageTimeline.shouldComponentUpdate should return true for currentlyDragging', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); expect( wrapper.instance().shouldComponentUpdate( @@ -340,19 +276,10 @@ it('TracePageTimeline.shouldComponentUpdate should return true for currentlyDrag }); it('TracePageTimeline.shouldComponentUpdate should return false otherwise', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); expect( - wrapper - .instance() - .shouldComponentUpdate( - defaultProps, - wrapper.state(), - defaultOptions.context - ) + wrapper.instance().shouldComponentUpdate(defaultProps, wrapper.state(), defaultOptions.context) ).toBe(false); }); @@ -376,10 +303,7 @@ it('TracePageTimeline.onMouseMove should do nothing if currentlyDragging is fals }); it('TracePageTimeline.onMouseMove should store the clientX on the state', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); wrapper.instance().svg = { clientWidth: 100 }; wrapper.setState({ currentlyDragging: 'leftBound' }); @@ -404,9 +328,7 @@ it('TracePageTimeline.onMouseMove should update the timeRangeFilter for the left wrapper.instance().onMouseMove({ clientX: 45 }); - expect( - updateTimeRangeFilter.calledWith(timestamp + 22500, timestamp + 50000) - ).toBeTruthy(); + expect(updateTimeRangeFilter.calledWith(timestamp + 22500, timestamp + 50000)).toBeTruthy(); }); it('TracePageTimeline.onMouseMove should update the timeRangeFilter for the right handle', () => { @@ -424,16 +346,11 @@ it('TracePageTimeline.onMouseMove should update the timeRangeFilter for the righ wrapper.instance().onMouseMove({ clientX: 45 }); - expect( - updateTimeRangeFilter.calledWith(timestamp, timestamp + 22500) - ).toBeTruthy(); + expect(updateTimeRangeFilter.calledWith(timestamp, timestamp + 22500)).toBeTruthy(); }); it('TracePageTimeline.startDragging should store the boundName and the prevX in state', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); wrapper.instance().startDragging('leftBound', { clientX: 100 }); @@ -442,96 +359,61 @@ it('TracePageTimeline.startDragging should store the boundName and the prevX in }); // TODO: Need to figure out how to mock to window events. -it.skip( - 'TracePageTimeline.startDragging should bind event listeners to the window', - () => { - const wrapper = shallow( - , - defaultOptions - ); - - clearListeners(); - - wrapper.instance().startDragging('leftBound', { clientX: 100 }); - - expect( - addEventListener.calledWith('mousemove', sinon.match.func) - ).toBeTruthy(); - expect( - addEventListener.calledWith('mouseup', sinon.match.func) - ).toBeTruthy(); - } -); - -it.skip( - 'TracePageTimeline.startDragging should call onMouseMove on the window', - () => { - const wrapper = shallow( - , - defaultOptions - ); - - clearListeners(); - - wrapper.instance().startDragging('leftBound', { clientX: 100 }); - sinon.stub(wrapper.instance(), 'onMouseMove'); - - const event = { clientX: 99 }; - listeners.mousemove(event); - - expect(wrapper.instance().onMouseMove.calledWith(event)).toBeTruthy(); - } -); - -it.skip( - 'TracePageTimeline.startDragging mouseup should call stopDragging', - () => { - const wrapper = shallow( - , - defaultOptions - ); - - clearListeners(); - - wrapper.instance().startDragging('leftBound', { clientX: 100 }); - sinon.stub(wrapper.instance(), 'stopDragging'); - - const event = { clientX: 99 }; - listeners.mouseup(event); - - expect(wrapper.instance().stopDragging.called).toBeTruthy(); - } -); - -it.skip( - 'TracePageTimeline.startDragging mouseup should stop listening to the events', - () => { - const wrapper = shallow( - , - defaultOptions - ); - - clearListeners(); - - wrapper.instance().startDragging('leftBound', { clientX: 100 }); - - const event = { clientX: 99 }; - listeners.mouseup(event); - - expect( - removeEventListener.calledWith('mousemove', sinon.match.func) - ).toBeTruthy(); - expect( - removeEventListener.calledWith('mouseup', sinon.match.func) - ).toBeTruthy(); - } -); +it.skip('TracePageTimeline.startDragging should bind event listeners to the window', () => { + const wrapper = shallow(, defaultOptions); + + clearListeners(); + + wrapper.instance().startDragging('leftBound', { clientX: 100 }); + + expect(addEventListener.calledWith('mousemove', sinon.match.func)).toBeTruthy(); + expect(addEventListener.calledWith('mouseup', sinon.match.func)).toBeTruthy(); +}); + +it.skip('TracePageTimeline.startDragging should call onMouseMove on the window', () => { + const wrapper = shallow(, defaultOptions); + + clearListeners(); + + wrapper.instance().startDragging('leftBound', { clientX: 100 }); + sinon.stub(wrapper.instance(), 'onMouseMove'); + + const event = { clientX: 99 }; + listeners.mousemove(event); + + expect(wrapper.instance().onMouseMove.calledWith(event)).toBeTruthy(); +}); + +it.skip('TracePageTimeline.startDragging mouseup should call stopDragging', () => { + const wrapper = shallow(, defaultOptions); + + clearListeners(); + + wrapper.instance().startDragging('leftBound', { clientX: 100 }); + sinon.stub(wrapper.instance(), 'stopDragging'); + + const event = { clientX: 99 }; + listeners.mouseup(event); + + expect(wrapper.instance().stopDragging.called).toBeTruthy(); +}); + +it.skip('TracePageTimeline.startDragging mouseup should stop listening to the events', () => { + const wrapper = shallow(, defaultOptions); + + clearListeners(); + + wrapper.instance().startDragging('leftBound', { clientX: 100 }); + + const event = { clientX: 99 }; + listeners.mouseup(event); + + expect(removeEventListener.calledWith('mousemove', sinon.match.func)).toBeTruthy(); + expect(removeEventListener.calledWith('mouseup', sinon.match.func)).toBeTruthy(); +}); it('TracePageTimeline.stopDragging should clear currentlyDragging and prevX', () => { - const wrapper = shallow( - , - defaultOptions - ); + const wrapper = shallow(, defaultOptions); wrapper.instance().stopDragging(); diff --git a/src/components/TracePage/TraceTimelineViewer/SpanBreakdownGraph.js b/src/components/TracePage/TraceTimelineViewer/SpanBreakdownGraph.js deleted file mode 100644 index f5e5e5a643..0000000000 --- a/src/components/TracePage/TraceTimelineViewer/SpanBreakdownGraph.js +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2017 Uber Technologies, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -import PropTypes from 'prop-types'; -import React from 'react'; -import SpanGraphTick from '../../SpanGraph/SpanGraphTick'; -import logPropTypes from '../../../propTypes/log'; - -export default function SpanBreakdownBar({ span }) { - const padding = 3; - const fontSize = 11; - return ( -
-
- - 0 ms - - - {span.duration} ms - -
- - {span.logs.map((log, i) => ( - - ))} - -
- ); -} - -SpanBreakdownBar.propTypes = { - span: PropTypes.shape({ - duration: PropTypes.number, - timestamp: PropTypes.number, - logs: PropTypes.arrayOf(logPropTypes), - }), -}; diff --git a/src/components/TracePage/TraceTimelineViewer/SpanDetail.js b/src/components/TracePage/TraceTimelineViewer/SpanDetail.js index c397df6ce6..8ed2a190aa 100644 --- a/src/components/TracePage/TraceTimelineViewer/SpanDetail.js +++ b/src/components/TracePage/TraceTimelineViewer/SpanDetail.js @@ -29,12 +29,7 @@ import { formatDuration } from './utils'; const collapseEnhancer = withState('open', 'onToggleOpen', false); function CollapsePanel(props) { - const { - header, - onToggleOpen, - children, - open, - } = props; + const { header, onToggleOpen, children, open } = props; return ( {open && @@ -95,10 +92,7 @@ function ExpandableDataTable(props) { } return ( - + {row.key} @@ -145,16 +139,14 @@ function Logs({ logs, traceStartTime, open, onToggleOpen }) {
{open &&
- {_.sortBy(logs, 'timestamp').map(log => ( + {_.sortBy(logs, 'timestamp').map(log => - ))} + )}
- - **Log timestamps are relative to the start time of the full trace. - + **Log timestamps are relative to the start time of the full trace.
}
@@ -180,19 +172,27 @@ export default function SpanDetail(props) { return (
-

{span.operationName}

+

+ {span.operationName} +

Service: - {span.process.serviceName} + + {span.process.serviceName} +
Duration: - {formatDuration(span.duration)} + + {formatDuration(span.duration)} +
Start Time: - {formatDuration(span.relativeStartTime)} + + {formatDuration(span.relativeStartTime)} +

@@ -202,10 +202,7 @@ export default function SpanDetail(props) { {span.process && span.process.tags && - } + }
{span.logs && span.logs.length > 0 && @@ -215,7 +212,9 @@ export default function SpanDetail(props) { - +
spanID{span.spanID} + {span.spanID} +
diff --git a/src/components/TracePage/TraceTimelineViewer/index.js b/src/components/TracePage/TraceTimelineViewer/index.js index 20c6dccd2c..ecec067886 100644 --- a/src/components/TracePage/TraceTimelineViewer/index.js +++ b/src/components/TracePage/TraceTimelineViewer/index.js @@ -21,13 +21,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import _ from 'lodash'; -import { - onlyUpdateForKeys, - compose, - withState, - withProps, - pure, -} from 'recompose'; +import { onlyUpdateForKeys, compose, withState, withProps, pure } from 'recompose'; import * as d3 from 'd3-scale'; import { filterSpansForText } from '../../../selectors/span'; import './grid.css'; @@ -50,8 +44,7 @@ import SpanDetail from './SpanDetail'; // TODO: Add unit tests // TODO: unify transforms and utils -const ensurePercentIsBetween0And100 = percent => - ensureWithinRange([0, 100], percent); +const ensurePercentIsBetween0And100 = percent => ensureWithinRange([0, 100], percent); /** * Components! @@ -140,7 +133,7 @@ function Ticks(props) { const margin = 5; return (
- {ticks.map(tick => ( + {ticks.map(tick =>
- ))} + )}
); } @@ -258,189 +251,152 @@ function TraceView(props) { } let collapseBelow = null; - const renderSpansRows = trace.spans.reduce( - (arr, span, i) => { - const { spanID } = span; - const showSpanDetails = selectedSpanIDs.has(spanID); - const spanHasChildren = span.hasChildren; - const spanIsCollapsed = collapsedSpanIDs.has(spanID); - const spanColor = colorGenerator.getColorByKey(span.process.serviceName); + const renderSpansRows = trace.spans.reduce((arr, span, i) => { + const { spanID } = span; + const showSpanDetails = selectedSpanIDs.has(spanID); + const spanHasChildren = span.hasChildren; + const spanIsCollapsed = collapsedSpanIDs.has(spanID); + const spanColor = colorGenerator.getColorByKey(span.process.serviceName); - let filterOutSpan = false; - if (filteredSpansIDs) { - filterOutSpan = !filteredSpansIDs.has(spanID); - } + let filterOutSpan = false; + if (filteredSpansIDs) { + filterOutSpan = !filteredSpansIDs.has(spanID); + } - // Collapse logic - // TODO: Investigate if this should be moved out to statefull component. - let hidden = false; - if (collapseBelow) { - if (span.depth >= collapseBelow) { - hidden = true; - } else { - collapseBelow = null; - } - } - if (spanIsCollapsed && !hidden) { - collapseBelow = span.depth + 1; - } - if (hidden) { - return arr; + // Collapse logic + // TODO: Investigate if this should be moved out to statefull component. + let hidden = false; + if (collapseBelow) { + if (span.depth >= collapseBelow) { + hidden = true; + } else { + collapseBelow = null; } + } + if (spanIsCollapsed && !hidden) { + collapseBelow = span.depth + 1; + } + if (hidden) { + return arr; + } - // Compute span position with given zoom. - const { xStart: startPercent, xEnd: endPercent } = calculateSpanPosition({ + // Compute span position with given zoom. + const { xStart: startPercent, xEnd: endPercent } = calculateSpanPosition({ + traceStartTime: trace.startTime, + traceEndTime: trace.endTime, + spanStart: span.startTime, + spanEnd: span.startTime + span.duration, + xStart: zoomStart, + xEnd: zoomEnd, + }); + + // Check for direct child "server" span if the span is a "client" span. + // TODO: Can probably optimize this a bit more so it does not do it + // on render. + const childServerSpan = findServerChildSpan(trace.spans.slice(i)); + let interval; + if (childServerSpan && spanIsCollapsed) { + const childSpanPosition = calculateSpanPosition({ traceStartTime: trace.startTime, traceEndTime: trace.endTime, - spanStart: span.startTime, - spanEnd: span.startTime + span.duration, + spanStart: childServerSpan.startTime, + spanEnd: childServerSpan.startTime + childServerSpan.duration, xStart: zoomStart, xEnd: zoomEnd, }); + const x = d3.scaleLinear().domain([startPercent, endPercent]).range([0, 100]); + interval = { + color: colorGenerator.getColorByKey(childServerSpan.process.serviceName), + startPercent: x(childSpanPosition.xStart), + endPercent: x(childSpanPosition.xEnd), + }; + } - // Check for direct child "server" span if the span is a "client" span. - // TODO: Can probably optimize this a bit more so it does not do it - // on render. - const childServerSpan = findServerChildSpan(trace.spans.slice(i)); - let interval; - if (childServerSpan && spanIsCollapsed) { - const childSpanPosition = calculateSpanPosition({ - traceStartTime: trace.startTime, - traceEndTime: trace.endTime, - spanStart: childServerSpan.startTime, - spanEnd: childServerSpan.startTime + childServerSpan.duration, - xStart: zoomStart, - xEnd: zoomEnd, - }); - const x = d3 - .scaleLinear() - .domain([startPercent, endPercent]) - .range([0, 100]); - interval = { - color: colorGenerator.getColorByKey( - childServerSpan.process.serviceName - ), - startPercent: x(childSpanPosition.xStart), - endPercent: x(childSpanPosition.xEnd), - }; - } - - const showErrorIcon = isErrorSpan(span) || - (spanIsCollapsed && spanContainsErredSpan(trace.spans, i)); - const backgroundColor = showSpanDetails ? 'whitesmoke' : null; - arr.push( - - -
+ +