Skip to content

Commit

Permalink
[APM] use react-redux-request (#24117)
Browse files Browse the repository at this point in the history
* [APM] use react-redux-request

* Stricter type checking
  • Loading branch information
sorenlouv committed Oct 18, 2018
1 parent 3474565 commit 6656f99
Show file tree
Hide file tree
Showing 15 changed files with 234 additions and 131 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@
"url": "https://github.com/elastic/kibana.git"
},
"resolutions": {
"**/@types/node": "8.10.21"
"**/@types/node": "8.10.21",
"@types/react": "16.3.14"
},
"dependencies": {
"@elastic/eui": "4.4.1",
Expand Down Expand Up @@ -210,9 +211,6 @@
"x-pack": "link:x-pack",
"yauzl": "2.7.0"
},
"resolutions": {
"@types/react": "16.3.14"
},
"devDependencies": {
"@babel/parser": "^7.1.0",
"@babel/types": "^7.0.0",
Expand Down Expand Up @@ -249,6 +247,7 @@
"@types/listr": "^0.13.0",
"@types/lodash": "^3.10.1",
"@types/minimatch": "^2.0.29",
"@types/moment-timezone": "^0.5.8",
"@types/node": "^8.10.20",
"@types/prop-types": "^15.5.3",
"@types/puppeteer": "^1.6.2",
Expand All @@ -262,6 +261,7 @@
"@types/semver": "^5.5.0",
"@types/sinon": "^5.0.1",
"@types/strip-ansi": "^3.0.0",
"@types/styled-components": "^3.0.1",
"@types/supertest": "^2.0.5",
"@types/type-detect": "^4.0.1",
"@types/uuid": "^3.4.4",
Expand Down
1 change: 0 additions & 1 deletion x-pack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,6 @@
"@samverschueren/stream-to-observable": "^0.3.0",
"@scant/router": "^0.1.0",
"@slack/client": "^4.2.2",
"@types/moment-timezone": "^0.5.8",
"angular-resource": "1.4.9",
"angular-sanitize": "1.4.9",
"angular-ui-ace": "0.2.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ export function getWaterfall(
entryTransaction: Transaction
): IWaterfall {
const items = hits
.filter(hit => {
const docType = hit.processor.event;
return ['span', 'transaction'].includes(docType);
})
.map(addVersion)
.map(hit => {
const docType = hit.processor.event;
Expand All @@ -122,10 +126,9 @@ export function getWaterfall(
case 'transaction':
return getTransactionItem(hit as Transaction);
default:
return null;
throw new Error(`Unknown type ${docType}`);
}
})
.filter(removeEmpty);
});

const entryTransactionItem = getTransactionItem(addVersion(entryTransaction));
const root = getWaterfallRoot(items, entryTransactionItem);
Expand All @@ -137,10 +140,6 @@ export function getWaterfall(
};
}

function removeEmpty<T>(value: T | null): value is T {
return value !== null;
}

function addVersion<T extends Transaction | Span>(hit: T): T {
hit.version = hit.hasOwnProperty('trace') ? 'v2' : 'v1';
return hit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { get } from 'lodash';
import React, { PureComponent } from 'react';
import React from 'react';
// @ts-ignore
import {
SERVICE_NAME,
Expand All @@ -14,8 +13,11 @@ import {
} from '../../../../../../common/constants';
import { Transaction } from '../../../../../../typings/Transaction';

import { RRRRender } from 'react-redux-request';
import { WaterfallV1Request } from 'x-pack/plugins/apm/public/store/reactReduxRequest/waterfallV1';
import { WaterfallV2Request } from 'x-pack/plugins/apm/public/store/reactReduxRequest/waterfallV2';
import { IUrlParams } from 'x-pack/plugins/apm/public/store/urlParams';
import { Span } from '../../../../../../typings/Span';
import { WaterfallResponse } from 'x-pack/plugins/apm/typings/waterfall';
// @ts-ignore
import { loadSpans, loadTrace } from '../../../../../services/rest/apm';
import { getServiceColors } from './getServiceColors';
Expand All @@ -29,107 +31,65 @@ interface Props {
location: any;
}

interface State {
services: string[];
hits: Array<Span | Transaction>;
interface WaterfallRequestProps {
urlParams: IUrlParams;
transaction: Transaction;
render: RRRRender<WaterfallResponse>;
}

export class WaterfallContainer extends PureComponent<Props, State> {
public state: Readonly<State> = {
services: [],
hits: []
};

public maybeFetchWaterfall = async (prevProps?: Props) => {
const hasTrace = this.props.transaction.hasOwnProperty('trace');
if (hasTrace) {
this.maybeFetchTrace(prevProps);
} else {
this.maybeFetchSpans(prevProps);
}
};

public maybeFetchSpans = async (prevProps = {} as Partial<Props>) => {
const { start, end } = this.props.urlParams;
const { start: prevStart, end: prevEnd } =
prevProps.urlParams || ({} as IUrlParams);

const serviceName: string = get(this.props.transaction, SERVICE_NAME);
const prevServiceName: string = get(prevProps.transaction, SERVICE_NAME);

const transactionId: string = get(this.props.transaction, TRANSACTION_ID);
const prevTransactionId: string = get(
prevProps.transaction,
TRANSACTION_ID
function WaterfallRequest({
urlParams,
transaction,
render
}: WaterfallRequestProps) {
const hasTrace = transaction.hasOwnProperty('trace');
if (hasTrace) {
return (
<WaterfallV2Request
urlParams={urlParams}
transaction={transaction}
render={render}
/>
);

if (
serviceName !== prevServiceName ||
transactionId !== prevTransactionId ||
start !== prevStart ||
end !== prevEnd
) {
const spans = await loadSpans({
serviceName,
transactionId,
start,
end
});

this.setState({
hits: [this.props.transaction, ...spans],
services: [serviceName]
});
}
};

public maybeFetchTrace = async (prevProps = {} as Partial<Props>) => {
const { start, end } = this.props.urlParams;
const { start: prevStart, end: prevEnd } =
prevProps.urlParams || ({} as IUrlParams);

const traceId = get(this.props, `transaction.${TRACE_ID}`);
const prevTraceId: string = get(prevProps, `transaction.${TRACE_ID}`);

if (
traceId &&
start &&
end &&
(traceId !== prevTraceId || start !== prevStart || end !== prevEnd)
) {
const { hits, services } = await loadTrace({ traceId, start, end });
this.setState({ hits, services });
}
};

public componentDidMount() {
this.maybeFetchWaterfall();
}

public async componentDidUpdate(prevProps: Props) {
this.maybeFetchWaterfall(prevProps);
}

public render() {
const { location, urlParams, transaction } = this.props;
const { hits, services } = this.state;
const waterfall = getWaterfall(hits, services, transaction);

if (!waterfall) {
return null;
}
const serviceColors = getServiceColors(waterfall.services);

} else {
return (
<div>
<ServiceLegends serviceColors={serviceColors} />
<Waterfall
location={location}
serviceColors={serviceColors}
urlParams={urlParams}
waterfall={waterfall}
/>
</div>
<WaterfallV1Request
urlParams={urlParams}
transaction={transaction}
render={render}
/>
);
}
}

export function WaterfallContainer({
location,
urlParams,
transaction
}: Props) {
return (
<WaterfallRequest
urlParams={urlParams}
transaction={transaction}
render={({ data }) => {
const waterfall = getWaterfall(data.hits, data.services, transaction);
if (!waterfall) {
return null;
}
const serviceColors = getServiceColors(waterfall.services);

return (
<div>
<ServiceLegends serviceColors={serviceColors} />
<Waterfall
location={location}
serviceColors={serviceColors}
urlParams={urlParams}
waterfall={waterfall}
/>
</div>
);
}}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function getErrorDistribution(state) {
export function ErrorDistributionRequest({ urlParams, render }) {
const { serviceName, start, end, errorGroupId, kuery } = urlParams;

if (!(serviceName, start, end, errorGroupId)) {
if (!(serviceName && start && end && errorGroupId)) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/

import React from 'react';
// @ts-ignore
import { Request } from 'react-redux-request';
import { IDistributionResponse } from '../../../server/lib/transactions/distribution/get_distribution';
// @ts-ignore
Expand Down
55 changes: 55 additions & 0 deletions x-pack/plugins/apm/public/store/reactReduxRequest/waterfallV1.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { get } from 'lodash';
import React from 'react';
import { Request, RRRRender } from 'react-redux-request';
import {
SERVICE_NAME,
TRANSACTION_ID
} from 'x-pack/plugins/apm/common/constants';
import { Span } from 'x-pack/plugins/apm/typings/Span';
import { Transaction } from 'x-pack/plugins/apm/typings/Transaction';
import { WaterfallResponse } from 'x-pack/plugins/apm/typings/waterfall';
// @ts-ignore
import { loadSpans, loadTrace } from '../../services/rest/apm';
import { IUrlParams } from '../urlParams';
// @ts-ignore
import { createInitialDataSelector } from './helpers';

const ID = 'waterfallV1';

interface Props {
urlParams: IUrlParams;
transaction: Transaction;
render: RRRRender<WaterfallResponse>;
}

export function WaterfallV1Request({ urlParams, transaction, render }: Props) {
const { start, end } = urlParams;
const transactionId: string = get(transaction, TRANSACTION_ID);
const serviceName: string = get(transaction, SERVICE_NAME);

if (!(serviceName && transactionId && start && end)) {
return null;
}

return (
<Request<Span[]>
id={ID}
fn={loadSpans}
args={[{ serviceName, start, end, transactionId }]}
render={({ status, data, args }) => {
const res = {
hits: [transaction, ...data],
services: [serviceName]
};

return render({ status, data: res, args });
}}
/>
);
}
47 changes: 47 additions & 0 deletions x-pack/plugins/apm/public/store/reactReduxRequest/waterfallV2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { get } from 'lodash';
import React from 'react';
import { Request, RRRRender } from 'react-redux-request';
import { TRACE_ID } from 'x-pack/plugins/apm/common/constants';
import { Transaction } from 'x-pack/plugins/apm/typings/Transaction';
import { WaterfallResponse } from 'x-pack/plugins/apm/typings/waterfall';

// @ts-ignore
import { loadSpans, loadTrace } from '../../services/rest/apm';
import { IUrlParams } from '../urlParams';
// @ts-ignore
import { createInitialDataSelector } from './helpers';

const ID = 'waterfallV2';

interface Props {
urlParams: IUrlParams;
transaction: Transaction;
render: RRRRender<WaterfallResponse>;
}

const defaultData = { hits: [], services: [] };
export function WaterfallV2Request({ urlParams, transaction, render }: Props) {
const { start, end } = urlParams;
const traceId: string = get(transaction, TRACE_ID);

if (!(traceId && start && end)) {
return null;
}

return (
<Request<WaterfallResponse>
id={ID}
fn={loadTrace}
args={[{ traceId, start, end }]}
render={({ args, data = defaultData, status }) =>
render({ args, data, status })
}
/>
);
}
1 change: 0 additions & 1 deletion x-pack/plugins/apm/public/store/rootReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/

// @ts-ignore
import { reducer } from 'react-redux-request';
import { combineReducers } from 'redux';
import { StringMap } from '../../typings/common';
Expand Down
Loading

0 comments on commit 6656f99

Please sign in to comment.