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.Alert{}, "alerting-alerts")
orm.RegisterSchemaWithIndexName(alerting.AlertingHistory{}, "alerting-alert-history") orm.RegisterSchemaWithIndexName(alerting.AlertingHistory{}, "alerting-alert-history")
orm.RegisterSchema(elastic.CommonCommand{}) orm.RegisterSchema(elastic.CommonCommand{})
orm.RegisterSchemaWithIndexName(elastic.TraceMeta{}, "traces")
alertSrv.GetScheduler().Start() alertSrv.GetScheduler().Start()
},nil){ },nil){
app.Run() app.Run()

View File

@ -127,64 +127,64 @@ export default [
// ], // ],
// }, // },
//data // data
{
path: "/data",
name: "data",
icon: "database",
routes: [
// { // {
// path: "/data", // path: '/data/overview',
// name: "data", // name: 'overview',
// icon: "database", // component: './DataManagement/IndexSummary',
// routes: [ // routes:[
// // { // { path: '/', redirect: '/' },
// // 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",
// },
// ], // ],
// }, // },
{
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 //search
// { // {

View File

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

View File

@ -17,29 +17,28 @@
* under the License. * under the License.
*/ */
import _ from 'lodash'; import _ from "lodash";
import React, { useEffect, useRef } from 'react'; import React, { useEffect, useRef } from "react";
import { QueryStart, SavedQuery } from '../../query'; import { QueryStart, SavedQuery } from "../../query";
import { SearchBar } from './'; import { SearchBar } from "./";
import { useFilterManager } from './lib/use_filter_manager'; import { useFilterManager } from "./lib/use_filter_manager";
import { useTimefilter } from './lib/use_timefilter'; import { useTimefilter } from "./lib/use_timefilter";
// import { useSavedQuery } from './lib/use_saved_query'; // import { useSavedQuery } from './lib/use_saved_query';
import { Filter, Query, TimeRange } from '../../../common'; import { Filter, Query, TimeRange } from "../../../common";
import { useQueryStringManager } from './lib/use_query_string_manager'; import { useQueryStringManager } from "./lib/use_query_string_manager";
// Respond to user changing the filters // Respond to user changing the filters
const defaultFiltersUpdated = (props) => { const defaultFiltersUpdated = (props) => {
return (filters: Filter[]) => { return (filters: Filter[]) => {
props.filterManager.setFilters(filters); props.filterManager.setFilters(filters);
if (props.onQuerySubmit) if (props.onQuerySubmit) props.onQuerySubmit();
props.onQuerySubmit();
}; };
}; };
// Respond to user changing the refresh settings // Respond to user changing the refresh settings
const defaultOnRefreshChange = (props) => { const defaultOnRefreshChange = (props) => {
// const { timefilter } = props.timefilter; // const { timefilter } = props.timefilter;
const timefilter = props.timefilter const timefilter = props.timefilter;
return (options: { isPaused: boolean; refreshInterval: number }) => { return (options: { isPaused: boolean; refreshInterval: number }) => {
timefilter.setRefreshInterval({ timefilter.setRefreshInterval({
value: options.refreshInterval, value: options.refreshInterval,
@ -49,10 +48,7 @@ const defaultOnRefreshChange = (props) => {
}; };
// Respond to user changing the query string or time settings // Respond to user changing the query string or time settings
const defaultOnQuerySubmit = ( const defaultOnQuerySubmit = (props, currentQuery) => {
props,
currentQuery
) => {
if (!props.useDefaultBehaviors) return props.onQuerySubmit; if (!props.useDefaultBehaviors) return props.onQuerySubmit;
//const { timefilter } = props.timefilter; //const { timefilter } = props.timefilter;
@ -69,8 +65,7 @@ const defaultOnQuerySubmit = (
} else { } else {
props.queryString.clearQuery(); props.queryString.clearQuery();
} }
} } else {
else {
// Refresh button triggered for an update // Refresh button triggered for an update
if (props.onQuerySubmit) if (props.onQuerySubmit)
props.onQuerySubmit( props.onQuerySubmit(

View File

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

View File

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

View File

@ -32,7 +32,17 @@ import * as styles from "./discover.scss";
import { Subscription } from "rxjs"; import { Subscription } from "rxjs";
import { connect } from "dva"; 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 DiscoverGrid from './Components/discover_grid';
import { flattenHitWrapper } from "../../components/kibana/data/common/index_patterns/index_patterns"; import { flattenHitWrapper } from "../../components/kibana/data/common/index_patterns/index_patterns";
import { getStateColumnActions } from "../../components/kibana/discover/public/application/angular/doc_table/actions/columns"; import { getStateColumnActions } from "../../components/kibana/discover/public/application/angular/doc_table/actions/columns";
@ -85,7 +95,9 @@ const Discover = (props) => {
const [state, setState] = useState({ const [state, setState] = useState({
columns: columnsParam || ["_source"], //['name', 'address'], columns: columnsParam || ["_source"], //['name', 'address'],
interval: "auto", interval: "auto",
activeTabKey: "normal",
}); });
const [searchType, setSearchType] = React.useState("normal");
// const [sort, setSort] = useState(null); // const [sort, setSort] = useState(null);
@ -100,7 +112,7 @@ const Discover = (props) => {
); );
return subscriptions; return subscriptions;
}, [props.indexPattern]); }, [props.indexPattern]);
const setIndexPattern = async (id, typ) => { const setIndexPattern = async (id, typ, filters, isReset = false) => {
const IP = await services.indexPatternService.get( const IP = await services.indexPatternService.get(
id, id,
typ, typ,
@ -113,6 +125,14 @@ const Discover = (props) => {
columns: ["_source"], columns: ["_source"],
sort: [], sort: [],
}); });
if (filters && filters.length > 0) {
if (isReset) {
filterManager.setFilters(filters);
} else {
filterManager.addFilters(filters);
}
}
updateQuery();
}; };
const onTimeFieldChange = async (id, timeField) => { const onTimeFieldChange = async (id, timeField) => {
const IP = await services.indexPatternService.get( const IP = await services.indexPatternService.get(
@ -130,6 +150,8 @@ const Discover = (props) => {
const indexPatterns = [indexPattern]; const indexPatterns = [indexPattern];
const indexPatternList = props.indexPatternList; const indexPatternList = props.indexPatternList;
const contentCentered = false; //resultState != 'ready'; const contentCentered = false; //resultState != 'ready';
const indexPatternRef = React.useRef();
indexPatternRef.current = indexPattern;
indexPatterns.get = (id) => { indexPatterns.get = (id) => {
return Promise.resolve(indexPatterns.find((ip) => ip.id == id)); return Promise.resolve(indexPatterns.find((ip) => ip.id == id));
@ -143,12 +165,12 @@ const Discover = (props) => {
const updateQuery = useCallback( const updateQuery = useCallback(
async (_payload) => { async (_payload) => {
if (!indexPattern) { if (!indexPatternRef.current) {
return; return;
} }
setResultState("loading"); setResultState("loading");
const params = getSearchParams( const params = getSearchParams(
_payload?.indexPattern || indexPattern, _payload?.indexPattern || indexPatternRef.current,
_payload?.interval || state.interval, _payload?.interval || state.interval,
_payload?.sort _payload?.sort
); );
@ -171,7 +193,7 @@ const Discover = (props) => {
// console.log(getEsQuery(indexPattern)); // console.log(getEsQuery(indexPattern));
// console.log(timefilter.createFilter(indexPattern)); // console.log(timefilter.createFilter(indexPattern));
}, },
[indexPattern, state.interval] [state.interval]
); );
const onChangeInterval = useCallback( const onChangeInterval = useCallback(
@ -406,9 +428,43 @@ const Discover = (props) => {
}, [saveDocument, deleteDocument]); }, [saveDocument, deleteDocument]);
const [settingsVisible, setSettingsVisible] = React.useState(false); 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 ( return (
<Card bordered={false} bodyStyle={{ paddingTop: 10 }}> <Card bordered={false} bodyStyle={{ paddingTop: 10 }}>
<Tabs
animated={false}
tabPosition="right"
activeKey={searchType}
onChange={setSearchType}
type="card"
>
<Tabs.TabPane key="normal" tab="Normal">
<SearchBar <SearchBar
{...{ {...{
showSearchBar: false, showSearchBar: false,
@ -434,6 +490,20 @@ const Discover = (props) => {
services, 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"> <EuiPageBody className="dscPageBody" aria-describedby="savedSearchTitle">
<EuiFlexGroup className="dscPageBody__contents" gutterSize="none"> <EuiFlexGroup className="dscPageBody__contents" gutterSize="none">
@ -658,6 +728,9 @@ const Discover = (props) => {
}; };
const DiscoverUI = (props) => { const DiscoverUI = (props) => {
if (!props.selectedCluster.id) {
return null;
}
const [viewID, setViewID] = useQueryParam("viewID", StringParam); const [viewID, setViewID] = useQueryParam("viewID", StringParam);
const [index, setIndex] = useQueryParam("index", StringParam); const [index, setIndex] = useQueryParam("index", StringParam);
// const [type, setType] = useQueryParam('type', StringParam); // const [type, setType] = useQueryParam('type', StringParam);

View File

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