mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 02:09:32 -04:00
[APM] Convert most of remaining js to ts (#32115)
* [APM] Convert most of remaining js to ts * Fixes for distribution component * Make `page` and `sort` optional * Add Server definition from hapi
This commit is contained in:
parent
95a3284637
commit
aa71146252
36 changed files with 291 additions and 232 deletions
|
@ -4,18 +4,20 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { Server } from 'hapi';
|
||||
import { resolve } from 'path';
|
||||
import { initTransactionGroupsApi } from './server/routes/transaction_groups';
|
||||
import { initServicesApi } from './server/routes/services';
|
||||
import mappings from './mappings.json';
|
||||
import { makeApmUsageCollector } from './server/lib/apm_telemetry';
|
||||
import { initErrorsApi } from './server/routes/errors';
|
||||
import { initMetricsApi } from './server/routes/metrics';
|
||||
import { initServicesApi } from './server/routes/services';
|
||||
import { initStatusApi } from './server/routes/status_check';
|
||||
import { initTracesApi } from './server/routes/traces';
|
||||
import { initMetricsApi } from './server/routes/metrics';
|
||||
import mappings from './mappings';
|
||||
import { makeApmUsageCollector } from './server/lib/apm_telemetry';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { initTransactionGroupsApi } from './server/routes/transaction_groups';
|
||||
|
||||
export function apm(kibana) {
|
||||
// TODO: get proper types
|
||||
export function apm(kibana: any) {
|
||||
return new kibana.Plugin({
|
||||
require: ['kibana', 'elasticsearch', 'xpack_main', 'apm_oss'],
|
||||
id: 'apm',
|
||||
|
@ -35,7 +37,9 @@ export function apm(kibana) {
|
|||
},
|
||||
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
|
||||
home: ['plugins/apm/register_feature'],
|
||||
injectDefaultVars(server) {
|
||||
|
||||
// TODO: get proper types
|
||||
injectDefaultVars(server: Server) {
|
||||
const config = server.config();
|
||||
return {
|
||||
apmUiEnabled: config.get('xpack.apm.ui.enabled'),
|
||||
|
@ -51,7 +55,8 @@ export function apm(kibana) {
|
|||
mappings
|
||||
},
|
||||
|
||||
config(Joi) {
|
||||
// TODO: get proper types
|
||||
config(Joi: any) {
|
||||
return Joi.object({
|
||||
// display menu item
|
||||
ui: Joi.object({
|
||||
|
@ -68,7 +73,8 @@ export function apm(kibana) {
|
|||
}).default();
|
||||
},
|
||||
|
||||
init(server) {
|
||||
// TODO: get proper types
|
||||
init(server: any) {
|
||||
initTransactionGroupsApi(server);
|
||||
initTracesApi(server);
|
||||
initServicesApi(server);
|
|
@ -7,10 +7,32 @@
|
|||
import { EuiTitle } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
// @ts-ignore
|
||||
import Histogram from '../../../shared/charts/Histogram';
|
||||
import { EmptyMessage } from '../../../shared/EmptyMessage';
|
||||
|
||||
export function getFormattedBuckets(buckets, bucketSize) {
|
||||
interface IBucket {
|
||||
key: number;
|
||||
count: number;
|
||||
}
|
||||
|
||||
// TODO: cleanup duplication of this in distribution/get_distribution.ts (ErrorDistributionAPIResponse) and transactions/distribution/index.ts (ITransactionDistributionAPIResponse)
|
||||
interface IDistribution {
|
||||
totalHits: number;
|
||||
buckets: IBucket[];
|
||||
bucketSize: number;
|
||||
}
|
||||
|
||||
interface FormattedBucket {
|
||||
x0: number;
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
export function getFormattedBuckets(
|
||||
buckets: IBucket[],
|
||||
bucketSize: number
|
||||
): FormattedBucket[] | null {
|
||||
if (!buckets) {
|
||||
return null;
|
||||
}
|
||||
|
@ -24,12 +46,12 @@ export function getFormattedBuckets(buckets, bucketSize) {
|
|||
});
|
||||
}
|
||||
|
||||
function Distribution({
|
||||
distribution,
|
||||
title = i18n.translate('xpack.apm.errorGroupDetails.occurrencesChartLabel', {
|
||||
defaultMessage: 'Occurrences'
|
||||
})
|
||||
}) {
|
||||
interface Props {
|
||||
distribution: IDistribution;
|
||||
title: React.ReactNode;
|
||||
}
|
||||
|
||||
export function ErrorDistribution({ distribution, title }: Props) {
|
||||
const buckets = getFormattedBuckets(
|
||||
distribution.buckets,
|
||||
distribution.bucketSize
|
||||
|
@ -53,17 +75,17 @@ function Distribution({
|
|||
<span>{title}</span>
|
||||
</EuiTitle>
|
||||
<Histogram
|
||||
verticalLineHover={bucket => bucket.x}
|
||||
verticalLineHover={(bucket: FormattedBucket) => bucket.x}
|
||||
xType="time"
|
||||
buckets={buckets}
|
||||
bucketSize={distribution.bucketSize}
|
||||
formatYShort={value =>
|
||||
formatYShort={(value: number) =>
|
||||
i18n.translate('xpack.apm.errorGroupDetails.occurrencesShortLabel', {
|
||||
defaultMessage: '{occCount} occ.',
|
||||
values: { occCount: value }
|
||||
})
|
||||
}
|
||||
formatYLong={value =>
|
||||
formatYLong={(value: number) =>
|
||||
i18n.translate('xpack.apm.errorGroupDetails.occurrencesLongLabel', {
|
||||
defaultMessage: '{occCount} occurrences',
|
||||
values: { occCount: value }
|
||||
|
@ -73,5 +95,3 @@ function Distribution({
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Distribution;
|
|
@ -5,10 +5,11 @@
|
|||
*/
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
import { ErrorGroupDetails } from './view';
|
||||
import { IReduxState } from '../../../store/rootReducer';
|
||||
import { getUrlParams } from '../../../store/urlParams';
|
||||
import { ErrorGroupDetailsView } from './view';
|
||||
|
||||
function mapStateToProps(state = {}) {
|
||||
function mapStateToProps(state = {} as IReduxState) {
|
||||
return {
|
||||
urlParams: getUrlParams(state),
|
||||
location: state.location
|
||||
|
@ -17,7 +18,7 @@ function mapStateToProps(state = {}) {
|
|||
|
||||
const mapDispatchToProps = {};
|
||||
|
||||
export default connect(
|
||||
export const ErrorGroupDetails = connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ErrorGroupDetails);
|
||||
)(ErrorGroupDetailsView);
|
|
@ -25,8 +25,7 @@ import {
|
|||
// @ts-ignore
|
||||
import { KueryBar } from '../../shared/KueryBar';
|
||||
import { DetailView } from './DetailView';
|
||||
// @ts-ignore
|
||||
import Distribution from './Distribution';
|
||||
import { ErrorDistribution } from './Distribution';
|
||||
|
||||
const Titles = styled.div`
|
||||
margin-bottom: ${px(units.plus)};
|
||||
|
@ -67,7 +66,7 @@ interface Props {
|
|||
location: Location;
|
||||
}
|
||||
|
||||
export function ErrorGroupDetails({ urlParams, location }: Props) {
|
||||
export function ErrorGroupDetailsView({ urlParams, location }: Props) {
|
||||
return (
|
||||
<ErrorGroupDetailsRequest
|
||||
urlParams={urlParams}
|
||||
|
@ -152,7 +151,17 @@ export function ErrorGroupDetails({ urlParams, location }: Props) {
|
|||
)}
|
||||
<ErrorDistributionRequest
|
||||
urlParams={urlParams}
|
||||
render={({ data }) => <Distribution distribution={data} />}
|
||||
render={({ data }) => (
|
||||
<ErrorDistribution
|
||||
distribution={data}
|
||||
title={i18n.translate(
|
||||
'xpack.apm.errorGroupDetails.occurrencesChartLabel',
|
||||
{
|
||||
defaultMessage: 'Occurrences'
|
||||
}
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{showDetails && (
|
||||
<DetailView
|
||||
|
|
|
@ -5,15 +5,14 @@
|
|||
*/
|
||||
|
||||
import { mount } from 'enzyme';
|
||||
import { Location } from 'history';
|
||||
import React from 'react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import {
|
||||
mockMoment,
|
||||
mountWithRouterAndStore,
|
||||
toJson
|
||||
// @ts-ignore
|
||||
} from '../../../../../utils/testHelpers';
|
||||
// @ts-ignore
|
||||
import { ErrorGroupList } from '../index';
|
||||
import props from './props.json';
|
||||
|
||||
|
@ -26,7 +25,11 @@ describe('ErrorGroupOverview -> List', () => {
|
|||
const storeState = {};
|
||||
const wrapper = mount(
|
||||
<MemoryRouter>
|
||||
<ErrorGroupList items={[]} urlParams={props.urlParams} location={{}} />
|
||||
<ErrorGroupList
|
||||
items={[]}
|
||||
urlParams={props.urlParams}
|
||||
location={{} as Location}
|
||||
/>
|
||||
</MemoryRouter>,
|
||||
storeState
|
||||
);
|
||||
|
|
|
@ -4,25 +4,35 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { EuiBasicTable, EuiBadge, EuiToolTip } from '@elastic/eui';
|
||||
import { EuiBadge, EuiBasicTable, EuiToolTip } from '@elastic/eui';
|
||||
import numeral from '@elastic/numeral';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { Location } from 'history';
|
||||
import moment from 'moment';
|
||||
import { toQuery, fromQuery, history } from '../../../shared/Links/url_helpers';
|
||||
import { KibanaLink } from '../../../shared/Links/KibanaLink';
|
||||
import React, { Component } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { IUrlParams } from 'x-pack/plugins/apm/public/store/urlParams';
|
||||
import { ErrorGroupListAPIResponse } from 'x-pack/plugins/apm/server/lib/errors/get_error_groups';
|
||||
import { NOT_AVAILABLE_LABEL } from '../../../../../common/i18n';
|
||||
import {
|
||||
unit,
|
||||
px,
|
||||
fontFamilyCode,
|
||||
fontSizes,
|
||||
truncate
|
||||
px,
|
||||
truncate,
|
||||
unit
|
||||
} from '../../../../style/variables';
|
||||
import { NOT_AVAILABLE_LABEL } from '../../../../../common/i18n';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { KibanaLink } from '../../../shared/Links/KibanaLink';
|
||||
import { fromQuery, history, toQuery } from '../../../shared/Links/url_helpers';
|
||||
|
||||
function paginateItems({ items, pageIndex, pageSize }) {
|
||||
function paginateItems({
|
||||
items,
|
||||
pageIndex,
|
||||
pageSize
|
||||
}: {
|
||||
items: any[];
|
||||
pageIndex: number;
|
||||
pageSize: number;
|
||||
}) {
|
||||
return items.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize);
|
||||
}
|
||||
|
||||
|
@ -44,15 +54,33 @@ const Culprit = styled.div`
|
|||
font-family: ${fontFamilyCode};
|
||||
`;
|
||||
|
||||
export class ErrorGroupList extends Component {
|
||||
state = {
|
||||
interface Props {
|
||||
location: Location;
|
||||
urlParams: IUrlParams;
|
||||
items: ErrorGroupListAPIResponse;
|
||||
}
|
||||
|
||||
interface ITableChange {
|
||||
page: { index?: number; size?: number };
|
||||
sort: {
|
||||
field?: string;
|
||||
direction?: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface State {
|
||||
page: { index?: number; size?: number };
|
||||
}
|
||||
|
||||
export class ErrorGroupList extends Component<Props, State> {
|
||||
public state = {
|
||||
page: {
|
||||
index: 0,
|
||||
size: 25
|
||||
}
|
||||
};
|
||||
|
||||
onTableChange = ({ page = {}, sort = {} }) => {
|
||||
public onTableChange = ({ page = {}, sort = {} }: ITableChange) => {
|
||||
this.setState({ page });
|
||||
|
||||
const { location } = this.props;
|
||||
|
@ -67,7 +95,7 @@ export class ErrorGroupList extends Component {
|
|||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
const { items } = this.props;
|
||||
const { serviceName, sortDirection, sortField } = this.props.urlParams;
|
||||
|
||||
|
@ -85,7 +113,7 @@ export class ErrorGroupList extends Component {
|
|||
field: 'groupId',
|
||||
sortable: false,
|
||||
width: px(unit * 6),
|
||||
render: groupId => {
|
||||
render: (groupId: string) => {
|
||||
return (
|
||||
<GroupIdLink hash={`/${serviceName}/errors/${groupId}`}>
|
||||
{groupId.slice(0, 5) || NOT_AVAILABLE_LABEL}
|
||||
|
@ -103,7 +131,7 @@ export class ErrorGroupList extends Component {
|
|||
field: 'message',
|
||||
sortable: false,
|
||||
width: '50%',
|
||||
render: (message, item) => {
|
||||
render: (message: string, item: ErrorGroupListAPIResponse[0]) => {
|
||||
return (
|
||||
<MessageAndCulpritCell>
|
||||
<EuiToolTip
|
||||
|
@ -130,7 +158,7 @@ export class ErrorGroupList extends Component {
|
|||
field: 'handled',
|
||||
sortable: false,
|
||||
align: 'right',
|
||||
render: isUnhandled =>
|
||||
render: (isUnhandled: boolean) =>
|
||||
isUnhandled === false && (
|
||||
<EuiBadge color="warning">
|
||||
{i18n.translate('xpack.apm.errorsTable.unhandledLabel', {
|
||||
|
@ -146,7 +174,7 @@ export class ErrorGroupList extends Component {
|
|||
field: 'occurrenceCount',
|
||||
sortable: true,
|
||||
dataType: 'number',
|
||||
render: value =>
|
||||
render: (value?: number) =>
|
||||
value ? numeral(value).format('0.[0]a') : NOT_AVAILABLE_LABEL
|
||||
},
|
||||
{
|
||||
|
@ -159,7 +187,8 @@ export class ErrorGroupList extends Component {
|
|||
}
|
||||
),
|
||||
align: 'right',
|
||||
render: value => (value ? moment(value).fromNow() : NOT_AVAILABLE_LABEL)
|
||||
render: (value?: number) =>
|
||||
value ? moment(value).fromNow() : NOT_AVAILABLE_LABEL
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -186,7 +215,3 @@ export class ErrorGroupList extends Component {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
ErrorGroupList.propTypes = {
|
||||
location: PropTypes.object.isRequired
|
||||
};
|
|
@ -4,16 +4,14 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { Location } from 'history';
|
||||
import React from 'react';
|
||||
// @ts-ignore
|
||||
import Distribution from 'x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution';
|
||||
import { ErrorDistribution } from 'x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution';
|
||||
import { ErrorDistributionRequest } from 'x-pack/plugins/apm/public/store/reactReduxRequest/errorDistribution';
|
||||
import { IUrlParams } from 'x-pack/plugins/apm/public/store/urlParams';
|
||||
import { ErrorGroupOverviewRequest } from '../../../store/reactReduxRequest/errorGroupList';
|
||||
// @ts-ignore
|
||||
import { ErrorGroupList } from './List';
|
||||
|
||||
interface ErrorGroupOverviewProps {
|
||||
|
@ -32,20 +30,14 @@ const ErrorGroupOverview: React.SFC<ErrorGroupOverviewProps> = ({
|
|||
<ErrorDistributionRequest
|
||||
urlParams={urlParams}
|
||||
render={({ data }) => (
|
||||
<Distribution
|
||||
<ErrorDistribution
|
||||
distribution={data}
|
||||
title={
|
||||
<EuiTitle size="xs">
|
||||
<span>
|
||||
{i18n.translate(
|
||||
title={i18n.translate(
|
||||
'xpack.apm.serviceDetails.metrics.errorOccurrencesChartTitle',
|
||||
{
|
||||
defaultMessage: 'Error occurrences'
|
||||
}
|
||||
)}
|
||||
</span>
|
||||
</EuiTitle>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
|
|
@ -4,22 +4,23 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { get, some } from 'lodash';
|
||||
import { connect } from 'react-redux';
|
||||
import view from './view';
|
||||
import { some, get } from 'lodash';
|
||||
import { IReduxState } from 'x-pack/plugins/apm/public/store/rootReducer';
|
||||
import { STATUS } from '../../../../constants/index';
|
||||
import { GlobalProgressView } from './view';
|
||||
|
||||
function getIsLoading(state) {
|
||||
function getIsLoading(state: IReduxState) {
|
||||
return some(
|
||||
state.reactReduxRequest,
|
||||
subState => get(subState, 'status') === STATUS.LOADING
|
||||
);
|
||||
}
|
||||
|
||||
function mapStateToProps(state = {}) {
|
||||
function mapStateToProps(state = {} as IReduxState) {
|
||||
return {
|
||||
isLoading: getIsLoading(state)
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(view);
|
||||
export const GlobalProgress = connect(mapStateToProps)(GlobalProgressView);
|
|
@ -4,10 +4,14 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiDelayHide, EuiPortal, EuiProgress } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { EuiPortal, EuiProgress, EuiDelayHide } from '@elastic/eui';
|
||||
|
||||
export default ({ isLoading }) => {
|
||||
interface Props {
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export function GlobalProgressView({ isLoading }: Props) {
|
||||
return (
|
||||
<EuiDelayHide
|
||||
hide={!isLoading}
|
||||
|
@ -19,4 +23,4 @@ export default ({ isLoading }) => {
|
|||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
|
@ -4,18 +4,21 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Location } from 'history';
|
||||
import { Component } from 'react';
|
||||
|
||||
class ScrollToTopOnPathChange extends Component {
|
||||
componentDidUpdate(prevProps) {
|
||||
interface Props {
|
||||
location: Location;
|
||||
}
|
||||
|
||||
export class ScrollToTopOnPathChange extends Component<Props> {
|
||||
public componentDidUpdate(prevProps: Props) {
|
||||
if (this.props.location.pathname !== prevProps.location.pathname) {
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
public render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export default ScrollToTopOnPathChange;
|
|
@ -12,8 +12,7 @@ import { px, topNavHeight, unit, units } from '../../../style/variables';
|
|||
import ConnectRouterToRedux from '../../shared/ConnectRouterToRedux';
|
||||
import { LicenseCheck } from './LicenseCheck';
|
||||
import { routes } from './routeConfig';
|
||||
// @ts-ignore
|
||||
import ScrollToTopOnPathChange from './ScrollToTopOnPathChange';
|
||||
import { ScrollToTopOnPathChange } from './ScrollToTopOnPathChange';
|
||||
import { UpdateBreadcrumbs } from './UpdateBreadcrumbs';
|
||||
|
||||
const MainContainer = styled.div`
|
||||
|
|
|
@ -8,8 +8,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import React from 'react';
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom';
|
||||
import { legacyDecodeURIComponent } from 'x-pack/plugins/apm/public/components/shared/Links/url_helpers';
|
||||
// @ts-ignore
|
||||
import ErrorGroupDetails from '../ErrorGroupDetails';
|
||||
import { ErrorGroupDetails } from '../ErrorGroupDetails';
|
||||
import { ServiceDetails } from '../ServiceDetails';
|
||||
import { TransactionDetails } from '../TransactionDetails';
|
||||
import { Home } from './Home';
|
||||
|
|
|
@ -8,14 +8,12 @@ import {
|
|||
EuiFlexGrid,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiSpacer,
|
||||
EuiTitle
|
||||
EuiSpacer
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { Location } from 'history';
|
||||
import React from 'react';
|
||||
// @ts-ignore
|
||||
import Distribution from 'x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution';
|
||||
import { ErrorDistribution } from 'x-pack/plugins/apm/public/components/app/ErrorGroupDetails/Distribution';
|
||||
import { SyncChartGroup } from 'x-pack/plugins/apm/public/components/shared/charts/SyncChartGroup';
|
||||
import { TransactionCharts } from 'x-pack/plugins/apm/public/components/shared/charts/TransactionCharts';
|
||||
import { ErrorDistributionRequest } from 'x-pack/plugins/apm/public/store/reactReduxRequest/errorDistribution';
|
||||
|
@ -51,20 +49,14 @@ export function ServiceMetrics({ urlParams, location }: ServiceMetricsProps) {
|
|||
<ErrorDistributionRequest
|
||||
urlParams={urlParams}
|
||||
render={({ data }) => (
|
||||
<Distribution
|
||||
<ErrorDistribution
|
||||
distribution={data}
|
||||
title={
|
||||
<EuiTitle size="xs">
|
||||
<span>
|
||||
{i18n.translate(
|
||||
title={i18n.translate(
|
||||
'xpack.apm.serviceDetails.metrics.errorOccurrencesChartTitle',
|
||||
{
|
||||
defaultMessage: 'Error occurrences'
|
||||
}
|
||||
)}
|
||||
</span>
|
||||
</EuiTitle>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
|
|
@ -8,7 +8,6 @@ import { i18n } from '@kbn/i18n';
|
|||
import React from 'react';
|
||||
import { RRRRenderResponse } from 'react-redux-request';
|
||||
import { TraceListAPIResponse } from 'x-pack/plugins/apm/server/lib/traces/get_top_traces';
|
||||
// @ts-ignore
|
||||
import { TraceListRequest } from '../../../store/reactReduxRequest/traceList';
|
||||
import { EmptyMessage } from '../../shared/EmptyMessage';
|
||||
import { TraceList } from './TraceList';
|
||||
|
|
|
@ -56,7 +56,7 @@ interface Props {
|
|||
urlParams: IUrlParams;
|
||||
}
|
||||
|
||||
export class Distribution extends Component<Props> {
|
||||
export class TransactionDistribution extends Component<Props> {
|
||||
public formatYShort = (t: number) => {
|
||||
return i18n.translate(
|
||||
'xpack.apm.transactionDetails.transactionsDurationDistributionChart.unitShortLabel',
|
||||
|
|
|
@ -9,7 +9,6 @@ import { i18n } from '@kbn/i18n';
|
|||
import React, { Fragment, useEffect, useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { px, units } from '../../../../../../../style/variables';
|
||||
// @ts-ignore
|
||||
import { Ellipsis } from '../../../../../../shared/Icons';
|
||||
|
||||
const ToggleButtonContainer = styled.div`
|
||||
|
@ -59,10 +58,7 @@ export const TruncateHeightSection: React.SFC<Props> = ({
|
|||
setIsOpen(!isOpen);
|
||||
}}
|
||||
>
|
||||
<Ellipsis
|
||||
horizontal={!isOpen}
|
||||
style={{ marginRight: units.half }}
|
||||
/>{' '}
|
||||
<Ellipsis horizontal={!isOpen} />{' '}
|
||||
{isOpen
|
||||
? i18n.translate('xpack.apm.toggleHeight.showMoreButtonLabel', {
|
||||
defaultMessage: 'Show more lines'
|
||||
|
|
|
@ -16,7 +16,7 @@ import { TransactionCharts } from '../../shared/charts/TransactionCharts';
|
|||
import { EmptyMessage } from '../../shared/EmptyMessage';
|
||||
// @ts-ignore
|
||||
import { KueryBar } from '../../shared/KueryBar';
|
||||
import { Distribution } from './Distribution';
|
||||
import { TransactionDistribution } from './Distribution';
|
||||
import { Transaction } from './Transaction';
|
||||
|
||||
interface Props {
|
||||
|
@ -54,7 +54,7 @@ export function TransactionDetailsView({ urlParams, location }: Props) {
|
|||
<TransactionDistributionRequest
|
||||
urlParams={urlParams}
|
||||
render={({ data }) => (
|
||||
<Distribution
|
||||
<TransactionDistribution
|
||||
distribution={data}
|
||||
urlParams={urlParams}
|
||||
location={location}
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
export function Icon({ name, className, ...props }) {
|
||||
return <i className={`fa ${name} ${className}`} {...props} />;
|
||||
}
|
||||
|
||||
export function Ellipsis({ horizontal, style, ...props }) {
|
||||
return (
|
||||
<Icon
|
||||
style={{
|
||||
transition: 'transform 0.1s',
|
||||
transform: `rotate(${horizontal ? 90 : 0}deg)`,
|
||||
...style
|
||||
}}
|
||||
name="fa-ellipsis-v"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function Check({ ...props }) {
|
||||
return <Icon name="fa-check" {...props} />;
|
||||
}
|
||||
|
||||
export function Close({ ...props }) {
|
||||
return <Icon name="fa-times" {...props} />;
|
||||
}
|
22
x-pack/plugins/apm/public/components/shared/Icons.tsx
Normal file
22
x-pack/plugins/apm/public/components/shared/Icons.tsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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 { EuiIcon } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { units } from '../../style/variables';
|
||||
|
||||
export function Ellipsis({ horizontal }: { horizontal: boolean }) {
|
||||
return (
|
||||
<EuiIcon
|
||||
style={{
|
||||
transition: 'transform 0.1s',
|
||||
transform: `rotate(${horizontal ? 90 : 0}deg)`,
|
||||
marginRight: units.half
|
||||
}}
|
||||
type="boxesVertical"
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -9,8 +9,6 @@ import { i18n } from '@kbn/i18n';
|
|||
import React, { Fragment } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { IStackframe } from 'x-pack/plugins/apm/typings/es_schemas/fields/Stackframe';
|
||||
import { units } from '../../../style/variables';
|
||||
// @ts-ignore
|
||||
import { Ellipsis } from '../../shared/Icons';
|
||||
import { Stackframe } from './Stackframe';
|
||||
|
||||
|
@ -48,10 +46,7 @@ export class LibraryStackFrames extends React.Component<Props, State> {
|
|||
<div>
|
||||
<LibraryFrameToggle>
|
||||
<EuiLink onClick={this.onClick}>
|
||||
<Ellipsis
|
||||
horizontal={isVisible}
|
||||
style={{ marginRight: units.half }}
|
||||
/>{' '}
|
||||
<Ellipsis horizontal={isVisible} />{' '}
|
||||
{i18n.translate(
|
||||
'xpack.apm.stacktraceTab.libraryFramesToogleButtonLabel',
|
||||
{
|
||||
|
|
|
@ -16,7 +16,6 @@ import {
|
|||
unit,
|
||||
units
|
||||
} from '../../../style/variables';
|
||||
// @ts-ignore
|
||||
import { Ellipsis } from '../Icons';
|
||||
import { PropertiesTable } from '../PropertiesTable';
|
||||
|
||||
|
@ -59,10 +58,7 @@ export class Variables extends React.Component<Props> {
|
|||
return (
|
||||
<VariablesContainer>
|
||||
<VariablesToggle onClick={this.onClick}>
|
||||
<Ellipsis
|
||||
horizontal={this.state.isVisible}
|
||||
style={{ marginRight: units.half }}
|
||||
/>{' '}
|
||||
<Ellipsis horizontal={this.state.isVisible} />{' '}
|
||||
{i18n.translate(
|
||||
'xpack.apm.stacktraceTab.localVariablesToogleButtonLabel',
|
||||
{ defaultMessage: 'Local variables' }
|
||||
|
|
|
@ -10,8 +10,6 @@ import { isEmpty, last } from 'lodash';
|
|||
import React, { Fragment } from 'react';
|
||||
import { IStackframe } from '../../../../typings/es_schemas/fields/Stackframe';
|
||||
import { EmptyMessage } from '../../shared/EmptyMessage';
|
||||
// @ts-ignore
|
||||
import { Ellipsis } from '../../shared/Icons';
|
||||
import { LibraryStackFrames } from './LibraryStackFrames';
|
||||
import { Stackframe } from './Stackframe';
|
||||
|
||||
|
|
|
@ -4,26 +4,28 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { uiModules } from 'ui/modules'; // eslint-disable-line no-unused-vars
|
||||
import chrome from 'ui/chrome';
|
||||
import React, { Fragment } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import { Router } from 'react-router-dom';
|
||||
import ReactDOM from 'react-dom';
|
||||
import 'ui/autoload/styles';
|
||||
import 'ui/autoload/all';
|
||||
import 'uiExports/autocompleteProviders';
|
||||
import 'react-vis/dist/style.css';
|
||||
import 'ui/autoload/all';
|
||||
import 'ui/autoload/styles';
|
||||
import chrome from 'ui/chrome';
|
||||
import { I18nContext } from 'ui/i18n';
|
||||
// @ts-ignore
|
||||
import { uiModules } from 'ui/modules';
|
||||
import 'uiExports/autocompleteProviders';
|
||||
import { GlobalHelpExtension } from './components/app/GlobalHelpExtension';
|
||||
import { Main } from './components/app/Main';
|
||||
import { GlobalProgress } from './components/app/Main/GlobalProgress';
|
||||
import { history } from './components/shared/Links/url_helpers';
|
||||
// @ts-ignore
|
||||
import configureStore from './store/config/configureStore';
|
||||
import './style/global_overrides.css';
|
||||
import template from './templates/index.html';
|
||||
import { Main } from './components/app/Main';
|
||||
// @ts-ignore
|
||||
import { initTimepicker } from './utils/timepicker';
|
||||
import configureStore from './store/config/configureStore';
|
||||
import GlobalProgress from './components/app/Main/GlobalProgress';
|
||||
import { GlobalHelpExtension } from './components/app/GlobalHelpExtension';
|
||||
|
||||
import { history } from './components/shared/Links/url_helpers';
|
||||
import { I18nContext } from 'ui/i18n';
|
||||
|
||||
// render APM feedback link in global help menu
|
||||
chrome.helpExtension.set(domElement => {
|
||||
|
@ -33,6 +35,7 @@ chrome.helpExtension.set(domElement => {
|
|||
};
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
chrome.setRootTemplate(template);
|
||||
const store = configureStore();
|
||||
|
|
@ -4,9 +4,15 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Location } from 'history';
|
||||
import { AnyAction } from 'redux';
|
||||
|
||||
export const LOCATION_UPDATE = 'LOCATION_UPDATE';
|
||||
|
||||
function location(state = { pathname: '', search: '', hash: '' }, action) {
|
||||
export function locationReducer(
|
||||
state = { pathname: '', search: '', hash: '' },
|
||||
action: AnyAction
|
||||
) {
|
||||
switch (action.type) {
|
||||
case LOCATION_UPDATE:
|
||||
return action.location;
|
||||
|
@ -15,11 +21,9 @@ function location(state = { pathname: '', search: '', hash: '' }, action) {
|
|||
}
|
||||
}
|
||||
|
||||
export function updateLocation(nextLocation) {
|
||||
export function updateLocation(nextLocation: Location) {
|
||||
return {
|
||||
type: LOCATION_UPDATE,
|
||||
location: nextLocation
|
||||
};
|
||||
}
|
||||
|
||||
export default location;
|
|
@ -10,7 +10,6 @@ import { ErrorDistributionAPIResponse } from 'x-pack/plugins/apm/server/lib/erro
|
|||
import { loadErrorDistribution } from '../../services/rest/apm/error_groups';
|
||||
import { IReduxState } from '../rootReducer';
|
||||
import { IUrlParams } from '../urlParams';
|
||||
// @ts-ignore
|
||||
import { createInitialDataSelector } from './helpers';
|
||||
|
||||
const ID = 'errorDistribution';
|
||||
|
|
|
@ -10,7 +10,6 @@ import { ErrorGroupAPIResponse } from 'x-pack/plugins/apm/server/lib/errors/get_
|
|||
import { loadErrorGroupDetails } from '../../services/rest/apm/error_groups';
|
||||
import { IReduxState } from '../rootReducer';
|
||||
import { IUrlParams } from '../urlParams';
|
||||
// @ts-ignore
|
||||
import { createInitialDataSelector } from './helpers';
|
||||
|
||||
const ID = 'errorGroupDetails';
|
||||
|
|
|
@ -5,16 +5,19 @@
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Request } from 'react-redux-request';
|
||||
import { Request, RRRRender } from 'react-redux-request';
|
||||
import { createSelector } from 'reselect';
|
||||
import { TraceListAPIResponse } from 'x-pack/plugins/apm/server/lib/traces/get_top_traces';
|
||||
import { loadTraceList } from '../../services/rest/apm/traces';
|
||||
import { IReduxState } from '../rootReducer';
|
||||
import { IUrlParams } from '../urlParams';
|
||||
import { createInitialDataSelector } from './helpers';
|
||||
|
||||
const ID = 'traceList';
|
||||
const INITIAL_DATA = [];
|
||||
const INITIAL_DATA: TraceListAPIResponse = [];
|
||||
const withInitialData = createInitialDataSelector(INITIAL_DATA);
|
||||
|
||||
const selectRRR = (state = {}) => state.reactReduxRequest;
|
||||
const selectRRR = (state = {} as IReduxState) => state.reactReduxRequest;
|
||||
|
||||
export const selectTraceList = createSelector(
|
||||
[selectRRR],
|
||||
|
@ -23,7 +26,12 @@ export const selectTraceList = createSelector(
|
|||
}
|
||||
);
|
||||
|
||||
export function TraceListRequest({ urlParams = {}, render }) {
|
||||
interface Props {
|
||||
urlParams: IUrlParams;
|
||||
render: RRRRender<TraceListAPIResponse>;
|
||||
}
|
||||
|
||||
export function TraceListRequest({ urlParams, render }: Props) {
|
||||
const { start, end, kuery } = urlParams;
|
||||
|
||||
if (!start || !end) {
|
|
@ -13,8 +13,6 @@ import {
|
|||
} from '../../components/app/TransactionDetails/Transaction/WaterfallContainer/Waterfall/waterfall_helpers/waterfall_helpers';
|
||||
import { loadTrace } from '../../services/rest/apm/traces';
|
||||
import { IUrlParams } from '../urlParams';
|
||||
// @ts-ignore
|
||||
import { createInitialDataSelector } from './helpers';
|
||||
|
||||
export const ID = 'waterfall';
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@ import { Location } from 'history';
|
|||
import { reducer } from 'react-redux-request';
|
||||
import { combineReducers } from 'redux';
|
||||
import { StringMap } from '../../typings/common';
|
||||
// @ts-ignore
|
||||
import location from './location';
|
||||
import { locationReducer } from './location';
|
||||
import { IUrlParams, urlParamsReducer } from './urlParams';
|
||||
|
||||
export interface IReduxState {
|
||||
|
@ -19,7 +18,7 @@ export interface IReduxState {
|
|||
}
|
||||
|
||||
export const rootReducer = combineReducers({
|
||||
location,
|
||||
location: locationReducer,
|
||||
urlParams: urlParamsReducer,
|
||||
reactReduxRequest: reducer
|
||||
});
|
||||
|
|
|
@ -4,14 +4,13 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Location } from 'history';
|
||||
import { compact, pick } from 'lodash';
|
||||
import { AnyAction } from 'redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import {
|
||||
legacyDecodeURIComponent,
|
||||
toQuery
|
||||
} from '../components/shared/Links/url_helpers';
|
||||
// @ts-ignore
|
||||
import { LOCATION_UPDATE } from './location';
|
||||
import { getDefaultTransactionType } from './reactReduxRequest/serviceDetails';
|
||||
import { getDefaultDistributionSample } from './reactReduxRequest/transactionDistribution';
|
||||
|
@ -20,6 +19,16 @@ import { IReduxState } from './rootReducer';
|
|||
// ACTION TYPES
|
||||
export const TIMEPICKER_UPDATE = 'TIMEPICKER_UPDATE';
|
||||
|
||||
interface LocationAction {
|
||||
type: typeof LOCATION_UPDATE;
|
||||
location: Location;
|
||||
}
|
||||
interface TimepickerAction {
|
||||
type: typeof TIMEPICKER_UPDATE;
|
||||
time: { min: number; max: number };
|
||||
}
|
||||
type Action = LocationAction | TimepickerAction;
|
||||
|
||||
// "urlParams" contains path and query parameters from the url, that can be easily consumed from
|
||||
// any (container) component with access to the store
|
||||
|
||||
|
@ -28,7 +37,7 @@ export const TIMEPICKER_UPDATE = 'TIMEPICKER_UPDATE';
|
|||
// serviceName: opbeans-backend (path param)
|
||||
// transactionType: Brewing%20Bot (path param)
|
||||
// transactionId: 1321 (query param)
|
||||
export function urlParamsReducer(state = {}, action: AnyAction) {
|
||||
export function urlParamsReducer(state = {}, action: Action) {
|
||||
switch (action.type) {
|
||||
case LOCATION_UPDATE: {
|
||||
const {
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
import { metadata } from 'ui/metadata';
|
||||
const STACK_VERSION = metadata.branch;
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
import { metadata } from 'ui/metadata';
|
||||
const STACK_VERSION = metadata.branch;
|
||||
|
||||
|
|
|
@ -6,15 +6,17 @@
|
|||
|
||||
/* global jest */
|
||||
|
||||
import { mount } from 'enzyme';
|
||||
import moment from 'moment';
|
||||
import { createMockStore } from 'redux-test-utils';
|
||||
import createHistory from 'history/createHashHistory';
|
||||
import PropTypes from 'prop-types';
|
||||
import { mount, ReactWrapper } from 'enzyme';
|
||||
import enzymeToJson from 'enzyme-to-json';
|
||||
import createHistory from 'history/createHashHistory';
|
||||
import 'jest-styled-components';
|
||||
import moment from 'moment';
|
||||
import { Moment } from 'moment-timezone';
|
||||
import PropTypes from 'prop-types';
|
||||
// @ts-ignore
|
||||
import { createMockStore } from 'redux-test-utils';
|
||||
|
||||
export function toJson(wrapper) {
|
||||
export function toJson(wrapper: ReactWrapper) {
|
||||
return enzymeToJson(wrapper, {
|
||||
noKey: true,
|
||||
mode: 'deep'
|
||||
|
@ -27,7 +29,7 @@ const defaultRoute = {
|
|||
};
|
||||
|
||||
export function mountWithRouterAndStore(
|
||||
Component,
|
||||
Component: React.ReactElement,
|
||||
storeState = {},
|
||||
route = defaultRoute
|
||||
) {
|
||||
|
@ -51,7 +53,7 @@ export function mountWithRouterAndStore(
|
|||
return mount(Component, options);
|
||||
}
|
||||
|
||||
export function mountWithStore(Component, storeState = {}) {
|
||||
export function mountWithStore(Component: React.ReactElement, storeState = {}) {
|
||||
const store = createMockStore(storeState);
|
||||
|
||||
const options = {
|
||||
|
@ -68,12 +70,16 @@ export function mountWithStore(Component, storeState = {}) {
|
|||
|
||||
export function mockMoment() {
|
||||
// avoid timezone issues
|
||||
jest.spyOn(moment.prototype, 'format').mockImplementation(function() {
|
||||
jest
|
||||
.spyOn(moment.prototype, 'format')
|
||||
.mockImplementation(function(this: Moment) {
|
||||
return `1st of January (mocking ${this.unix()})`;
|
||||
});
|
||||
|
||||
// convert relative time to absolute time to avoid timing issues
|
||||
jest.spyOn(moment.prototype, 'fromNow').mockImplementation(function() {
|
||||
jest
|
||||
.spyOn(moment.prototype, 'fromNow')
|
||||
.mockImplementation(function(this: Moment) {
|
||||
return `1337 minutes ago (mocking ${this.unix()})`;
|
||||
});
|
||||
}
|
|
@ -4,13 +4,15 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { SearchParams } from 'elasticsearch';
|
||||
import { OBSERVER_LISTENING } from '../../../common/elasticsearch_fieldnames';
|
||||
import { Setup } from '../helpers/setup_request';
|
||||
|
||||
// Note: this logic is duplicated in tutorials/apm/envs/on_prem
|
||||
export async function getServerStatus({ setup }) {
|
||||
export async function getServerStatus({ setup }: { setup: Setup }) {
|
||||
const { client, config } = setup;
|
||||
|
||||
const params = {
|
||||
const params: SearchParams = {
|
||||
index: config.get('apm_oss.onboardingIndices'),
|
||||
body: {
|
||||
size: 0,
|
|
@ -4,26 +4,28 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import Joi from 'joi';
|
||||
import Boom from 'boom';
|
||||
|
||||
import { Server } from 'hapi';
|
||||
import Joi from 'joi';
|
||||
import { Legacy } from 'kibana';
|
||||
import { getDistribution } from '../lib/errors/distribution/get_distribution';
|
||||
import { getErrorGroups } from '../lib/errors/get_error_groups';
|
||||
import { getErrorGroup } from '../lib/errors/get_error_group';
|
||||
import { setupRequest } from '../lib/helpers/setup_request';
|
||||
import { getErrorGroups } from '../lib/errors/get_error_groups';
|
||||
import { withDefaultValidators } from '../lib/helpers/input_validation';
|
||||
import { setupRequest } from '../lib/helpers/setup_request';
|
||||
|
||||
const ROOT = '/api/apm/services/{serviceName}/errors';
|
||||
const defaultErrorHandler = err => {
|
||||
const defaultErrorHandler = (err: Error) => {
|
||||
// tslint:disable-next-line
|
||||
console.error(err.stack);
|
||||
throw Boom.boomify(err, { statusCode: 400 });
|
||||
};
|
||||
|
||||
export function initErrorsApi(server) {
|
||||
export function initErrorsApi(server: Server) {
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: ROOT,
|
||||
config: {
|
||||
options: {
|
||||
validate: {
|
||||
query: withDefaultValidators({
|
||||
sortField: Joi.string(),
|
||||
|
@ -34,7 +36,10 @@ export function initErrorsApi(server) {
|
|||
handler: req => {
|
||||
const setup = setupRequest(req);
|
||||
const { serviceName } = req.params;
|
||||
const { sortField, sortDirection } = req.query;
|
||||
const { sortField, sortDirection } = req.query as {
|
||||
sortField: string;
|
||||
sortDirection: 'desc' | 'asc';
|
||||
};
|
||||
|
||||
return getErrorGroups({
|
||||
serviceName,
|
||||
|
@ -48,7 +53,7 @@ export function initErrorsApi(server) {
|
|||
server.route({
|
||||
method: 'GET',
|
||||
path: `${ROOT}/{groupId}`,
|
||||
config: {
|
||||
options: {
|
||||
validate: {
|
||||
query: withDefaultValidators()
|
||||
}
|
||||
|
@ -62,19 +67,19 @@ export function initErrorsApi(server) {
|
|||
}
|
||||
});
|
||||
|
||||
const distributionHandler = req => {
|
||||
function distributionHandler(req: Legacy.Request) {
|
||||
const setup = setupRequest(req);
|
||||
const { serviceName, groupId } = req.params;
|
||||
|
||||
return getDistribution({ serviceName, groupId, setup }).catch(
|
||||
defaultErrorHandler
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: `${ROOT}/{groupId}/distribution`,
|
||||
config: {
|
||||
options: {
|
||||
validate: {
|
||||
query: withDefaultValidators()
|
||||
}
|
||||
|
@ -85,7 +90,7 @@ export function initErrorsApi(server) {
|
|||
server.route({
|
||||
method: 'GET',
|
||||
path: `${ROOT}/distribution`,
|
||||
config: {
|
||||
options: {
|
||||
validate: {
|
||||
query: withDefaultValidators()
|
||||
}
|
|
@ -4,23 +4,25 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import Joi from 'joi';
|
||||
import Boom from 'boom';
|
||||
import { getServerStatus } from '../lib/status_check/server_check';
|
||||
import { getAgentStatus } from '../lib/status_check/agent_check';
|
||||
import { Server } from 'hapi';
|
||||
import Joi from 'joi';
|
||||
import { setupRequest } from '../lib/helpers/setup_request';
|
||||
import { getAgentStatus } from '../lib/status_check/agent_check';
|
||||
import { getServerStatus } from '../lib/status_check/server_check';
|
||||
|
||||
const ROOT = '/api/apm/status';
|
||||
const defaultErrorHandler = err => {
|
||||
const defaultErrorHandler = (err: Error) => {
|
||||
// tslint:disable-next-line
|
||||
console.error(err.stack);
|
||||
throw Boom.boomify(err, { statusCode: 400 });
|
||||
};
|
||||
|
||||
export function initStatusApi(server) {
|
||||
export function initStatusApi(server: Server) {
|
||||
server.route({
|
||||
method: 'GET',
|
||||
path: `${ROOT}/server`,
|
||||
config: {
|
||||
options: {
|
||||
validate: {
|
||||
query: Joi.object().keys({
|
||||
_debug: Joi.bool()
|
||||
|
@ -36,7 +38,7 @@ export function initStatusApi(server) {
|
|||
server.route({
|
||||
method: 'GET',
|
||||
path: `${ROOT}/agent`,
|
||||
config: {
|
||||
options: {
|
||||
validate: {
|
||||
query: Joi.object().keys({
|
||||
_debug: Joi.bool()
|
Loading…
Add table
Add a link
Reference in a new issue