mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[6.x] [InfraOps] Preserve time values when navigating from the waffle map to the logs and details pages (#24666) (#24911)
Backports the following commits to 6.x: - [InfraOps] Preserve time values when navigating from the waffle map to the logs and details pages (#24666)
This commit is contained in:
parent
8f9e176dd2
commit
ed9843a0af
18 changed files with 132 additions and 268 deletions
|
@ -6,7 +6,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { InfraNodeType } from '../../../common/graphql/types';
|
||||
import { InfraNodeType, InfraTimerangeInput } from '../../../common/graphql/types';
|
||||
import {
|
||||
InfraWaffleMapBounds,
|
||||
InfraWaffleMapGroupOfGroups,
|
||||
|
@ -22,6 +22,7 @@ interface Props {
|
|||
formatter: (val: number) => string;
|
||||
bounds: InfraWaffleMapBounds;
|
||||
nodeType: InfraNodeType;
|
||||
timeRange: InfraTimerangeInput;
|
||||
}
|
||||
|
||||
export const GroupOfGroups: React.SFC<Props> = props => {
|
||||
|
@ -39,6 +40,7 @@ export const GroupOfGroups: React.SFC<Props> = props => {
|
|||
formatter={props.formatter}
|
||||
bounds={props.bounds}
|
||||
nodeType={props.nodeType}
|
||||
timeRange={props.timeRange}
|
||||
/>
|
||||
))}
|
||||
</Groups>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { InfraNodeType } from '../../../common/graphql/types';
|
||||
import { InfraNodeType, InfraTimerangeInput } from '../../../common/graphql/types';
|
||||
import {
|
||||
InfraWaffleMapBounds,
|
||||
InfraWaffleMapGroupOfNodes,
|
||||
|
@ -23,6 +23,7 @@ interface Props {
|
|||
isChild: boolean;
|
||||
bounds: InfraWaffleMapBounds;
|
||||
nodeType: InfraNodeType;
|
||||
timeRange: InfraTimerangeInput;
|
||||
}
|
||||
|
||||
export const GroupOfNodes: React.SFC<Props> = ({
|
||||
|
@ -33,6 +34,7 @@ export const GroupOfNodes: React.SFC<Props> = ({
|
|||
isChild = false,
|
||||
bounds,
|
||||
nodeType,
|
||||
timeRange,
|
||||
}) => {
|
||||
const width = group.width > 200 ? group.width : 200;
|
||||
return (
|
||||
|
@ -48,6 +50,7 @@ export const GroupOfNodes: React.SFC<Props> = ({
|
|||
formatter={formatter}
|
||||
bounds={bounds}
|
||||
nodeType={nodeType}
|
||||
timeRange={timeRange}
|
||||
/>
|
||||
))}
|
||||
</Nodes>
|
||||
|
|
|
@ -7,7 +7,7 @@ import { EuiButton, EuiEmptyPrompt } from '@elastic/eui';
|
|||
import { get, max, min } from 'lodash';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { InfraMetricType, InfraNodeType } from '../../../common/graphql/types';
|
||||
import { InfraMetricType, InfraNodeType, InfraTimerangeInput } from '../../../common/graphql/types';
|
||||
import {
|
||||
isWaffleMapGroupWithGroups,
|
||||
isWaffleMapGroupWithNodes,
|
||||
|
@ -35,6 +35,7 @@ interface Props {
|
|||
loading: boolean;
|
||||
reload: () => void;
|
||||
onDrilldown: (filter: KueryFilterQuery) => void;
|
||||
timeRange: InfraTimerangeInput;
|
||||
}
|
||||
|
||||
interface MetricFormatter {
|
||||
|
@ -90,7 +91,7 @@ const calculateBoundsFromMap = (map: InfraWaffleData): InfraWaffleMapBounds => {
|
|||
|
||||
export class Waffle extends React.Component<Props, {}> {
|
||||
public render() {
|
||||
const { loading, map, reload } = this.props;
|
||||
const { loading, map, reload, timeRange } = this.props;
|
||||
if (loading) {
|
||||
return <InfraLoadingPanel height="100%" width="100%" text="Loading data" />;
|
||||
} else if (!loading && map && map.length === 0) {
|
||||
|
@ -132,7 +133,7 @@ export class Waffle extends React.Component<Props, {}> {
|
|||
data-test-subj="waffleMap"
|
||||
>
|
||||
<WaffleMapInnerContainer>
|
||||
{groupsWithLayout.map(this.renderGroup(bounds))}
|
||||
{groupsWithLayout.map(this.renderGroup(bounds, timeRange))}
|
||||
</WaffleMapInnerContainer>
|
||||
<Legend
|
||||
formatter={this.formatter}
|
||||
|
@ -169,7 +170,9 @@ export class Waffle extends React.Component<Props, {}> {
|
|||
return;
|
||||
};
|
||||
|
||||
private renderGroup = (bounds: InfraWaffleMapBounds) => (group: InfraWaffleMapGroup) => {
|
||||
private renderGroup = (bounds: InfraWaffleMapBounds, timeRange: InfraTimerangeInput) => (
|
||||
group: InfraWaffleMapGroup
|
||||
) => {
|
||||
if (isWaffleMapGroupWithGroups(group)) {
|
||||
return (
|
||||
<GroupOfGroups
|
||||
|
@ -180,6 +183,7 @@ export class Waffle extends React.Component<Props, {}> {
|
|||
formatter={this.formatter}
|
||||
bounds={bounds}
|
||||
nodeType={this.props.nodeType}
|
||||
timeRange={timeRange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -194,6 +198,7 @@ export class Waffle extends React.Component<Props, {}> {
|
|||
isChild={false}
|
||||
bounds={bounds}
|
||||
nodeType={this.props.nodeType}
|
||||
timeRange={timeRange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import { EuiToolTip } from '@elastic/eui';
|
|||
import { darken, readableColor } from 'polished';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { InfraTimerangeInput } from 'x-pack/plugins/infra/common/graphql/types';
|
||||
import { InfraNodeType } from '../../../server/lib/adapters/nodes';
|
||||
import { InfraWaffleMapBounds, InfraWaffleMapNode, InfraWaffleMapOptions } from '../../lib/lib';
|
||||
import { colorFromValue } from './lib/color_from_value';
|
||||
|
@ -26,12 +27,13 @@ interface Props {
|
|||
formatter: (val: number) => string;
|
||||
bounds: InfraWaffleMapBounds;
|
||||
nodeType: InfraNodeType;
|
||||
timeRange: InfraTimerangeInput;
|
||||
}
|
||||
|
||||
export class Node extends React.PureComponent<Props, State> {
|
||||
public readonly state: State = initialState;
|
||||
public render() {
|
||||
const { nodeType, node, options, squareSize, bounds, formatter } = this.props;
|
||||
const { nodeType, node, options, squareSize, bounds, formatter, timeRange } = this.props;
|
||||
const { isPopoverOpen } = this.state;
|
||||
const { metric } = node;
|
||||
const valueMode = squareSize > 110;
|
||||
|
@ -45,6 +47,7 @@ export class Node extends React.PureComponent<Props, State> {
|
|||
isPopoverOpen={isPopoverOpen}
|
||||
closePopover={this.closePopover}
|
||||
options={options}
|
||||
timeRange={timeRange}
|
||||
>
|
||||
<EuiToolTip position="top" content={`${node.name} | ${value}`}>
|
||||
<NodeContainer
|
||||
|
|
|
@ -6,19 +6,14 @@
|
|||
|
||||
import { EuiContextMenu, EuiContextMenuPanelDescriptor, EuiPopover } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import { InfraNodeType } from '../../../common/graphql/types';
|
||||
|
||||
import { InfraNodeType, InfraTimerangeInput } from '../../../common/graphql/types';
|
||||
import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../lib/lib';
|
||||
import {
|
||||
getContainerDetailUrl,
|
||||
getContainerLogsUrl,
|
||||
getHostDetailUrl,
|
||||
getHostLogsUrl,
|
||||
getPodDetailUrl,
|
||||
getPodLogsUrl,
|
||||
} from '../../pages/link_to';
|
||||
import { getNodeDetailUrl, getNodeLogsUrl } from '../../pages/link_to';
|
||||
|
||||
interface Props {
|
||||
options: InfraWaffleMapOptions;
|
||||
timeRange: InfraTimerangeInput;
|
||||
node: InfraWaffleMapNode;
|
||||
nodeType: InfraNodeType;
|
||||
isPopoverOpen: boolean;
|
||||
|
@ -27,14 +22,30 @@ interface Props {
|
|||
|
||||
export const NodeContextMenu: React.SFC<Props> = ({
|
||||
options,
|
||||
timeRange,
|
||||
children,
|
||||
node,
|
||||
isPopoverOpen,
|
||||
closePopover,
|
||||
nodeType,
|
||||
}) => {
|
||||
const nodeLogsUrl = getNodeLogsUrl(nodeType, node);
|
||||
const nodeDetailUrl = getNodeDetailUrl(nodeType, node);
|
||||
const nodeName = node.path.length > 0 ? node.path[node.path.length - 1].value : undefined;
|
||||
const nodeLogsUrl = nodeName
|
||||
? getNodeLogsUrl({
|
||||
nodeType,
|
||||
nodeName,
|
||||
time: timeRange.to,
|
||||
})
|
||||
: undefined;
|
||||
const nodeDetailUrl = nodeName
|
||||
? getNodeDetailUrl({
|
||||
nodeType,
|
||||
nodeName,
|
||||
from: timeRange.from,
|
||||
to: timeRange.to,
|
||||
})
|
||||
: undefined;
|
||||
|
||||
const panels: EuiContextMenuPanelDescriptor[] = [
|
||||
{
|
||||
id: 0,
|
||||
|
@ -72,47 +83,3 @@ export const NodeContextMenu: React.SFC<Props> = ({
|
|||
</EuiPopover>
|
||||
);
|
||||
};
|
||||
|
||||
const getNodeLogsUrl = (
|
||||
nodeType: 'host' | 'container' | 'pod',
|
||||
{ path }: InfraWaffleMapNode
|
||||
): string | undefined => {
|
||||
if (path.length <= 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const lastPathSegment = path[path.length - 1];
|
||||
|
||||
switch (nodeType) {
|
||||
case 'host':
|
||||
return getHostLogsUrl({ hostname: lastPathSegment.value });
|
||||
case 'container':
|
||||
return getContainerLogsUrl({ containerId: lastPathSegment.value });
|
||||
case 'pod':
|
||||
return getPodLogsUrl({ podId: lastPathSegment.value });
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
const getNodeDetailUrl = (
|
||||
nodeType: 'host' | 'container' | 'pod',
|
||||
{ path }: InfraWaffleMapNode
|
||||
): string | undefined => {
|
||||
if (path.length <= 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const lastPathSegment = path[path.length - 1];
|
||||
|
||||
switch (nodeType) {
|
||||
case 'host':
|
||||
return getHostDetailUrl({ name: lastPathSegment.value });
|
||||
case 'container':
|
||||
return getContainerDetailUrl({ name: lastPathSegment.value });
|
||||
case 'pod':
|
||||
return getPodDetailUrl({ name: lastPathSegment.value });
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@ import { createSelector } from 'reselect';
|
|||
import { metricTimeActions, metricTimeSelectors, State } from '../../store';
|
||||
import { asChildFunctionRenderer } from '../../utils/typed_react';
|
||||
import { bindPlainActionCreators } from '../../utils/typed_redux';
|
||||
import { UrlStateContainer } from '../../utils/url_state';
|
||||
import { replaceStateKeyInQueryString, UrlStateContainer } from '../../utils/url_state';
|
||||
|
||||
export const withMetricsTime = connect(
|
||||
(state: State) => ({
|
||||
|
@ -94,3 +94,15 @@ const mapToTimeUrlState = (value: any) =>
|
|||
value && (typeof value.to === 'number' && typeof value.from === 'number') ? value : undefined;
|
||||
|
||||
const mapToAutoReloadUrlState = (value: any) => (typeof value === 'boolean' ? value : undefined);
|
||||
|
||||
export const replaceMetricTimeInQueryString = (from: number, to: number) =>
|
||||
Number.isNaN(from) || Number.isNaN(to)
|
||||
? (value: string) => value
|
||||
: replaceStateKeyInQueryString<MetricTimeUrlState>('metricTime', {
|
||||
autoReload: false,
|
||||
time: {
|
||||
interval: '>=1m',
|
||||
from,
|
||||
to,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -44,6 +44,7 @@ export const HomePageContent: React.SFC = () => (
|
|||
options={{ ...wafflemap, metric, fields: configuredFields, groupBy }}
|
||||
reload={refetch}
|
||||
onDrilldown={applyFilterQuery}
|
||||
timeRange={currentTimeRange}
|
||||
/>
|
||||
)}
|
||||
</WithWaffleNodes>
|
||||
|
|
|
@ -1,16 +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 { Location } from 'history';
|
||||
import { replaceStateKeyInQueryString } from '../../utils/url_state';
|
||||
import { getFromFromLocation, getToFromLocation } from './query_params';
|
||||
|
||||
export const createQueryStringForDetailTime = (location: Location) => {
|
||||
const to = getToFromLocation(location);
|
||||
const from = getFromFromLocation(location);
|
||||
return to && from
|
||||
? '?' + replaceStateKeyInQueryString('metricTime', { to, from, interval: '>=1m' })('')
|
||||
: '';
|
||||
};
|
|
@ -5,9 +5,5 @@
|
|||
*/
|
||||
|
||||
export { LinkToPage } from './link_to';
|
||||
export { getContainerLogsUrl, RedirectToContainerLogs } from './redirect_to_container_logs';
|
||||
export { getHostLogsUrl, RedirectToHostLogs } from './redirect_to_host_logs';
|
||||
export { getPodLogsUrl, RedirectToPodLogs } from './redirect_to_pod_logs';
|
||||
export { getHostDetailUrl, RedirectToHostDetail } from './redirect_to_host_detail';
|
||||
export { getContainerDetailUrl, RedirectToContainerDetail } from './redirect_to_container_detail';
|
||||
export { getPodDetailUrl, RedirectToPodDetail } from './redirect_to_pod_detail';
|
||||
export { getNodeLogsUrl, RedirectToNodeLogs } from './redirect_to_node_logs';
|
||||
export { getNodeDetailUrl, RedirectToNodeDetail } from './redirect_to_node_detail';
|
||||
|
|
|
@ -7,12 +7,8 @@
|
|||
import React from 'react';
|
||||
import { match as RouteMatch, Redirect, Route, Switch } from 'react-router-dom';
|
||||
|
||||
import { RedirectToContainerDetail } from './redirect_to_container_detail';
|
||||
import { RedirectToContainerLogs } from './redirect_to_container_logs';
|
||||
import { RedirectToHostDetail } from './redirect_to_host_detail';
|
||||
import { RedirectToHostLogs } from './redirect_to_host_logs';
|
||||
import { RedirectToPodDetail } from './redirect_to_pod_detail';
|
||||
import { RedirectToPodLogs } from './redirect_to_pod_logs';
|
||||
import { RedirectToNodeDetail } from './redirect_to_node_detail';
|
||||
import { RedirectToNodeLogs } from './redirect_to_node_logs';
|
||||
|
||||
interface LinkToPageProps {
|
||||
match: RouteMatch<{}>;
|
||||
|
@ -25,14 +21,13 @@ export class LinkToPage extends React.Component<LinkToPageProps> {
|
|||
return (
|
||||
<Switch>
|
||||
<Route
|
||||
path={`${match.url}/container-logs/:containerId`}
|
||||
component={RedirectToContainerLogs}
|
||||
path={`${match.url}/:nodeType(host|container|pod)-logs/:nodeName`}
|
||||
component={RedirectToNodeLogs}
|
||||
/>
|
||||
<Route
|
||||
path={`${match.url}/:nodeType(host|container|pod)-detail/:nodeName`}
|
||||
component={RedirectToNodeDetail}
|
||||
/>
|
||||
<Route path={`${match.url}/host-logs/:hostname`} component={RedirectToHostLogs} />
|
||||
<Route path={`${match.url}/pod-logs/:podId`} component={RedirectToPodLogs} />
|
||||
<Route path={`${match.url}/host-detail/:name`} component={RedirectToHostDetail} />
|
||||
<Route path={`${match.url}/pod-detail/:name`} component={RedirectToPodDetail} />
|
||||
<Route path={`${match.url}/container-detail/:name`} component={RedirectToContainerDetail} />
|
||||
<Redirect to="/home" />
|
||||
</Switch>
|
||||
);
|
||||
|
|
|
@ -1,30 +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';
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom';
|
||||
import { createQueryStringForDetailTime } from './create_query_string_for_detail_time';
|
||||
|
||||
export const RedirectToContainerDetail = ({
|
||||
match,
|
||||
location,
|
||||
}: RouteComponentProps<{ name: string }>) => {
|
||||
const args = createQueryStringForDetailTime(location);
|
||||
return <Redirect to={`/metrics/container/${match.params.name}${args}`} />;
|
||||
};
|
||||
|
||||
export const getContainerDetailUrl = ({
|
||||
name,
|
||||
to,
|
||||
from,
|
||||
}: {
|
||||
name: string;
|
||||
to?: number;
|
||||
from?: number;
|
||||
}) => {
|
||||
const args = to && from ? `?to=${to}&from=${from}` : '';
|
||||
return `#/link-to/container-detail/${name}${args}`;
|
||||
};
|
|
@ -1,29 +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';
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom';
|
||||
import { createQueryStringForDetailTime } from './create_query_string_for_detail_time';
|
||||
export const RedirectToHostDetail = ({
|
||||
match,
|
||||
location,
|
||||
}: RouteComponentProps<{ name: string }>) => {
|
||||
const args = createQueryStringForDetailTime(location);
|
||||
return <Redirect to={`/metrics/host/${match.params.name}${args}`} />;
|
||||
};
|
||||
|
||||
export const getHostDetailUrl = ({
|
||||
name,
|
||||
to,
|
||||
from,
|
||||
}: {
|
||||
name: string;
|
||||
to?: number;
|
||||
from?: number;
|
||||
}) => {
|
||||
const args = to && from ? `?to=${to}&from=${from}` : '';
|
||||
return `#/link-to/host-detail/${name}${args}`;
|
||||
};
|
|
@ -1,38 +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 compose from 'lodash/fp/compose';
|
||||
import React from 'react';
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom';
|
||||
|
||||
import { LoadingPage } from '../../components/loading_page';
|
||||
import { replaceLogFilterInQueryString } from '../../containers/logs/with_log_filter';
|
||||
import { replaceLogPositionInQueryString } from '../../containers/logs/with_log_position';
|
||||
import { WithSource } from '../../containers/with_source';
|
||||
import { getTimeFromLocation } from './query_params';
|
||||
|
||||
export const RedirectToHostLogs = ({
|
||||
match,
|
||||
location,
|
||||
}: RouteComponentProps<{ hostname: string }>) => (
|
||||
<WithSource>
|
||||
{({ configuredFields }) => {
|
||||
if (!configuredFields) {
|
||||
return <LoadingPage message="Loading host logs" />;
|
||||
}
|
||||
|
||||
const searchString = compose(
|
||||
replaceLogFilterInQueryString(`${configuredFields.host}: ${match.params.hostname}`),
|
||||
replaceLogPositionInQueryString(getTimeFromLocation(location))
|
||||
)('');
|
||||
|
||||
return <Redirect to={`/logs?${searchString}`} />;
|
||||
}}
|
||||
</WithSource>
|
||||
);
|
||||
|
||||
export const getHostLogsUrl = ({ hostname, time }: { hostname: string; time?: number }) =>
|
||||
['#/link-to/host-logs/', hostname, ...(time ? [`?time=${time}`] : [])].join('');
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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';
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom';
|
||||
import { InfraNodeType } from 'x-pack/plugins/infra/common/graphql/types';
|
||||
import { replaceMetricTimeInQueryString } from '../../containers/metrics/with_metrics_time';
|
||||
import { getFromFromLocation, getToFromLocation } from './query_params';
|
||||
|
||||
type RedirectToNodeDetailProps = RouteComponentProps<{
|
||||
nodeName: string;
|
||||
nodeType: InfraNodeType;
|
||||
}>;
|
||||
|
||||
export const RedirectToNodeDetail = ({
|
||||
match: {
|
||||
params: { nodeName, nodeType },
|
||||
},
|
||||
location,
|
||||
}: RedirectToNodeDetailProps) => {
|
||||
const searchString = replaceMetricTimeInQueryString(
|
||||
getFromFromLocation(location),
|
||||
getToFromLocation(location)
|
||||
)('');
|
||||
|
||||
return <Redirect to={`/metrics/${nodeType}/${nodeName}?${searchString}`} />;
|
||||
};
|
||||
|
||||
export const getNodeDetailUrl = ({
|
||||
nodeType,
|
||||
nodeName,
|
||||
to,
|
||||
from,
|
||||
}: {
|
||||
nodeType: InfraNodeType;
|
||||
nodeName: string;
|
||||
to?: number;
|
||||
from?: number;
|
||||
}) => {
|
||||
const args = to && from ? `?to=${to}&from=${from}` : '';
|
||||
return `#/link-to/${nodeType}-detail/${nodeName}${args}`;
|
||||
};
|
|
@ -8,24 +8,32 @@ import compose from 'lodash/fp/compose';
|
|||
import React from 'react';
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom';
|
||||
|
||||
import { InfraNodeType } from 'x-pack/plugins/infra/common/graphql/types';
|
||||
import { LoadingPage } from '../../components/loading_page';
|
||||
import { replaceLogFilterInQueryString } from '../../containers/logs/with_log_filter';
|
||||
import { replaceLogPositionInQueryString } from '../../containers/logs/with_log_position';
|
||||
import { WithSource } from '../../containers/with_source';
|
||||
import { getTimeFromLocation } from './query_params';
|
||||
|
||||
export const RedirectToContainerLogs = ({
|
||||
match,
|
||||
type RedirectToNodeLogsProps = RouteComponentProps<{
|
||||
nodeName: string;
|
||||
nodeType: InfraNodeType;
|
||||
}>;
|
||||
|
||||
export const RedirectToNodeLogs = ({
|
||||
match: {
|
||||
params: { nodeName, nodeType },
|
||||
},
|
||||
location,
|
||||
}: RouteComponentProps<{ containerId: string }>) => (
|
||||
}: RedirectToNodeLogsProps) => (
|
||||
<WithSource>
|
||||
{({ configuredFields }) => {
|
||||
if (!configuredFields) {
|
||||
return <LoadingPage message="Loading container logs" />;
|
||||
return <LoadingPage message={`Loading ${nodeType} logs`} />;
|
||||
}
|
||||
|
||||
const searchString = compose(
|
||||
replaceLogFilterInQueryString(`${configuredFields.container}: ${match.params.containerId}`),
|
||||
replaceLogFilterInQueryString(`${configuredFields[nodeType]}: ${nodeName}`),
|
||||
replaceLogPositionInQueryString(getTimeFromLocation(location))
|
||||
)('');
|
||||
|
||||
|
@ -34,10 +42,12 @@ export const RedirectToContainerLogs = ({
|
|||
</WithSource>
|
||||
);
|
||||
|
||||
export const getContainerLogsUrl = ({
|
||||
containerId,
|
||||
export const getNodeLogsUrl = ({
|
||||
nodeName,
|
||||
nodeType,
|
||||
time,
|
||||
}: {
|
||||
containerId: string;
|
||||
nodeName: string;
|
||||
nodeType: InfraNodeType;
|
||||
time?: number;
|
||||
}) => ['#/link-to/container-logs/', containerId, ...(time ? [`?time=${time}`] : [])].join('');
|
||||
}) => [`#/link-to/${nodeType}-logs/`, nodeName, ...(time ? [`?time=${time}`] : [])].join('');
|
|
@ -1,27 +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';
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom';
|
||||
import { createQueryStringForDetailTime } from './create_query_string_for_detail_time';
|
||||
|
||||
export const RedirectToPodDetail = ({ match, location }: RouteComponentProps<{ name: string }>) => {
|
||||
const args = createQueryStringForDetailTime(location);
|
||||
return <Redirect to={`/metrics/pod/${match.params.name}${args}`} />;
|
||||
};
|
||||
|
||||
export const getPodDetailUrl = ({
|
||||
name,
|
||||
to,
|
||||
from,
|
||||
}: {
|
||||
name: string;
|
||||
to?: number;
|
||||
from?: number;
|
||||
}) => {
|
||||
const args = to && from ? `?to=${to}&from=${from}` : '';
|
||||
return `#/link-to/pod-detail/${name}${args}`;
|
||||
};
|
|
@ -1,35 +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 compose from 'lodash/fp/compose';
|
||||
import React from 'react';
|
||||
import { Redirect, RouteComponentProps } from 'react-router-dom';
|
||||
|
||||
import { LoadingPage } from '../../components/loading_page';
|
||||
import { replaceLogFilterInQueryString } from '../../containers/logs/with_log_filter';
|
||||
import { replaceLogPositionInQueryString } from '../../containers/logs/with_log_position';
|
||||
import { WithSource } from '../../containers/with_source';
|
||||
import { getTimeFromLocation } from './query_params';
|
||||
|
||||
export const RedirectToPodLogs = ({ match, location }: RouteComponentProps<{ podId: string }>) => (
|
||||
<WithSource>
|
||||
{({ configuredFields }) => {
|
||||
if (!configuredFields) {
|
||||
return <LoadingPage message="Loading pod logs" />;
|
||||
}
|
||||
|
||||
const searchString = compose(
|
||||
replaceLogFilterInQueryString(`${configuredFields.pod}: ${match.params.podId}`),
|
||||
replaceLogPositionInQueryString(getTimeFromLocation(location))
|
||||
)('');
|
||||
|
||||
return <Redirect to={`/logs?${searchString}`} />;
|
||||
}}
|
||||
</WithSource>
|
||||
);
|
||||
|
||||
export const getPodLogsUrl = ({ podId, time }: { podId: string; time?: number }) =>
|
||||
['#/link-to/pod-logs/', podId, ...(time ? [`?time=${time}`] : [])].join('');
|
|
@ -17,7 +17,7 @@ export const selectTimeUpdatePolicyInterval = (state: WaffleTimeState) =>
|
|||
state.updatePolicy.policy === 'interval' ? state.updatePolicy.interval : null;
|
||||
|
||||
export const selectCurrentTimeRange = createSelector(selectCurrentTime, currentTime => ({
|
||||
from: currentTime - 1000 * 60 * 10,
|
||||
interval: '5m',
|
||||
from: currentTime - 1000 * 60 * 60,
|
||||
interval: '1m',
|
||||
to: currentTime,
|
||||
}));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue