add traceid

This commit is contained in:
liugq 2021-12-13 10:25:05 +08:00
parent f810a4e364
commit 453033ac43
8 changed files with 556 additions and 447 deletions

View File

@ -105,6 +105,7 @@ func main() {
orm.RegisterSchemaWithIndexName(alerting.Alert{}, "alerting-alerts")
orm.RegisterSchemaWithIndexName(alerting.AlertingHistory{}, "alerting-alert-history")
orm.RegisterSchema(elastic.CommonCommand{})
orm.RegisterSchemaWithIndexName(elastic.TraceMeta{}, "traces")
alertSrv.GetScheduler().Start()
},nil){
app.Run()

View File

@ -127,64 +127,64 @@ export default [
// ],
// },
//data
// {
// path: "/data",
// name: "data",
// icon: "database",
// routes: [
// // {
// // path: '/data/overview',
// // name: 'overview',
// // component: './DataManagement/IndexSummary',
// // routes:[
// // { path: '/', redirect: '/' },
// // ],
// // },
// {
// path: "/data/index",
// name: "index",
// component: "./DataManagement/Index",
// routes: [{ path: "/", redirect: "/" }],
// },
// // {
// // path: '/data/document',
// // name: 'document',
// // component: './DataManagement/Document',
// // routes:[
// // { path: '/', redirect: '/' },
// // ],
// // },
// // {
// // path: '/data/template',
// // name: 'template',
// // component: './DataManagement/IndexTemplate',
// // routes:[
// // { path: '/', redirect: '/' },
// // ],
// // },
// // {
// // path: '/data/lifecycle',
// // name: 'lifecycle',
// // component: './DataManagement/IndexLifeCycle',
// // routes:[
// // { path: '/', redirect: '/' },
// // ],
// // },
// {
// routes: [{ path: "/", redirect: "/" }],
// path: "/data/discover",
// name: "discover",
// component: "./DataManagement/Discover",
// },
// {
// routes: [{ path: "/", redirect: "/" }],
// path: "/data/views/",
// name: "indexPatterns",
// component: "./DataManagement/IndexPatterns",
// },
// ],
// },
// data
{
path: "/data",
name: "data",
icon: "database",
routes: [
// {
// path: '/data/overview',
// name: 'overview',
// component: './DataManagement/IndexSummary',
// routes:[
// { path: '/', redirect: '/' },
// ],
// },
{
path: "/data/index",
name: "index",
component: "./DataManagement/Index",
routes: [{ path: "/", redirect: "/" }],
},
// {
// path: '/data/document',
// name: 'document',
// component: './DataManagement/Document',
// routes:[
// { path: '/', redirect: '/' },
// ],
// },
// {
// path: '/data/template',
// name: 'template',
// component: './DataManagement/IndexTemplate',
// routes:[
// { path: '/', redirect: '/' },
// ],
// },
// {
// path: '/data/lifecycle',
// name: 'lifecycle',
// component: './DataManagement/IndexLifeCycle',
// routes:[
// { path: '/', redirect: '/' },
// ],
// },
{
routes: [{ path: "/", redirect: "/" }],
path: "/data/discover",
name: "discover",
component: "./DataManagement/Discover",
},
{
routes: [{ path: "/", redirect: "/" }],
path: "/data/views/",
name: "indexPatterns",
component: "./DataManagement/IndexPatterns",
},
],
},
//search
// {

View File

@ -17,14 +17,14 @@
* under the License.
*/
import { EuiContextMenu, EuiPopover } from '@elastic/eui';
import { InjectedIntl } from '@kbn/i18n/react';
import classNames from 'classnames';
import React, { MouseEvent, useState, useEffect } from 'react';
import { IUiSettingsClient } from 'src/core/public';
import { FilterEditor } from './filter_editor';
import { FilterView } from './filter_view';
import { IIndexPattern } from '../..';
import { EuiContextMenu, EuiPopover } from "@elastic/eui";
import { InjectedIntl } from "@kbn/i18n/react";
import classNames from "classnames";
import React, { MouseEvent, useState, useEffect } from "react";
import { IUiSettingsClient } from "src/core/public";
import { FilterEditor } from "./filter_editor";
import { FilterView } from "./filter_view";
import { IIndexPattern } from "../..";
import {
Filter,
isFilterPinned,
@ -33,8 +33,8 @@ import {
toggleFilterPinned,
toggleFilterDisabled,
getIndexPatternFromFilter,
} from '../../../common';
import { getIndexPatterns } from '../../services';
} from "../../../common";
import { getIndexPatterns } from "../../services";
interface Props {
id: string;
@ -53,9 +53,9 @@ interface LabelOptions {
message?: string;
}
const FILTER_ITEM_OK = '';
const FILTER_ITEM_WARNING = 'warn';
const FILTER_ITEM_ERROR = 'error';
const FILTER_ITEM_OK = "";
const FILTER_ITEM_WARNING = "warn";
const FILTER_ITEM_ERROR = "error";
export type FilterLabelStatus =
| typeof FILTER_ITEM_OK
@ -64,7 +64,9 @@ export type FilterLabelStatus =
export function FilterItem(props: Props) {
const [isPopoverOpen, setIsPopoverOpen] = useState<boolean>(false);
const [indexPatternExists, setIndexPatternExists] = useState<boolean | undefined>(undefined);
const [indexPatternExists, setIndexPatternExists] = useState<
boolean | undefined
>(undefined);
const { id, filter, indexPatterns } = props;
useEffect(() => {
@ -123,26 +125,35 @@ export function FilterItem(props: Props) {
function getClasses(negate: boolean, labelConfig: LabelOptions) {
return classNames(
'globalFilterItem',
"globalFilterItem",
{
'globalFilterItem-isDisabled': isDisabled(labelConfig),
'globalFilterItem-isError': labelConfig.status === FILTER_ITEM_ERROR,
'globalFilterItem-isWarning': labelConfig.status === FILTER_ITEM_WARNING,
'globalFilterItem-isPinned': isFilterPinned(filter),
'globalFilterItem-isExcluded': negate,
"globalFilterItem-isDisabled": isDisabled(labelConfig),
"globalFilterItem-isError": labelConfig.status === FILTER_ITEM_ERROR,
"globalFilterItem-isWarning":
labelConfig.status === FILTER_ITEM_WARNING,
"globalFilterItem-isPinned": isFilterPinned(filter),
"globalFilterItem-isExcluded": negate,
},
props.className
);
}
function getDataTestSubj(labelConfig: LabelOptions) {
const dataTestSubjKey = filter.meta.key ? `filter-key-${filter.meta.key}` : '';
const dataTestSubjKey = filter.meta.key
? `filter-key-${filter.meta.key}`
: "";
const dataTestSubjValue = filter.meta.value
? `filter-value-${isValidLabel(labelConfig) ? labelConfig.title : labelConfig.status}`
: '';
const dataTestSubjNegated = filter.meta.negate ? 'filter-negated' : '';
const dataTestSubjDisabled = `filter-${isDisabled(labelConfig) ? 'disabled' : 'enabled'}`;
const dataTestSubjPinned = `filter-${isFilterPinned(filter) ? 'pinned' : 'unpinned'}`;
? `filter-value-${
isValidLabel(labelConfig) ? labelConfig.title : labelConfig.status
}`
: "";
const dataTestSubjNegated = filter.meta.negate ? "filter-negated" : "";
const dataTestSubjDisabled = `filter-${
isDisabled(labelConfig) ? "disabled" : "enabled"
}`;
const dataTestSubjPinned = `filter-${
isFilterPinned(filter) ? "pinned" : "unpinned"
}`;
return `filter ${dataTestSubjDisabled} ${dataTestSubjKey} ${dataTestSubjValue} ${dataTestSubjPinned} ${dataTestSubjNegated}`;
}
@ -153,52 +164,46 @@ export function FilterItem(props: Props) {
id: 0,
items: [
{
name: isFilterPinned(filter)
? 'Unpin'
: 'Pin across all apps',
icon: 'pin',
name: isFilterPinned(filter) ? "Unpin" : "Pin across all apps",
icon: "pin",
onClick: () => {
setIsPopoverOpen(false);
onTogglePinned();
},
'data-test-subj': 'pinFilter',
"data-test-subj": "pinFilter",
},
{
name: 'Edit filter',
icon: 'pencil',
name: "Edit filter",
icon: "pencil",
panel: 1,
'data-test-subj': 'editFilter',
"data-test-subj": "editFilter",
},
{
name: negate
? 'Include results'
: 'Exclude results',
icon: negate ? 'plusInCircle' : 'minusInCircle',
name: negate ? "Include results" : "Exclude results",
icon: negate ? "plusInCircle" : "minusInCircle",
onClick: () => {
setIsPopoverOpen(false);
onToggleNegated();
},
'data-test-subj': 'negateFilter',
"data-test-subj": "negateFilter",
},
{
name: disabled
? 'Re-enable'
: 'Temporarily disable',
icon: `${disabled ? 'eye' : 'eyeClosed'}`,
name: disabled ? "Re-enable" : "Temporarily disable",
icon: `${disabled ? "eye" : "eyeClosed"}`,
onClick: () => {
setIsPopoverOpen(false);
onToggleDisabled();
},
'data-test-subj': 'disableFilter',
"data-test-subj": "disableFilter",
},
{
name: 'Delete',
icon: 'trash',
name: "Delete",
icon: "trash",
onClick: () => {
setIsPopoverOpen(false);
props.onRemove();
},
'data-test-subj': 'deleteFilter',
"data-test-subj": "deleteFilter",
},
],
},
@ -236,31 +241,23 @@ export function FilterItem(props: Props) {
const allFields = indexPatterns.map((indexPattern) => {
return indexPattern.fields.map((field) => field.name);
});
const flatFields = allFields.reduce((acc: string[], it: string[]) => [...acc, ...it], []);
return flatFields.includes(filter.meta?.key || '');
const flatFields = allFields.reduce(
(acc: string[], it: string[]) => [...acc, ...it],
[]
);
return flatFields.includes(filter.meta?.key || "");
}
function getValueLabel(): LabelOptions {
const label: LabelOptions = {
title: '',
message: '',
title: "",
message: "",
status: FILTER_ITEM_OK,
};
if (indexPatternExists === false) {
label.status = FILTER_ITEM_ERROR;
label.title = props.intl.formatMessage({
id: 'data.filter.filterBar.labelErrorText',
defaultMessage: `Error`,
});
label.message = props.intl.formatMessage(
{
id: 'data.filter.filterBar.labelErrorInfo',
defaultMessage: 'Index pattern {indexPattern} not found',
},
{
indexPattern: filter.meta.index,
}
);
label.title = "Error";
label.message = "Index pattern not found";
} else if (isFilterApplicable()) {
try {
label.title = getDisplayValueFromFilter(filter, indexPatterns);

View File

@ -17,29 +17,28 @@
* under the License.
*/
import _ from 'lodash';
import React, { useEffect, useRef } from 'react';
import { QueryStart, SavedQuery } from '../../query';
import { SearchBar } from './';
import { useFilterManager } from './lib/use_filter_manager';
import { useTimefilter } from './lib/use_timefilter';
import _ from "lodash";
import React, { useEffect, useRef } from "react";
import { QueryStart, SavedQuery } from "../../query";
import { SearchBar } from "./";
import { useFilterManager } from "./lib/use_filter_manager";
import { useTimefilter } from "./lib/use_timefilter";
// import { useSavedQuery } from './lib/use_saved_query';
import { Filter, Query, TimeRange } from '../../../common';
import { useQueryStringManager } from './lib/use_query_string_manager';
import { Filter, Query, TimeRange } from "../../../common";
import { useQueryStringManager } from "./lib/use_query_string_manager";
// Respond to user changing the filters
const defaultFiltersUpdated = (props) => {
return (filters: Filter[]) => {
props.filterManager.setFilters(filters);
if (props.onQuerySubmit)
props.onQuerySubmit();
if (props.onQuerySubmit) props.onQuerySubmit();
};
};
// Respond to user changing the refresh settings
const defaultOnRefreshChange = (props) => {
// const { timefilter } = props.timefilter;
const timefilter = props.timefilter
const timefilter = props.timefilter;
return (options: { isPaused: boolean; refreshInterval: number }) => {
timefilter.setRefreshInterval({
value: options.refreshInterval,
@ -49,14 +48,11 @@ const defaultOnRefreshChange = (props) => {
};
// Respond to user changing the query string or time settings
const defaultOnQuerySubmit = (
props,
currentQuery
) => {
const defaultOnQuerySubmit = (props, currentQuery) => {
if (!props.useDefaultBehaviors) return props.onQuerySubmit;
//const { timefilter } = props.timefilter;
const timefilter = props.timefilter;
const timefilter = props.timefilter;
return (payload: { dateRange: TimeRange; query?: Query }) => {
const isUpdate =
@ -69,8 +65,7 @@ const defaultOnQuerySubmit = (
} else {
props.queryString.clearQuery();
}
}
else {
} else {
// Refresh button triggered for an update
if (props.onQuerySubmit)
props.onQuerySubmit(
@ -143,7 +138,7 @@ export function createSearchBar() {
useEffect(() => {
if (!useDefaultBehaviors || !props.onQuerySubmit) return; //!onQuerySubmitRef.current
//onQuerySubmitRef.current(
props.onQuerySubmit(
props.onQuerySubmit(
{
dateRange: timeRange,
query,
@ -153,34 +148,34 @@ export function createSearchBar() {
}, [query, timeRange, useDefaultBehaviors, props.onQuerySubmit]);
return (
<SearchBar
showAutoRefreshOnly={props.showAutoRefreshOnly}
showDatePicker={props.showDatePicker}
showFilterBar={props.showFilterBar}
showQueryBar={props.showQueryBar}
showQueryInput={props.showQueryInput}
showSaveQuery={props.showSaveQuery}
screenTitle={props.screenTitle}
indexPatterns={props.indexPatterns}
indicateNoData={props.indicateNoData}
timeHistory={props.timefilter.history}
dateRangeFrom={timeRange.from}
dateRangeTo={timeRange.to}
refreshInterval={refreshInterval.value}
isRefreshPaused={refreshInterval.pause}
filters={filters}
query={query}
onFiltersUpdated={defaultFiltersUpdated(props)}
onRefreshChange={defaultOnRefreshChange(props)}
//savedQuery={savedQuery}
onQuerySubmit={defaultOnQuerySubmit(props, query)}
//onClearSavedQuery={defaultOnClearSavedQuery(props, clearSavedQuery)}
//onSavedQueryUpdated={defaultOnSavedQueryUpdated(props, setSavedQuery)}
//onSaved={defaultOnSavedQueryUpdated(props, setSavedQuery)}
{...overrideDefaultBehaviors(props)}
storage={props.storage}
services={props.services}
/>
<SearchBar
showAutoRefreshOnly={props.showAutoRefreshOnly}
showDatePicker={props.showDatePicker}
showFilterBar={props.showFilterBar}
showQueryBar={props.showQueryBar}
showQueryInput={props.showQueryInput}
showSaveQuery={props.showSaveQuery}
screenTitle={props.screenTitle}
indexPatterns={props.indexPatterns}
indicateNoData={props.indicateNoData}
timeHistory={props.timefilter.history}
dateRangeFrom={timeRange.from}
dateRangeTo={timeRange.to}
refreshInterval={refreshInterval.value}
isRefreshPaused={refreshInterval.pause}
filters={filters}
query={query}
onFiltersUpdated={defaultFiltersUpdated(props)}
onRefreshChange={defaultOnRefreshChange(props)}
//savedQuery={savedQuery}
onQuerySubmit={defaultOnQuerySubmit(props, query)}
//onClearSavedQuery={defaultOnClearSavedQuery(props, clearSavedQuery)}
//onSavedQueryUpdated={defaultOnSavedQueryUpdated(props, setSavedQuery)}
//onSaved={defaultOnSavedQueryUpdated(props, setSavedQuery)}
{...overrideDefaultBehaviors(props)}
storage={props.storage}
services={props.services}
/>
);
};
}

View File

@ -17,7 +17,7 @@
* under the License.
*/
import React, { useState } from 'react';
import React, { useState } from "react";
import {
EuiButtonEmpty,
EuiPopover,
@ -28,10 +28,9 @@ import {
EuiTabbedContent,
EuiTab,
EuiSwitch,
} from '@elastic/eui';
import { EuiSelectableProps } from '@elastic/eui/src/components/selectable/selectable';
import { IndexPatternRef } from './types';
} from "@elastic/eui";
import { EuiSelectableProps } from "@elastic/eui/src/components/selectable/selectable";
import { IndexPatternRef } from "./types";
export type ChangeIndexPatternTriggerProps = EuiButtonEmptyProps & {
label: string;
@ -55,7 +54,7 @@ export function ChangeIndexPattern({
}) {
const [isPopoverOpen, setPopoverIsOpen] = useState(false);
const createTrigger = function () {
const createTrigger = function() {
const { label, title, ...rest } = trigger;
return (
<EuiButtonEmpty
@ -72,100 +71,133 @@ export function ChangeIndexPattern({
</EuiButtonEmpty>
);
};
const [selectedTabId, setSelectedTabId] = useState(indices.includes(indexPatternId) ? 1 :0);
const indexNames = (indexPatternId || "").split(",");
const [selectedTabId, setSelectedTabId] = useState(
indexNames.every((index) => indices.includes(index)) ? 1 : 0
);
const singleSelection = React.useMemo(() => {
return indexNames.length > 1 ? true : "always";
}, [indexNames]);
const onSelectedTabChanged = (id: number) => {
setSelectedTabId(id);
};
const [includeSystemIndex, setIncludeSystemIndex] = useState(false);
const tabs = React.useMemo(()=>{
const showIndices = includeSystemIndex ? indices: indices.filter(key=>!key.startsWith("."));
const tabs = React.useMemo(() => {
const showIndices = includeSystemIndex
? indices
: indices.filter((key) => !key.startsWith("."));
const tabs = [
{
id: 'view',
name: 'View',
id: "view",
name: "View",
disabled: false,
content: ( <EuiSelectable
style={{marginTop:10}}
data-test-subj="indexPattern-switcher"
{...selectableProps}
searchable
singleSelection="always"
options={indexPatternRefs.map(({ title, id ,viewName}) => ({
label: viewName,
key: id,
value: id,
checked: id === indexPatternId ? 'on' : undefined,
}))}
onChange={(choices) => {
const choice = (choices.find(({ checked }) => checked) as unknown) as {
value: string;
};
onChangeIndexPattern(choice.value, 'view');
setPopoverIsOpen(false);
}}
searchProps={{
compressed: true,
...(selectableProps ? selectableProps.searchProps : undefined),
}}
>
{(list, search) => (
<>
{search}
{list}
</>
)}
</EuiSelectable>),
content: (
<EuiSelectable
style={{ marginTop: 10 }}
data-test-subj="indexPattern-switcher"
{...selectableProps}
searchable
singleSelection="always"
options={indexPatternRefs.map(({ title, id, viewName }) => ({
label: viewName,
key: id,
value: id,
checked: id === indexPatternId ? "on" : undefined,
}))}
onChange={(choices) => {
const choice = (choices.find(
({ checked }) => checked
) as unknown) as {
value: string;
};
onChangeIndexPattern(choice.value, "view");
setPopoverIsOpen(false);
}}
searchProps={{
compressed: true,
...(selectableProps ? selectableProps.searchProps : undefined),
}}
>
{(list, search) => (
<>
{search}
{list}
</>
)}
</EuiSelectable>
),
},
{
id: 'index',
name: 'Index',
id: "index",
name: "Index",
disabled: false,
content:(
content: (
<div>
<div style={{display:'flex', margin:'10px auto', flexDirection: 'row-reverse',}}>
<EuiSwitch
label="Include system index"
checked={includeSystemIndex}
onChange={(e) => setIncludeSystemIndex(!includeSystemIndex)}
/>
<div
style={{
display: "flex",
margin: "10px auto",
flexDirection: "row-reverse",
}}
>
<EuiSwitch
label="Include system index"
checked={includeSystemIndex}
onChange={(e) => setIncludeSystemIndex(!includeSystemIndex)}
/>
</div>
<EuiSelectable
style={{marginTop:5}}
{...selectableProps}
searchable
singleSelection="always"
options={showIndices.map((indexName) => ({
label: indexName,
key: indexName,
value: indexName,
checked: indexName === indexPatternId ? 'on' : undefined,
}))}
onChange={(choices) => {
const choice = (choices.find(({ checked }) => checked) as unknown) as {
value: string;
};
onChangeIndexPattern(choice.value, 'index');
setPopoverIsOpen(false);
}}
searchProps={{
compressed: true,
...(selectableProps ? selectableProps.searchProps : undefined),
}}
>
{(list, search) => (
<>
{search}
{list}
</>
)}
</EuiSelectable></div>),
<EuiSelectable
style={{ marginTop: 5 }}
{...selectableProps}
searchable
singleSelection={singleSelection}
options={showIndices.map((indexName) => ({
label: indexName,
key: indexName,
value: indexName,
checked: indexNames.includes(indexName) ? "on" : undefined,
}))}
onChange={(choices) => {
// const choice = (choices.find(
// ({ checked }) => checked
// ) as unknown) as {
// value: string;
// };
const values = choices
.filter(({ checked }) => checked)
.map((choice) => {
return choice.value;
});
onChangeIndexPattern(values.join(","), "index");
setPopoverIsOpen(false);
}}
searchProps={{
compressed: true,
...(selectableProps ? selectableProps.searchProps : undefined),
}}
>
{(list, search) => (
<>
{search}
{list}
</>
)}
</EuiSelectable>
</div>
),
},
];
return tabs;
},[selectableProps, indexPatternId, indexPatternRefs, indices, includeSystemIndex])
}, [
selectableProps,
indexPatternId,
indexPatternRefs,
indices,
includeSystemIndex,
singleSelection,
]);
const selectedTabContent = React.useMemo(() => {
return tabs.find((obj) => obj.id === selectedTabId)?.content;
@ -199,15 +231,15 @@ export function ChangeIndexPattern({
{/* <EuiPopoverTitle>
</EuiPopoverTitle> */}
{/* <EuiTabs size="s" expand>
{/* <EuiTabs size="s" expand>
{renderTabs()}
</EuiTabs> */}
<EuiTabbedContent
<EuiTabbedContent
tabs={tabs}
initialSelectedTab={tabs[selectedTabId]}
autoFocus="selected"
onTabClick={(tab) => {
const idx = tabs.findIndex(item=>item.id == tab.id);
const idx = tabs.findIndex((item) => item.id == tab.id);
setSelectedTabId(idx);
}}
/>

View File

@ -16,12 +16,12 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { useState, useEffect } from 'react';
import { SavedObject } from 'kibana/public';
import { IIndexPattern, IndexPatternAttributes } from 'src/plugins/data/public';
import React, { useState, useEffect } from "react";
import { SavedObject } from "kibana/public";
import { IIndexPattern, IndexPatternAttributes } from "src/plugins/data/public";
import { IndexPatternRef } from './types';
import { ChangeIndexPattern } from './change_indexpattern';
import { IndexPatternRef } from "./types";
import { ChangeIndexPattern } from "./change_indexpattern";
export interface DiscoverIndexPatternProps {
/**
* list of available index patterns, if length > 1, component offers a "change" link
@ -56,7 +56,7 @@ export function DiscoverIndexPattern({
const [selected, setSelected] = useState({
id: selectedId,
title: selectedTitle || '',
title: selectedTitle || "",
});
useEffect(() => {
const { id, title, viewName } = selectedIndexPattern;
@ -68,37 +68,37 @@ export function DiscoverIndexPattern({
return (
<div className="dscIndexPattern__container">
<ChangeIndexPattern
trigger={{
label: selected.viewName,
title: selected.title,
'data-test-subj': 'indexPattern-switch-link',
className: 'dscIndexPattern__triggerButton',
}}
indexPatternId={selected.id}
indexPatternRefs={options}
onChangeIndexPattern={(id, typ) => {
let indexPattern = null;
if(typ == 'index'){
indices.forEach((indexName)=>{
if(indexName == id){
indexPattern = {
id: indexName,
title: indexName,
viewName: indexName,
}
}
})
}else{
indexPattern = options.find((pattern) => pattern.id === id);
}
if (indexPattern) {
setIndexPattern(id, typ);
setSelected(indexPattern);
}
}}
indices={indices}
/>
<ChangeIndexPattern
trigger={{
label: selected.viewName,
title: selected.title,
"data-test-subj": "indexPattern-switch-link",
className: "dscIndexPattern__triggerButton",
}}
indexPatternId={selected.id}
indexPatternRefs={options}
onChangeIndexPattern={(id, typ) => {
let indexPattern = null;
if (typ == "index") {
// indices.forEach((indexName)=>{
// if(indexName == id){
indexPattern = {
id: id,
title: id,
viewName: id,
};
// }
// })
} else {
indexPattern = options.find((pattern) => pattern.id === id);
}
if (indexPattern) {
setIndexPattern(id, typ);
setSelected(indexPattern);
}
}}
indices={indices}
/>
</div>
);
}

View File

@ -32,7 +32,17 @@ import * as styles from "./discover.scss";
import { Subscription } from "rxjs";
import { connect } from "dva";
import { Card, Spin, message, Select, Icon, Popover } from "antd";
import {
Card,
Spin,
message,
Select,
Icon,
Popover,
Tabs,
Input,
Button,
} from "antd";
// import DiscoverGrid from './Components/discover_grid';
import { flattenHitWrapper } from "../../components/kibana/data/common/index_patterns/index_patterns";
import { getStateColumnActions } from "../../components/kibana/discover/public/application/angular/doc_table/actions/columns";
@ -85,7 +95,9 @@ const Discover = (props) => {
const [state, setState] = useState({
columns: columnsParam || ["_source"], //['name', 'address'],
interval: "auto",
activeTabKey: "normal",
});
const [searchType, setSearchType] = React.useState("normal");
// const [sort, setSort] = useState(null);
@ -100,7 +112,7 @@ const Discover = (props) => {
);
return subscriptions;
}, [props.indexPattern]);
const setIndexPattern = async (id, typ) => {
const setIndexPattern = async (id, typ, filters, isReset = false) => {
const IP = await services.indexPatternService.get(
id,
typ,
@ -113,6 +125,14 @@ const Discover = (props) => {
columns: ["_source"],
sort: [],
});
if (filters && filters.length > 0) {
if (isReset) {
filterManager.setFilters(filters);
} else {
filterManager.addFilters(filters);
}
}
updateQuery();
};
const onTimeFieldChange = async (id, timeField) => {
const IP = await services.indexPatternService.get(
@ -130,6 +150,8 @@ const Discover = (props) => {
const indexPatterns = [indexPattern];
const indexPatternList = props.indexPatternList;
const contentCentered = false; //resultState != 'ready';
const indexPatternRef = React.useRef();
indexPatternRef.current = indexPattern;
indexPatterns.get = (id) => {
return Promise.resolve(indexPatterns.find((ip) => ip.id == id));
@ -143,12 +165,12 @@ const Discover = (props) => {
const updateQuery = useCallback(
async (_payload) => {
if (!indexPattern) {
if (!indexPatternRef.current) {
return;
}
setResultState("loading");
const params = getSearchParams(
_payload?.indexPattern || indexPattern,
_payload?.indexPattern || indexPatternRef.current,
_payload?.interval || state.interval,
_payload?.sort
);
@ -171,7 +193,7 @@ const Discover = (props) => {
// console.log(getEsQuery(indexPattern));
// console.log(timefilter.createFilter(indexPattern));
},
[indexPattern, state.interval]
[state.interval]
);
const onChangeInterval = useCallback(
@ -406,34 +428,82 @@ const Discover = (props) => {
}, [saveDocument, deleteDocument]);
const [settingsVisible, setSettingsVisible] = React.useState(false);
const onTraceIDSearch = React.useCallback(
async (value) => {
const { http } = getContext();
const indexNames = await http
.fetch(http.getServerBasePath() + "/search/trace_id", {
query: {
traceID: value,
},
})
.catch((err) => {
console.log(err);
});
if (indexNames && indexNames.length > 0) {
const newFilters = generateFilters(
filterManager,
"trace_id",
value,
"+",
indexNames.join(",")
);
setIndexPattern(indexNames.join(","), "index", newFilters, true);
setSearchType("normal");
}
},
[setIndexPattern]
);
return (
<Card bordered={false} bodyStyle={{ paddingTop: 10 }}>
<SearchBar
{...{
showSearchBar: false,
showQueryBar: true,
showQueryInput: true,
showDatePicker: showDatePicker,
showFilterBar: true,
useDefaultBehaviors: true,
screenTitle: "",
// filters: filters,
onFiltersUpdated: getContext().defaultFiltersUpdated(),
indexPatterns: [indexPattern],
filterManager,
query: {
language: "kuery",
query: queryParam || "",
},
queryStringManager,
queryString: queryStringManager,
timefilter,
storage,
onQuerySubmit: updateQuery,
services,
}}
/>
<Tabs
animated={false}
tabPosition="right"
activeKey={searchType}
onChange={setSearchType}
type="card"
>
<Tabs.TabPane key="normal" tab="Normal">
<SearchBar
{...{
showSearchBar: false,
showQueryBar: true,
showQueryInput: true,
showDatePicker: showDatePicker,
showFilterBar: true,
useDefaultBehaviors: true,
screenTitle: "",
// filters: filters,
onFiltersUpdated: getContext().defaultFiltersUpdated(),
indexPatterns: [indexPattern],
filterManager,
query: {
language: "kuery",
query: queryParam || "",
},
queryStringManager,
queryString: queryStringManager,
timefilter,
storage,
onQuerySubmit: updateQuery,
services,
}}
/>
</Tabs.TabPane>
<Tabs.TabPane key="traceid" tab="TraceID">
<Input.Search
placeholder="Input trace ID"
enterButton={
<Button icon="search" type="primary">
搜索
</Button>
}
size="large"
onSearch={onTraceIDSearch}
/>
</Tabs.TabPane>
</Tabs>
<EuiPageBody className="dscPageBody" aria-describedby="savedSearchTitle">
<EuiFlexGroup className="dscPageBody__contents" gutterSize="none">
@ -658,6 +728,9 @@ const Discover = (props) => {
};
const DiscoverUI = (props) => {
if (!props.selectedCluster.id) {
return null;
}
const [viewID, setViewID] = useQueryParam("viewID", StringParam);
const [index, setIndex] = useQueryParam("index", StringParam);
// const [type, setType] = useQueryParam('type', StringParam);

View File

@ -1,79 +1,85 @@
import {AutocompleteService} from '../../components/kibana/data/public/autocomplete';
import {FilterManager} from '../../components/kibana/data/public/query/filter_manager/filter_manager';
import {QueryStringManager} from '../../components/kibana/data/public/query/query_string/query_string_manager';
import {Timefilter, TimeHistory} from '../../components/kibana/data/public/query/timefilter';
import { useState, useEffect, createContext } from 'react';
import { Subscription } from 'rxjs';
import {buildEsQuery} from '../../components/kibana/data/common/es_query/es_query/build_es_query';
import {getCalculateAutoTimeExpression} from '../../components/kibana/data/common/search/aggs/utils/calculate_auto_time_expression';
import {intervalOptions} from '../../components/kibana/data/common/search/aggs/buckets/_interval_options';
import {TimeBuckets} from '../../components/kibana/data/common/search/aggs/buckets/lib/time_buckets/time_buckets';
import moment from 'moment';
import { AutocompleteService } from "../../components/kibana/data/public/autocomplete";
import { FilterManager } from "../../components/kibana/data/public/query/filter_manager/filter_manager";
import { QueryStringManager } from "../../components/kibana/data/public/query/query_string/query_string_manager";
import {
Timefilter,
TimeHistory,
} from "../../components/kibana/data/public/query/timefilter";
import { useState, useEffect, createContext } from "react";
import { Subscription } from "rxjs";
import { buildEsQuery } from "../../components/kibana/data/common/es_query/es_query/build_es_query";
import { getCalculateAutoTimeExpression } from "../../components/kibana/data/common/search/aggs/utils/calculate_auto_time_expression";
import { intervalOptions } from "../../components/kibana/data/common/search/aggs/buckets/_interval_options";
import { TimeBuckets } from "../../components/kibana/data/common/search/aggs/buckets/lib/time_buckets/time_buckets";
import moment from "moment";
// import { fetch } from 'umi-request';
import {Fetch} from '../../components/kibana/core/public/http/fetch';
import {SavedObjectsClient} from '../../components/kibana/core/public/saved_objects/saved_objects_client';
import {getIndexPatterns, setIndexPatterns} from '../../components/kibana/data/public/services';
import { Fetch } from "../../components/kibana/core/public/http/fetch";
import { SavedObjectsClient } from "../../components/kibana/core/public/saved_objects/saved_objects_client";
import {
getIndexPatterns,
setIndexPatterns,
} from "../../components/kibana/data/public/services";
import {
IndexPatternsService,
onRedirectNoIndexPattern,
onUnsupportedTimePattern,
IndexPatternsApiClient,
SavedObjectsClientPublicToCommon
} from '../../components/kibana/data/public/index_patterns';
import {FieldFormatsRegistry,} from '../../components/kibana/data/common/field_formats';
import {baseFormattersPublic} from '../../components/kibana/data/public/field_formats';
import { deserializeFieldFormat } from '../../components/kibana/data/public/field_formats/utils/deserialize';
import {ESPrefix} from '@/services/common'
SavedObjectsClientPublicToCommon,
} from "../../components/kibana/data/public/index_patterns";
import { FieldFormatsRegistry } from "../../components/kibana/data/common/field_formats";
import { baseFormattersPublic } from "../../components/kibana/data/public/field_formats";
import { deserializeFieldFormat } from "../../components/kibana/data/public/field_formats/utils/deserialize";
import { ESPrefix } from "@/services/common";
const timeBucketConfig = {
'histogram:maxBars': 100,
'histogram:barTarget': 50,
dateFormat: 'YYYY-MM-DD',
'dateFormat:scaled': [
['', 'HH:mm:ss.SSS'],
['PT1S', 'HH:mm:ss'],
['PT1M', 'HH:mm'],
['PT1H', 'YYYY-MM-DD HH:mm'],
['P1DT', 'YYYY-MM-DD'],
['P1YT', 'YYYY'],
"histogram:maxBars": 100,
"histogram:barTarget": 50,
dateFormat: "YYYY-MM-DD",
"dateFormat:scaled": [
["", "HH:mm:ss.SSS"],
["PT1S", "HH:mm:ss"],
["PT1M", "HH:mm"],
["PT1H", "YYYY-MM-DD HH:mm"],
["P1DT", "YYYY-MM-DD"],
["P1YT", "YYYY"],
],
};
const basePath = {
get:()=>{
return '';
get: () => {
return "";
},
prepend: (path)=>{
prepend: (path) => {
return path;
},
remove: (url)=>{
remove: (url) => {
return url;
},
serverBasePath: '/api/',
}
serverBasePath: "/api/",
};
const http = new Fetch({
basePath,
});
const savedObjects = new SavedObjectsClient(http);
const savedObjectsClient = new SavedObjectsClientPublicToCommon(savedObjects);
const getFieldFormatsConfig = (key)=>{
const getFieldFormatsConfig = (key) => {
return {
['format:defaultTypeMap']: {
"ip": { "id": "ip", "params": {} },
"date": { "id": "date", "params": {} },
"date_nanos": { "id": "date_nanos", "params": {}, "es": true },
"number": { "id": "number", "params": {} },
"boolean": { "id": "boolean", "params": {} },
"histogram": { "id": "histogram", "params": {} },
"_source": { "id": "_source", "params": {} },
"_default_": { "id": "string", "params": {} }
["format:defaultTypeMap"]: {
ip: { id: "ip", params: {} },
date: { id: "date", params: {} },
date_nanos: { id: "date_nanos", params: {}, es: true },
number: { id: "number", params: {} },
boolean: { id: "boolean", params: {} },
histogram: { id: "histogram", params: {} },
_source: { id: "_source", params: {} },
_default_: { id: "string", params: {} },
},
'format:number:defaultPattern': '0,0.[000]',
'format:percent:defaultPattern': '0,0.[000]%',
'format:bytes:defaultPattern': '0,0.[0]b',
'format:currency:defaultPattern': '($0,0.[00])',
"format:number:defaultPattern": "0,0.[000]",
"format:percent:defaultPattern": "0,0.[000]%",
"format:bytes:defaultPattern": "0,0.[0]b",
"format:currency:defaultPattern": "($0,0.[00])",
}[key];
}
};
const fieldFormats = new FieldFormatsRegistry();
fieldFormats.init(
@ -86,39 +92,36 @@ fieldFormats.init(
},
},
baseFormattersPublic
);
fieldFormats.deserialize = deserializeFieldFormat.bind(
fieldFormats
);
);
fieldFormats.deserialize = deserializeFieldFormat.bind(fieldFormats);
const indexPatternsApiClient = new IndexPatternsApiClient(http);
const uiconfigs = {
['metaFields']: ['_source', '_id', '_type', '_index'],//'_score'
defaultIndex: '',
["metaFields"]: ["_source", "_id", "_type", "_index"], //'_score'
defaultIndex: "",
};
const uiSettings = {
get: (key)=>{
return uiconfigs[key]
get: (key) => {
return uiconfigs[key];
},
set: (key, val)=>{
return uiconfigs[key] = val;
set: (key, val) => {
return (uiconfigs[key] = val);
},
getAll: ()=>{
getAll: () => {
return uiconfigs;
}
},
};
const indexPatternService = new IndexPatternsService({
uiSettings,
savedObjectsClient,
apiClient: indexPatternsApiClient,
fieldFormats,
onNotification:()=>{},
onError:()=>{},
onNotification: () => {},
onError: () => {},
onUnsupportedTimePattern,
onRedirectNoIndexPattern,
});
export class Storage {
store;
@ -126,7 +129,7 @@ export class Storage {
this.store = store;
}
get = (key) => {
get = (key) => {
if (!this.store) {
return null;
}
@ -160,33 +163,35 @@ export class Storage {
};
}
const filterManager = new FilterManager();
const storage = new Storage(localStorage);
const queryStringManager = new QueryStringManager(storage);
const timefilterConfig = {
timeDefaults: { from: 'now-15m', to: 'now' },
timeDefaults: { from: "now-15m", to: "now" },
refreshIntervalDefaults: { pause: true, value: 10000 },
};
const timeHistory = new TimeHistory(storage);
const timefilter = new Timefilter(timefilterConfig, timeHistory);
const autocomplete = new AutocompleteService();
autocomplete.setup({autocomplete: autocomplete, http:http}, {
timefilter,
});
autocomplete.setup(
{ autocomplete: autocomplete, http: http },
{
timefilter,
}
);
const getConfig = (key)=>{
const getConfig = (key) => {
const kvals = {
"histogram:maxBars": 100,
"histogram:barTarget": 50,
dateFormat: 'strict_date_optional_time',//'YYYY-MM-DD HH:mm:ss',
'dateFormat:scaled': true,
"histogram:maxBars": 100,
"histogram:barTarget": 50,
dateFormat: "strict_date_optional_time", //'YYYY-MM-DD HH:mm:ss',
"dateFormat:scaled": true,
};
return kvals[key] || '';
return kvals[key] || "";
};
const calculateAutoTimeExpression = getCalculateAutoTimeExpression(getConfig)
const calculateAutoTimeExpression = getCalculateAutoTimeExpression(getConfig);
// console.log(calculateAutoTimeExpression({
// from: timefilter.getTime().from,
// to: timefilter.getTime().to,
@ -203,8 +208,7 @@ const getTimeBuckets = (interval) => {
timeBuckets.setBounds(bounds);
timeBuckets.setInterval(interval);
return timeBuckets; //.getInterval(true);
}
};
const defaultFiltersUpdated = () => {
return (filters) => {
@ -215,7 +219,7 @@ const defaultFiltersUpdated = () => {
// const [getIndexPatterns, setIndexPatterns] = createGetterSetter('IndexPatterns');
export const getContext = ()=>{
export const getContext = () => {
return {
autocomplete: autocomplete,
filterManager,
@ -234,7 +238,7 @@ export const getContext = ()=>{
getTimeBuckets,
fetchESRequest,
services: {
savedObjects:{
savedObjects: {
client: savedObjects,
savedObjectsClient,
},
@ -244,76 +248,83 @@ export const getContext = ()=>{
indexPatternService,
},
http,
}
}
};
};
const getEsQuery = (indexPattern) => {
const timeFilter = timefilter.createFilter(indexPattern);
return buildEsQuery(
indexPattern,
queryStringManager.getQuery(),
[...filterManager.getFilters(), ...(timeFilter ? [timeFilter] : [])],
// getEsQueryConfig(getUiSettings())
[...filterManager.getFilters(), ...(timeFilter ? [timeFilter] : [])]
// getEsQueryConfig(getUiSettings())
);
}
};
const getSearchParams = (indexPattern, internal, sort) =>{
const getSearchParams = (indexPattern, internal, sort) => {
// const timeExp = calculateAutoTimeExpression(timefilter.getTime());
const timeExp = getTimeBuckets(internal).getInterval(true).expression;
// console.log(timeExp, internal)
let esSort = indexPattern.timeFieldName ? [{[indexPattern.timeFieldName]: {order: "desc"}}]: [];
if(sort){
esSort = sort.reduce((sorts, s)=>{
let esSort = indexPattern.timeFieldName
? [{ [indexPattern.timeFieldName]: { order: "desc" } }]
: [];
if (sort) {
esSort = sort.reduce((sorts, s) => {
const [sortField, sortDeriction] = s;
sorts.push({
[sortField]: {order: sortDeriction}
})
[sortField]: { order: sortDeriction },
});
return sorts;
}, [])
}, []);
}
const isCalendarInterval = timeExp.includes('w') || timeExp.includes('d') || timeExp.includes('y') || timeExp.includes('M');
const isCalendarInterval =
timeExp.includes("w") ||
timeExp.includes("d") ||
timeExp.includes("y") ||
timeExp.includes("M");
let aggs = {
2: {
date_histogram: {
//calendar_interval:
[isCalendarInterval? 'calendar_interval' : 'fixed_interval']: timeExp,
[isCalendarInterval ? "calendar_interval" : "fixed_interval"]: timeExp,
field: indexPattern.timeFieldName,
min_doc_count: 1,
time_zone: "Asia/Shanghai"
}
}
time_zone: "Asia/Shanghai",
},
},
};
let esRequest = {
index: indexPattern.index || indexPattern.title,
body:{
body: {
query: getEsQuery(indexPattern),
size: 500,
highlight:{
pre_tags:["@highlighted-field@"],
post_tags:["@highlighted-field@"]
highlight: {
pre_tags: ["@highlighted-field@"],
post_tags: ["@highlighted-field@"],
},
sort: esSort,//
}
}
if(indexPattern.timeFieldName){
esRequest.body['aggs']=aggs;
sort: esSort, //
},
};
if (indexPattern.timeFieldName) {
esRequest.body["aggs"] = aggs;
}
return esRequest;
}
};
const fetchESRequest = (params, clusterID) => {
return fetch(`${ESPrefix}/${clusterID}/search/ese`, {
headers:{
'Content-Type': 'application/json',
headers: {
"Content-Type": "application/json",
},
method: 'POST',
method: "POST",
body: JSON.stringify(params),
}).then( res => {
return res.json()
}).then(resJson=>{
return resJson;
})
}
.then((res) => {
return res.json();
})
.then((resJson) => {
return resJson;
});
};