diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a84593e1..28ac4d63d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan - [#8](https://github.com/kobsio/kobs/pull/8): Add new page to directly query a configured Prometheus datasource. - [#10](https://github.com/kobsio/kobs/pull/10): Add Elasticsearch as datasource for Application logs. - [#12](https://github.com/kobsio/kobs/pull/12): :warning: *Breaking change:* :warning: Add plugin system and readd Prometheus and Elasticsearch as plugins. +- [#13](https://github.com/kobsio/kobs/pull/13): Add Jaeger plugin to show traces for an Application and to compare traces. ### Fixed diff --git a/app/src/App.tsx b/app/src/App.tsx index 0feccefc4..14f9fb5d5 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -33,7 +33,7 @@ const App: React.FunctionComponent = () => { - + diff --git a/app/src/components/Title.tsx b/app/src/components/Title.tsx index b98d1f6b9..2b41e3939 100644 --- a/app/src/components/Title.tsx +++ b/app/src/components/Title.tsx @@ -17,7 +17,7 @@ const Title: React.FunctionComponent = ({ title, subtitle, size }: return ( {title} - {subtitle} + {subtitle} ); }; diff --git a/app/src/components/applications/ApplicationTabs.tsx b/app/src/components/applications/ApplicationTabs.tsx index a4e542ea1..b17affaa4 100644 --- a/app/src/components/applications/ApplicationTabs.tsx +++ b/app/src/components/applications/ApplicationTabs.tsx @@ -1,7 +1,7 @@ import { Tab, TabTitleText, Tabs } from '@patternfly/react-core'; import React from 'react'; -import { Plugin } from 'proto/plugins_pb'; +import { Plugin } from 'proto/plugins_grpc_web_pb'; interface IApplicationTabsProps { activeTab: string; diff --git a/app/src/components/plugins/Plugin.tsx b/app/src/components/plugins/Plugin.tsx index 64a264c29..5287f7815 100644 --- a/app/src/components/plugins/Plugin.tsx +++ b/app/src/components/plugins/Plugin.tsx @@ -2,7 +2,7 @@ import { Alert, AlertVariant } from '@patternfly/react-core'; import React, { useContext } from 'react'; import { IPluginsContext, PluginsContext } from 'context/PluginsContext'; -import { Plugin as IPlugin } from 'proto/plugins_pb'; +import { Plugin as IPlugin } from 'proto/plugins_grpc_web_pb'; import { plugins } from 'utils/plugins'; interface IPluginProps { diff --git a/app/src/components/plugins/PluginDataMissing.tsx b/app/src/components/plugins/PluginDataMissing.tsx index 54e709fc5..d047472b6 100644 --- a/app/src/components/plugins/PluginDataMissing.tsx +++ b/app/src/components/plugins/PluginDataMissing.tsx @@ -1,12 +1,11 @@ -import { Button, EmptyState, EmptyStateBody, EmptyStateIcon, Title } from '@patternfly/react-core'; +import { Brand, Button, EmptyState, EmptyStateBody, EmptyStateIcon, Title } from '@patternfly/react-core'; import React from 'react'; interface IPluginDataMissingProps { title: string; description: string; documentation: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - icon: React.ComponentType; + type: string; } // PluginDataMissing is the component, which is displayed when the user defines a plugin in an Application CR, but the @@ -15,12 +14,16 @@ interface IPluginDataMissingProps { const PluginDataMissing: React.FunctionComponent = ({ title, description, - icon, documentation, + type, }: IPluginDataMissingProps) => { + const PluginIcon: React.FunctionComponent = () => { + return ; + }; + return ( - + {title} diff --git a/app/src/components/resources/ToolbarItemNamespaces.tsx b/app/src/components/resources/ToolbarItemNamespaces.tsx index 9483758af..e22149029 100644 --- a/app/src/components/resources/ToolbarItemNamespaces.tsx +++ b/app/src/components/resources/ToolbarItemNamespaces.tsx @@ -1,8 +1,7 @@ import React, { useCallback, useEffect, useState } from 'react'; import { Select, SelectOption, SelectVariant } from '@patternfly/react-core'; -import { GetNamespacesRequest, GetNamespacesResponse } from 'proto/clusters_pb'; -import { ClustersPromiseClient } from 'proto/clusters_grpc_web_pb'; +import { ClustersPromiseClient, GetNamespacesRequest, GetNamespacesResponse } from 'proto/clusters_grpc_web_pb'; import { apiURL } from 'utils/constants'; // clustersService is the Clusters gRPC service, which is used to get all namespaces for the selected clusters. diff --git a/app/src/context/ClustersContext.tsx b/app/src/context/ClustersContext.tsx index e9e77e7ce..5b03b1a27 100644 --- a/app/src/context/ClustersContext.tsx +++ b/app/src/context/ClustersContext.tsx @@ -1,9 +1,14 @@ import { Alert, AlertActionLink, AlertVariant, Spinner } from '@patternfly/react-core'; import React, { useCallback, useEffect, useState } from 'react'; -import { GetCRDsRequest, GetCRDsResponse, GetClustersRequest, GetClustersResponse } from 'proto/clusters_pb'; +import { + ClustersPromiseClient, + GetCRDsRequest, + GetCRDsResponse, + GetClustersRequest, + GetClustersResponse, +} from 'proto/clusters_grpc_web_pb'; import { IResources, customResourceDefinition } from 'utils/resources'; -import { ClustersPromiseClient } from 'proto/clusters_grpc_web_pb'; import { apiURL } from 'utils/constants'; // clustersService is the Clusters gRPC service, which is used to get all clusters and Custom Resource Definitions. diff --git a/app/src/context/PluginsContext.tsx b/app/src/context/PluginsContext.tsx index 50d06891a..b04587880 100644 --- a/app/src/context/PluginsContext.tsx +++ b/app/src/context/PluginsContext.tsx @@ -1,8 +1,7 @@ import { Alert, AlertActionLink, AlertVariant, Spinner } from '@patternfly/react-core'; import React, { useCallback, useEffect, useState } from 'react'; -import { GetPluginsRequest, GetPluginsResponse, PluginShort } from 'proto/plugins_pb'; -import { PluginsPromiseClient } from 'proto/plugins_grpc_web_pb'; +import { GetPluginsRequest, GetPluginsResponse, PluginShort, PluginsPromiseClient } from 'proto/plugins_grpc_web_pb'; import { apiURL } from 'utils/constants'; // pluginsService is the Plugins gRPC service, which is used to get all configured plugins. diff --git a/app/src/plugins/elasticsearch/ElasticsearchPlugin.tsx b/app/src/plugins/elasticsearch/ElasticsearchPlugin.tsx index 28b72af5c..20d702192 100644 --- a/app/src/plugins/elasticsearch/ElasticsearchPlugin.tsx +++ b/app/src/plugins/elasticsearch/ElasticsearchPlugin.tsx @@ -1,5 +1,4 @@ import React, { useState } from 'react'; -import ListIcon from '@patternfly/react-icons/dist/js/icons/list-icon'; import ElasticsearchLogs from 'plugins/elasticsearch/ElasticsearchLogs'; import ElasticsearchPluginToolbar from 'plugins/elasticsearch/ElasticsearchPluginToolbar'; @@ -45,7 +44,7 @@ const ElasticsearchPlugin: React.FunctionComponent = ({ title="Elasticsearch properties are missing" description="The Elasticsearch properties are missing in your CR for this application. Visit the documentation to learn more on how to use the Elasticsearch plugin in an Application CR." documentation="https://kobs.io" - icon={ListIcon} + type="elasticsearch" /> ); } diff --git a/app/src/plugins/jaeger/JaegerPage.tsx b/app/src/plugins/jaeger/JaegerPage.tsx new file mode 100644 index 000000000..60bce55f1 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerPage.tsx @@ -0,0 +1,23 @@ +import { Route, Switch } from 'react-router-dom'; +import React from 'react'; + +import { IPluginPageProps } from 'utils/plugins'; +import JaegerPageCompare from 'plugins/jaeger/JaegerPageCompare'; +import JaegerPageTraces from 'plugins/jaeger/JaegerPageTraces'; + +// JaegerPage is the component, which implements the page component for the Jaeger plugin. The Jaeger plugin supports, +// two routes, one to search for traces and another one to render a single trace and compare it with another one. +const JaegerPage: React.FunctionComponent = ({ name, description }: IPluginPageProps) => { + return ( + + + + + + + + + ); +}; + +export default JaegerPage; diff --git a/app/src/plugins/jaeger/JaegerPageCompare.tsx b/app/src/plugins/jaeger/JaegerPageCompare.tsx new file mode 100644 index 000000000..141b2e852 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerPageCompare.tsx @@ -0,0 +1,68 @@ +import { Grid, GridItem } from '@patternfly/react-core'; +import React, { useEffect, useState } from 'react'; +import { useHistory, useLocation, useParams } from 'react-router-dom'; +import CloseIcon from '@patternfly/react-icons/dist/js/icons/close-icon'; + +import JaegerPageCompareInput from 'plugins/jaeger/JaegerPageCompareInput'; +import JaegerPageCompareTrace from 'plugins/jaeger/JaegerPageCompareTrace'; + +interface IJaegerPageCompareParams { + traceID: string; +} + +interface IJaegerPageCompareProps { + name: string; +} + +// JaegerPageCompare is the component, which renders two traces for comparison. +const JaegerPageCompare: React.FunctionComponent = ({ name }: IJaegerPageCompareProps) => { + const params = useParams(); + const history = useHistory(); + const location = useLocation(); + const [compareTrace, setCompareTrace] = useState(''); + + // changeCompareTrace is used to set the trace id, which should be compared against the trace id, which is provided as + // parameter in the URL. + const changeCompareTrace = (traceID: string): void => { + history.push({ + pathname: location.pathname, + search: `?compare=${traceID}`, + }); + }; + + // useEffect is used to set the options every time the search location for the current URL changes. The URL is changed + // via the changeOptions function. When the search location is changed we modify the options state. + useEffect(() => { + const params = new URLSearchParams(location.search); + const traceID = params.get('compare'); + setCompareTrace(traceID ? traceID : ''); + }, [location.search]); + + return ( + + + + : null} + /> + + + {compareTrace ? ( + + changeCompareTrace('')} /> + } + /> + + ) : null} + + + ); +}; + +export default JaegerPageCompare; diff --git a/app/src/plugins/jaeger/JaegerPageCompareInput.tsx b/app/src/plugins/jaeger/JaegerPageCompareInput.tsx new file mode 100644 index 000000000..fa9159109 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerPageCompareInput.tsx @@ -0,0 +1,40 @@ +import { Button, ButtonVariant, InputGroup, InputGroupText, TextInput } from '@patternfly/react-core'; +import React, { useState } from 'react'; +import SearchIcon from '@patternfly/react-icons/dist/js/icons/search-icon'; + +interface IJaegerPageCompareInputProps { + changeCompareTrace: (traceID: string) => void; +} + +// JaegerPageCompareInput is the component, which allows the user to provide a second trace id, to compare two traces. +const JaegerPageCompareInput: React.FunctionComponent = ({ + changeCompareTrace, +}: IJaegerPageCompareInputProps) => { + const [compareTrace, setCompareTrace] = useState(''); + + // onEnter is used to detect if the user pressed the "ENTER" key. If this is the case we are calling the + // changeCompareTrace function to trigger the comparision of traces. + const onEnter = (e: React.KeyboardEvent | undefined): void => { + if (e?.key === 'Enter' && !e.shiftKey) { + changeCompareTrace(compareTrace); + } + }; + + return ( + + Trace ID: + + + + ); +}; + +export default JaegerPageCompareInput; diff --git a/app/src/plugins/jaeger/JaegerPageCompareTrace.tsx b/app/src/plugins/jaeger/JaegerPageCompareTrace.tsx new file mode 100644 index 000000000..8c26fd085 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerPageCompareTrace.tsx @@ -0,0 +1,139 @@ +import { + Alert, + AlertActionLink, + AlertVariant, + Grid, + GridItem, + PageSection, + PageSectionVariants, + Spinner, + Title, +} from '@patternfly/react-core'; +import React, { useCallback, useEffect, useState } from 'react'; +import { useHistory } from 'react-router-dom'; + +import { GetTraceRequest, GetTraceResponse, JaegerPromiseClient } from 'proto/jaeger_grpc_web_pb'; +import { ITrace, formatTraceTime, getDuration } from 'plugins/jaeger/helpers'; +import JaegerSpans from 'plugins/jaeger/JaegerSpans'; +import { apiURL } from 'utils/constants'; + +// jaegerService is the gRPC service to get the traces from a Jaeger instance. +const jaegerService = new JaegerPromiseClient(apiURL, null, null); + +interface IDataState { + trace?: ITrace; + error: string; + isLoading: boolean; +} + +interface IJaegerPageCompareTraceProps { + name: string; + traceID: string; + headerComponent: React.ReactNode; +} + +// JaegerPageCompareTrace loads a single trace. +const JaegerPageCompareTrace: React.FunctionComponent = ({ + name, + traceID, + headerComponent, +}: IJaegerPageCompareTraceProps) => { + const history = useHistory(); + const [data, setData] = useState({ error: '', isLoading: true, trace: undefined }); + + // fetchTrace returns a single trace for the give trace id. + const fetchTrace = useCallback(async (): Promise => { + try { + setData({ error: '', isLoading: true, trace: undefined }); + + const getTraceRequest = new GetTraceRequest(); + getTraceRequest.setName(name); + getTraceRequest.setTraceid(traceID); + + const getTraceResponse: GetTraceResponse = await jaegerService.getTrace(getTraceRequest, null); + const trace = JSON.parse(getTraceResponse.toObject().traces).data; + + setData({ error: '', isLoading: false, trace: trace.length === 1 ? trace[0] : undefined }); + } catch (err) { + setData({ error: err.message, isLoading: false, trace: undefined }); + } + }, [name, traceID]); + + // useEffect is used to call the fetchTrace function every time the required props are changing. + useEffect(() => { + fetchTrace(); + }, [fetchTrace]); + + // When the loading identicator is true, we show a spinner component. + if (data.isLoading) { + return ; + } + + // When an error occured during the execution of the fetchTrace function, we show the error in an Alert component. + if (data.error || !data.trace) { + return ( + + history.push('/')}>Home + Retry + + } + > +

{data.error ? data.error : 'Trace is undefined'}

+
+ ); + } + + return ( + + + + + + {data.trace.processes[data.trace.spans[0].processID].serviceName}: {data.trace.spans[0].operationName}{' '} + <span className="pf-u-pl-sm pf-u-font-size-sm pf-u-color-400">{data.trace.traceID}</span> + +

+ + Trace Start: + {formatTraceTime(data.trace.spans[0].startTime)} + + + Duration: + {getDuration(data.trace.spans)}ms + + + Services: + {Object.keys(data.trace.processes).length} + + + Total Spans: + {data.trace.spans.length} + +

+
+
+ + {headerComponent ? ( + + + {headerComponent} + + + ) : null} + + + + + + +
+
+ ); +}; + +export default JaegerPageCompareTrace; diff --git a/app/src/plugins/jaeger/JaegerPageToolbar.tsx b/app/src/plugins/jaeger/JaegerPageToolbar.tsx new file mode 100644 index 000000000..2b98b30c1 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerPageToolbar.tsx @@ -0,0 +1,207 @@ +import { + Alert, + AlertActionLink, + AlertVariant, + Button, + ButtonVariant, + TextInput, + Toolbar, + ToolbarContent, + ToolbarGroup, + ToolbarItem, + ToolbarToggleGroup, +} from '@patternfly/react-core'; +import React, { useCallback, useEffect, useState } from 'react'; +import FilterIcon from '@patternfly/react-icons/dist/js/icons/filter-icon'; +import SearchIcon from '@patternfly/react-icons/dist/js/icons/search-icon'; + +import { GetOperationsRequest, GetOperationsResponse, JaegerPromiseClient } from 'proto/jaeger_grpc_web_pb'; +import Options, { IAdditionalFields } from 'components/Options'; +import { IJaegerOptions } from 'plugins/jaeger/helpers'; +import JaegerPageToolbarSelect from 'plugins/jaeger/JaegerPageToolbarSelect'; +import { apiURL } from 'utils/constants'; + +// jaegerService is the gRPC service get all services and operations for Jaeger. +const jaegerService = new JaegerPromiseClient(apiURL, null, null); + +interface IDataState { + error: string; + operations: string[]; + services: string[]; +} +// IJaegerPageToolbarProps is the interface for all properties, which can be passed to the JaegerPageToolbar component. +// This are all available Jaeger options and a function to write changes to these properties back to the parent +// component. +interface IJaegerPageToolbarProps extends IJaegerOptions { + name: string; + changeOptions: (data: IJaegerOptions) => void; +} + +// JaegerPageToolbar is the toolbar for the Jaeger plugin page. It allows a user to specify all options to get traces +// from a Jaeger instance. +const JaegerPageToolbar: React.FunctionComponent = ({ + name, + limit, + maxDuration, + minDuration, + operation, + service, + tags, + timeEnd, + timeStart, + changeOptions, +}: IJaegerPageToolbarProps) => { + const [data, setData] = useState({ error: '', operations: [], services: [] }); + const [options, setOptions] = useState({ + limit: limit, + maxDuration: maxDuration, + minDuration: minDuration, + operation: operation, + queryName: '', + service: service, + tags: tags, + timeEnd: timeEnd, + timeStart: timeStart, + }); + + // changeAddtionalOptions changes the Jaeger options. This function is passed to the shared Options component. + const changeAddtionalOptions = ( + additionalFields: IAdditionalFields[] | undefined, + timeEnd: number, + timeStart: number, + ): void => { + if (additionalFields && additionalFields.length === 3) { + setOptions({ + ...options, + limit: additionalFields[0].value, + maxDuration: additionalFields[1].value, + minDuration: additionalFields[2].value, + timeEnd: timeEnd, + timeStart: timeStart, + }); + } + }; + + // fetchOperations is used to retrieve the operations for the given service or if no service is specified also a list + // of services. + const fetchOperations = useCallback(async (): Promise => { + try { + const getOperationsRequest = new GetOperationsRequest(); + getOperationsRequest.setName(name); + getOperationsRequest.setService(options.service); + + const getOperationsResponse: GetOperationsResponse = await jaegerService.getOperations( + getOperationsRequest, + null, + ); + const { servicesList, operationsList } = getOperationsResponse.toObject(); + + if (servicesList.length > 0) { + setData({ error: '', operations: operationsList.map((operation) => operation.name), services: servicesList }); + } else { + setData((d) => { + return { ...d, error: '', operations: operationsList.map((operation) => operation.name) }; + }); + } + } catch (err) { + setData({ error: err.message, operations: [], services: [] }); + } + }, [name, options.service]); + + // useEffect is used to call the fetchOperations function everytime the Jaeger the service is changed are changed. + useEffect(() => { + fetchOperations(); + }, [fetchOperations]); + + if (data.error) { + return ( + + Retry + + } + > +

{data.error}

+
+ ); + } + + return ( + + + } breakpoint="lg"> + + + setOptions({ ...options, service: item })} + /> + + + setOptions({ ...options, operation: item })} + /> + + Tags + + setOptions({ ...options, tags: value })} + /> + + + + + + + + + + + + ); +}; + +export default JaegerPageToolbar; diff --git a/app/src/plugins/jaeger/JaegerPageToolbarSelect.tsx b/app/src/plugins/jaeger/JaegerPageToolbarSelect.tsx new file mode 100644 index 000000000..1e56a0b5b --- /dev/null +++ b/app/src/plugins/jaeger/JaegerPageToolbarSelect.tsx @@ -0,0 +1,47 @@ +import React, { useState } from 'react'; +import { Select, SelectOption, SelectOptionObject, SelectVariant } from '@patternfly/react-core'; + +interface IJaegerPageToolbarSelectProps { + placeholder: string; + items: string[]; + selectedItem: string; + selectItem: (item: string) => void; +} + +// JaegerPageToolbarSelect provides a select box for the services and operations for Jaeger. +const JaegerPageToolbarSelect: React.FunctionComponent = ({ + placeholder, + items, + selectedItem, + selectItem, +}: IJaegerPageToolbarSelectProps) => { + const [show, setShow] = useState(false); + + // changeItem changes the service/operations and the closes the select options. + const changeItem = ( + event: React.MouseEvent | React.ChangeEvent, + value: string | SelectOptionObject, + isPlaceholder?: boolean | undefined, + ): void => { + selectItem(value as string); + setShow(false); + }; + + return ( + + ); +}; + +export default JaegerPageToolbarSelect; diff --git a/app/src/plugins/jaeger/JaegerPageTraces.tsx b/app/src/plugins/jaeger/JaegerPageTraces.tsx new file mode 100644 index 000000000..2d0e5a48f --- /dev/null +++ b/app/src/plugins/jaeger/JaegerPageTraces.tsx @@ -0,0 +1,88 @@ +import { + Drawer, + DrawerContent, + DrawerContentBody, + PageSection, + PageSectionVariants, + Title, +} from '@patternfly/react-core'; +import React, { useEffect, useState } from 'react'; +import { useHistory, useLocation } from 'react-router-dom'; + +import { IJaegerOptions, getOptionsFromSearch } from 'plugins/jaeger/helpers'; +import { IPluginPageProps } from 'utils/plugins'; +import JaegerPageToolbar from 'plugins/jaeger/JaegerPageToolbar'; +import JaegerTraces from 'plugins/jaeger/JaegerTraces'; + +const JaegerPageTraces: React.FunctionComponent = ({ name, description }: IPluginPageProps) => { + const history = useHistory(); + const location = useLocation(); + const [options, setOptions] = useState(getOptionsFromSearch(location.search)); + const [trace, setTrace] = useState(undefined); + + // changeOptions is used to change the options for an Jaeger query. Instead of directly modifying the options + // state we change the URL parameters. + const changeOptions = (opts: IJaegerOptions): void => { + history.push({ + pathname: location.pathname, + search: `?limit=${opts.limit}&maxDuration=${opts.maxDuration}&minDuration=${opts.minDuration}&operation=${opts.operation}&service=${opts.service}&tags=${opts.tags}&timeEnd=${opts.timeEnd}&timeStart=${opts.timeStart}`, + }); + }; + + // useEffect is used to set the options every time the search location for the current URL changes. The URL is changed + // via the changeOptions function. When the search location is changed we modify the options state. + useEffect(() => { + setOptions(getOptionsFromSearch(location.search)); + }, [location.search]); + + return ( + + + + {name} + +

{description}

+ +
+ + + + + + {options.service ? ( + + ) : null} + + + + +
+ ); +}; + +export default JaegerPageTraces; diff --git a/app/src/plugins/jaeger/JaegerPlugin.tsx b/app/src/plugins/jaeger/JaegerPlugin.tsx new file mode 100644 index 000000000..c3bca4257 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerPlugin.tsx @@ -0,0 +1,96 @@ +import React, { useState } from 'react'; + +import { IJaegerOptions } from 'plugins/jaeger/helpers'; +import { IPluginProps } from 'utils/plugins'; +import JaegerPluginToolbar from 'plugins/jaeger/JaegerPluginToolbar'; +import JaegerTraces from 'plugins/jaeger/JaegerTraces'; +import PluginDataMissing from 'components/plugins/PluginDataMissing'; + +// ElasticsearchPlugin is the plugin component for the Elasticsearch plugin. It renders a toolbar, which allows a user +// to select the specified queries for an application. +const ElasticsearchPlugin: React.FunctionComponent = ({ + isInDrawer, + name, + description, + plugin, + showDetails, +}: IPluginProps) => { + const initialQuery = plugin.jaeger && plugin.jaeger.queriesList.length > 0 ? plugin.jaeger.queriesList[0] : undefined; + + const [options, setOptions] = useState({ + limit: '20', + maxDuration: '', + minDuration: '', + operation: initialQuery ? initialQuery.operation : '', + queryName: initialQuery ? initialQuery.name : '', + service: initialQuery ? initialQuery.service : '', + tags: initialQuery ? initialQuery.tags : '', + timeEnd: Math.floor(Date.now() / 1000), + timeStart: Math.floor(Date.now() / 1000) - 3600, + }); + + // When the elasticsearch property of the plugin is missing, we use the shared PluginDataMissing component, with a + // link to the corresponding documentation for the Elasticsearch plugin. + if (!plugin.jaeger) { + return ( + + ); + } + + return ( + + + setOptions({ ...options, operation: operation, queryName: name, service: service, tags: tags }) + } + setOptions={( + limit: string, + maxDuration: string, + minDuration: string, + timeEnd: number, + timeStart: number, + ): void => + setOptions({ + ...options, + limit: limit, + maxDuration: maxDuration, + minDuration: minDuration, + timeEnd: timeEnd, + timeStart: timeStart, + }) + } + /> +

 

+ {options.service && options.queryName ? ( + + ) : null} +
+ ); +}; + +export default ElasticsearchPlugin; diff --git a/app/src/plugins/jaeger/JaegerPluginToolbar.tsx b/app/src/plugins/jaeger/JaegerPluginToolbar.tsx new file mode 100644 index 000000000..54fafb350 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerPluginToolbar.tsx @@ -0,0 +1,126 @@ +import React, { useState } from 'react'; +import { + Select, + SelectOption, + SelectOptionObject, + SelectVariant, + Toolbar, + ToolbarContent, + ToolbarGroup, + ToolbarItem, + ToolbarToggleGroup, +} from '@patternfly/react-core'; +import FilterIcon from '@patternfly/react-icons/dist/js/icons/filter-icon'; + +import Options, { IAdditionalFields } from 'components/Options'; +import { Query } from 'proto/jaeger_grpc_web_pb'; + +interface IJaegerPluginToolbarProps { + queryName: string; + queries: Query.AsObject[]; + limit: string; + maxDuration: string; + minDuration: string; + timeEnd: number; + timeStart: number; + setQuery: (name: string, service: string, operation: string, tags: string) => void; + setOptions: (limit: string, maxDuration: string, minDuration: string, timeEnd: number, timeStart: number) => void; +} + +const JaegerPluginToolbar: React.FunctionComponent = ({ + queryName, + queries, + limit, + maxDuration, + minDuration, + timeEnd, + timeStart, + setQuery, + setOptions, +}: IJaegerPluginToolbarProps) => { + const [show, setShow] = useState(false); + + // changeAddtionalOptions changes the Jaeger options. This function is passed to the shared Options component. + const changeAddtionalOptions = ( + additionalFields: IAdditionalFields[] | undefined, + timeEnd: number, + timeStart: number, + ): void => { + if (additionalFields && additionalFields.length === 3) { + setOptions(additionalFields[0].value, additionalFields[1].value, additionalFields[2].value, timeEnd, timeStart); + } + }; + + // onSelect is used to change the query, when a user selects a query from the select component. + const onSelect = ( + event: React.MouseEvent | React.ChangeEvent, + value: string | SelectOptionObject, + ): void => { + const query = queries.filter((q) => q.name === value); + if (query.length === 1) { + setQuery(query[0].name, query[0].service, query[0].operation, query[0].tags); + setShow(false); + } + }; + + return ( + + + } breakpoint="lg"> + + + + + + + + + + + + ); +}; + +export default JaegerPluginToolbar; diff --git a/app/src/plugins/jaeger/JaegerSpan.tsx b/app/src/plugins/jaeger/JaegerSpan.tsx new file mode 100644 index 000000000..bccb914c4 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerSpan.tsx @@ -0,0 +1,103 @@ +import { AccordionContent, AccordionItem, AccordionToggle, Badge } from '@patternfly/react-core'; +import React, { useState } from 'react'; + +import { IProcesses, ISpan } from 'plugins/jaeger/helpers'; +import JaegerSpanLogs from 'plugins/jaeger/JaegerSpanLogs'; + +import 'plugins/jaeger/jaeger.css'; + +export interface IJaegerSpanProps { + span: ISpan; + processes: IProcesses; + padding: number; +} + +const JaegerSpan: React.FunctionComponent = ({ span, processes, padding }: IJaegerSpanProps) => { + const [expanded, setExpanded] = useState(false); + + const time = ( + + + + ); + + return ( + + + setExpanded(!expanded)} + isExpanded={expanded} + > + + {processes[span.processID].serviceName}: {span.operationName} + + {span.spanID} + + {span.duration / 1000}ms + + {!expanded && span.fill !== undefined && span.offset !== undefined ? time : null} + + + +
+ {processes[span.processID].tags.length > 0 ? ( +
+ Process: + {processes[span.processID].tags.map((tag, index) => ( + + {tag.key}: {tag.value} + + ))} +
+ ) : null} + {span.tags.length > 0 ? ( +
+ Tags: + {span.tags.map((tag, index) => ( + + {tag.key}: {tag.value} + + ))} +
+ ) : null} + {span.logs.length > 0 ? ( +
+ Logs: + +
+ ) : null} +
+ + {expanded && span.fill !== undefined && span.offset !== undefined ? time : null} +
+
+ + {span.childs + ? span.childs.map((span, index) => ( + + )) + : null} +
+ ); +}; + +export default JaegerSpan; diff --git a/app/src/plugins/jaeger/JaegerSpanLogs.tsx b/app/src/plugins/jaeger/JaegerSpanLogs.tsx new file mode 100644 index 000000000..50eff2295 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerSpanLogs.tsx @@ -0,0 +1,63 @@ +import { Accordion, AccordionContent, AccordionItem, AccordionToggle } from '@patternfly/react-core'; +import React, { useState } from 'react'; +import { TableComposable, TableVariant, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; + +import { ILog, formatTraceTime } from 'plugins/jaeger/helpers'; + +export interface IJaegerSpanLogsProps { + logs: ILog[]; +} + +const JaegerSpanLogs: React.FunctionComponent = ({ logs }: IJaegerSpanLogsProps) => { + const [expanded, setExpanded] = useState([]); + + const toggle = (id: string): void => { + if (expanded.includes(id)) { + setExpanded(expanded.filter((item) => item !== id)); + } else { + setExpanded([...expanded, id]); + } + }; + + return ( + + {logs.map((log, index) => ( + + toggle(`logs-accordion-${index}`)} + isExpanded={expanded.includes(`logs-accordion-${index}`)} + id={`resources-toggle-${index}`} + > + {formatTraceTime(log.timestamp)} () + + + + + + Key + Value + + + + + {log.fields.map((field, rowIndex) => ( + + {field.key} + {field.value} + + ))} + + + + + ))} + + ); +}; + +export default JaegerSpanLogs; diff --git a/app/src/plugins/jaeger/JaegerSpans.tsx b/app/src/plugins/jaeger/JaegerSpans.tsx new file mode 100644 index 000000000..c4efdb156 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerSpans.tsx @@ -0,0 +1,41 @@ +import { Accordion, Card, CardBody } from '@patternfly/react-core'; +import React from 'react'; + +import { ISpan, ITrace, createSpansTree, getDuration } from 'plugins/jaeger/helpers'; +import JaegerSpan from 'plugins/jaeger/JaegerSpan'; +import JaegerSpansChart from 'plugins/jaeger/JaegerSpansChart'; + +import 'plugins/jaeger/jaeger.css'; + +export interface IJaegerSpansProps { + trace: ITrace; +} + +const JaegerSpans: React.FunctionComponent = ({ trace }: IJaegerSpansProps) => { + const duration = getDuration(trace.spans); + const spans: ISpan[] = createSpansTree(trace.spans, trace.spans[0].startTime, duration); + + return ( + + + +
+ {spans.map((span, index) => ( + + ))} +
+
+
+ +

 

+ + + {spans.map((span, index) => ( + + ))} + +
+ ); +}; + +export default JaegerSpans; diff --git a/app/src/plugins/jaeger/JaegerSpansChart.tsx b/app/src/plugins/jaeger/JaegerSpansChart.tsx new file mode 100644 index 000000000..ea671f808 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerSpansChart.tsx @@ -0,0 +1,46 @@ +import {} from '@patternfly/react-core'; +import React from 'react'; + +import { ISpan } from 'plugins/jaeger/helpers'; + +export interface IJaegerSpansChartProps { + span: ISpan; + height: number; +} + +const JaegerSpansChart: React.FunctionComponent = ({ + span, + height, +}: IJaegerSpansChartProps) => { + return ( + +
+ + + +
+ + {span.childs + ? span.childs.map((span, index) => ) + : null} +
+ ); +}; + +export default JaegerSpansChart; diff --git a/app/src/plugins/jaeger/JaegerTrace.tsx b/app/src/plugins/jaeger/JaegerTrace.tsx new file mode 100644 index 000000000..21bc8c53e --- /dev/null +++ b/app/src/plugins/jaeger/JaegerTrace.tsx @@ -0,0 +1,71 @@ +import { + Button, + ButtonVariant, + DrawerActions, + DrawerCloseButton, + DrawerHead, + DrawerPanelBody, + DrawerPanelContent, +} from '@patternfly/react-core'; +import ExternalLinkIcon from '@patternfly/react-icons/dist/js/icons/external-link-alt-icon'; +import React from 'react'; + +import { ITrace, formatTraceTime, getDuration } from 'plugins/jaeger/helpers'; +import JaegerSpans from 'plugins/jaeger/JaegerSpans'; +import Title from 'components/Title'; + +export interface IJaegerTraceProps { + name: string; + trace: ITrace; + close: () => void; +} + +const JaegerTrace: React.FunctionComponent = ({ name, trace, close }: IJaegerTraceProps) => { + const rootSpan = trace.spans[0]; + const rootSpanProcess = trace.processes[rootSpan.processID]; + const rootSpanService = rootSpanProcess.serviceName; + + const openTrace = (): void => { + window.open(`/plugins/${name}/trace/${trace.traceID}`, '_blank'); + }; + + return ( + + + + <DrawerActions style={{ padding: 0 }}> + <div className="pf-c-drawer__close"> + <Button variant={ButtonVariant.plain} onClick={openTrace}> + <ExternalLinkIcon /> + </Button> + </div> + <DrawerCloseButton onClose={close} /> + </DrawerActions> + </DrawerHead> + + <DrawerPanelBody> + <span> + <span className="pf-u-color-400">Trace Start: </span> + <b className="pf-u-pr-md">{formatTraceTime(rootSpan.startTime)}</b> + </span> + <span> + <span className="pf-u-color-400">Duration: </span> + <b className="pf-u-pr-md">{getDuration(trace.spans)}ms</b> + </span> + <span> + <span className="pf-u-color-400">Services: </span> + <b className="pf-u-pr-md">{Object.keys(trace.processes).length}</b> + </span> + <span> + <span className="pf-u-color-400">Total Spans: </span> + <b className="pf-u-pr-md">{trace.spans.length}</b> + </span> + <p> </p> + <JaegerSpans trace={trace} /> + <p> </p> + </DrawerPanelBody> + </DrawerPanelContent> + ); +}; + +export default JaegerTrace; diff --git a/app/src/plugins/jaeger/JaegerTraces.tsx b/app/src/plugins/jaeger/JaegerTraces.tsx new file mode 100644 index 000000000..c36b0e335 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerTraces.tsx @@ -0,0 +1,116 @@ +import { Alert, AlertActionLink, AlertVariant, Spinner } from '@patternfly/react-core'; +import React, { useCallback, useEffect, useState } from 'react'; + +import { GetTracesRequest, GetTracesResponse, JaegerPromiseClient } from 'proto/jaeger_grpc_web_pb'; +import { IJaegerOptions, ITrace } from 'plugins/jaeger/helpers'; +import JaegerTracesChart from 'plugins/jaeger/JaegerTracesChart'; +import JaegerTracesTrace from 'plugins/jaeger/JaegerTracesTrace'; +import { apiURL } from 'utils/constants'; + +// jaegerService is the gRPC service to get the traces from a Jaeger instance. +const jaegerService = new JaegerPromiseClient(apiURL, null, null); + +interface IDataState { + traces: ITrace[]; + error: string; + isLoading: boolean; +} + +interface IJaegerTracesProps extends IJaegerOptions { + name: string; + queryName: string; + isInDrawer: boolean; + setTrace: (trace: React.ReactNode) => void; +} + +const JaegerTraces: React.FunctionComponent<IJaegerTracesProps> = ({ + name, + queryName, + isInDrawer, + limit, + maxDuration, + minDuration, + operation, + service, + tags, + timeEnd, + timeStart, + setTrace, +}: IJaegerTracesProps) => { + const [data, setData] = useState<IDataState>({ + error: '', + isLoading: true, + traces: [], + }); + + const fetchTraces = useCallback(async (): Promise<void> => { + try { + setData({ error: '', isLoading: true, traces: [] }); + + const getTracesRequest = new GetTracesRequest(); + getTracesRequest.setName(name); + getTracesRequest.setLimit(limit); + getTracesRequest.setMaxduration(maxDuration); + getTracesRequest.setMinduration(minDuration); + getTracesRequest.setOperation(operation); + getTracesRequest.setService(service); + getTracesRequest.setTags(tags); + getTracesRequest.setTimeend(timeEnd); + getTracesRequest.setTimestart(timeStart); + + const getTracesResponse: GetTracesResponse = await jaegerService.getTraces(getTracesRequest, null); + const traces = JSON.parse(getTracesResponse.toObject().traces).data; + + setData({ error: '', isLoading: false, traces: traces }); + } catch (err) { + setData({ error: err.message, isLoading: false, traces: [] }); + } + }, [name, limit, maxDuration, minDuration, operation, service, tags, timeEnd, timeStart]); + + // useEffect is used to call the fetchTraces function every time the required props are changing. + useEffect(() => { + fetchTraces(); + }, [fetchTraces]); + + // When the isLoading property is true, we render a spinner as loading indicator for the user. + if (data.isLoading) { + return <Spinner style={{ left: '50%', position: 'fixed', top: '50%', transform: 'translate(-50%, -50%)' }} />; + } + + // In case of an error, we show an Alert component, with the error message, while the request failed. + if (data.error) { + return ( + <Alert + variant={AlertVariant.danger} + isInline={isInDrawer} + title="Could not get traces" + actionLinks={ + <React.Fragment> + <AlertActionLink onClick={fetchTraces}>Retry</AlertActionLink> + </React.Fragment> + } + > + <p>{data.error}</p> + </Alert> + ); + } + + return ( + <React.Fragment> + <JaegerTracesChart isInDrawer={isInDrawer} traces={data.traces} /> + + <p> </p> + <p> </p> + <p> </p> + + {data.traces.map((trace, index) => ( + <React.Fragment key={index}> + <JaegerTracesTrace name={name} isInDrawer={isInDrawer} trace={trace} setTrace={setTrace} /> + <p> </p> + </React.Fragment> + ))} + </React.Fragment> + ); +}; + +export default JaegerTraces; diff --git a/app/src/plugins/jaeger/JaegerTracesChart.tsx b/app/src/plugins/jaeger/JaegerTracesChart.tsx new file mode 100644 index 000000000..ed763ca99 --- /dev/null +++ b/app/src/plugins/jaeger/JaegerTracesChart.tsx @@ -0,0 +1,111 @@ +import { Card, CardBody } from '@patternfly/react-core'; +import { + Chart, + ChartAxis, + ChartLegendTooltip, + ChartScatter, + ChartThemeColor, + createContainer, +} from '@patternfly/react-charts'; +import React, { useEffect, useRef, useState } from 'react'; + +import { ITrace, getDuration } from 'plugins/jaeger/helpers'; +import { formatTime } from 'utils/helpers'; + +interface IChartData { + x: number; + y: number; + z: number; +} + +interface ILabels { + datum: IChartData; +} + +interface IJaegerTracesChartProps { + isInDrawer: boolean; + traces: ITrace[]; +} + +const JaegerTracesChart: React.FunctionComponent<IJaegerTracesChartProps> = ({ + isInDrawer, + traces, +}: IJaegerTracesChartProps) => { + const refChart = useRef<HTMLDivElement>(null); + const [width, setWidth] = useState<number>(0); + const [height, setHeight] = useState<number>(0); + + // useEffect is executed on every render of this component. This is needed, so that we are able to use a width of 100% + // and a static height for the chart. + useEffect(() => { + if (refChart && refChart.current) { + setWidth(refChart.current.getBoundingClientRect().width); + setHeight(refChart.current.getBoundingClientRect().height); + } + }, []); + + if (traces.length === 0) { + return null; + } + + const CursorVoronoiContainer = createContainer('voronoi', 'cursor'); + const legendData = traces.map((trace) => { + const rootSpan = trace.spans[0]; + const rootSpanProcess = trace.processes[rootSpan.processID]; + const rootSpanService = rootSpanProcess.serviceName; + return { childName: 'trace', name: `${rootSpanService}: ${rootSpan.operationName}` }; + }); + const data: IChartData[] = traces.map((trace) => { + return { + x: Math.floor(trace.spans[0].startTime / 1000), + y: getDuration(trace.spans), + z: trace.spans.length, + }; + }); + + return ( + <Card isFlat={true} isCompact={true}> + <CardBody> + <div style={{ height: '200px', width: '100%' }} ref={refChart}> + <Chart + containerComponent={ + <CursorVoronoiContainer + cursorDimension="x" + labels={({ datum }: ILabels): string => `${datum.y}ms`} + labelComponent={ + <ChartLegendTooltip + legendData={legendData} + title={(point: IChartData): string => formatTime(Math.floor(point.x / 1000))} + /> + } + mouseFollowTooltips={true} + voronoiDimension="x" + voronoiPadding={0} + /> + } + height={height} + legendData={legendData} + legendPosition={undefined} + padding={{ bottom: 30, left: 0, right: 0, top: 0 }} + scale={{ x: 'time', y: 'linear' }} + themeColor={ChartThemeColor.multiOrdered} + width={width} + > + <ChartAxis dependentAxis={false} showGrid={false} /> + <ChartScatter + style={{ data: { fill: 'var(--pf-global--primary-color--100)' } }} + name="trace" + data={data} + bubbleProperty="z" + maxBubbleSize={25} + minBubbleSize={5} + size={1} + /> + </Chart> + </div> + </CardBody> + </Card> + ); +}; + +export default JaegerTracesChart; diff --git a/app/src/plugins/jaeger/JaegerTracesTrace.tsx b/app/src/plugins/jaeger/JaegerTracesTrace.tsx new file mode 100644 index 000000000..2bed1359f --- /dev/null +++ b/app/src/plugins/jaeger/JaegerTracesTrace.tsx @@ -0,0 +1,65 @@ +import { Badge, Card, CardActions, CardBody, CardHeader, CardTitle } from '@patternfly/react-core'; +import React from 'react'; + +import { ITrace, formatTraceTime, getDuration, getSpansPerServices } from 'plugins/jaeger/helpers'; +import JaegerTrace from 'plugins/jaeger/JaegerTrace'; + +interface IJaegerTracesTraceProps { + name: string; + isInDrawer: boolean; + trace: ITrace; + setTrace: (trace: React.ReactNode) => void; +} + +const JaegerTracesTrace: React.FunctionComponent<IJaegerTracesTraceProps> = ({ + name, + isInDrawer, + trace, + setTrace, +}: IJaegerTracesTraceProps) => { + const rootSpan = trace.spans[0]; + const rootSpanProcess = trace.processes[rootSpan.processID]; + const rootSpanService = rootSpanProcess.serviceName; + + const openTrace = (): void => { + window.open(`/plugins/${name}/trace/${trace.traceID}`, '_blank'); + }; + + return ( + <Card + isFlat={true} + isCompact={true} + isHoverable={true} + onClick={ + isInDrawer + ? (): void => openTrace() + : (): void => setTrace(<JaegerTrace name={name} trace={trace} close={(): void => setTrace(undefined)} />) + } + > + <CardHeader> + <CardTitle> + {rootSpanService}: {rootSpan.operationName}{' '} + <span className="pf-u-pl-sm pf-u-font-size-sm pf-u-color-400">{trace.traceID}</span> + </CardTitle> + <CardActions> + <span className="pf-u-pl-sm pf-u-font-size-sm pf-u-color-400">{getDuration(trace.spans)}ms</span> + </CardActions> + </CardHeader> + <CardBody> + <Badge className="pf-u-mr-xl" isRead={true}> + {trace.spans.length} Spans + </Badge> + + {getSpansPerServices(trace).map((service, index) => ( + <Badge className="pf-u-ml-sm" key={index} isRead={false}> + {service.service} ({service.spans}) + </Badge> + ))} + + <span style={{ float: 'right' }}>{formatTraceTime(rootSpan.startTime)}</span> + </CardBody> + </Card> + ); +}; + +export default JaegerTracesTrace; diff --git a/app/src/plugins/jaeger/helpers.ts b/app/src/plugins/jaeger/helpers.ts new file mode 100644 index 000000000..ba803cdd5 --- /dev/null +++ b/app/src/plugins/jaeger/helpers.ts @@ -0,0 +1,167 @@ +import { formatTime } from 'utils/helpers'; + +export interface IKeyValue { + key: string; + type: string; + value: string | boolean | number; +} + +export interface ILog { + timestamp: number; + fields: IKeyValue[]; +} + +export interface IProcess { + serviceName: string; + tags: IKeyValue[]; +} + +export interface IProcesses { + [key: string]: IProcess; +} + +export interface IReference { + refType: string; + spanID: string; + traceID: string; +} + +// ISpan is the interface for a single span, with all available fields. The "offset", "fill" and "childs" fields are not +// present on a span returned by the Jaeger Query API, instead we populate this fields within the React UI, to render +// the spans tree. +export interface ISpan { + traceID: string; + spanID: string; + flags: number; + operationName: string; + references: IReference[]; + startTime: number; + duration: number; + tags: IKeyValue[]; + logs: ILog[]; + processID: string; + offset?: number; + fill?: number; + childs?: ISpan[]; +} + +// ITrace is the interface for a single trace. We have to define the interface by ourselve, because the protobuf service +// just returns a single string with all traces, becaus we had some problems with the protobuf message formate for the +// value field in the IKeyValue interface. +export interface ITrace { + traceID: string; + spans: ISpan[]; + processes: IProcesses; +} + +// ITimes is the interface for a start and end time. +export interface ITimes { + timeEnd: number; + timeStart: number; +} + +// IJaegerOptions is the interface for all options, which can be set for a Jaeger query. +export interface IJaegerOptions extends ITimes { + limit: string; + maxDuration: string; + minDuration: string; + queryName: string; + operation: string; + service: string; + tags: string; +} + +// IServiceSpans is the interface to get the number of spans per service. +export interface IServiceSpans { + service: string; + spans: number; +} + +// getOptionsFromSearch is used to get the Jaeger options from a given search location. +export const getOptionsFromSearch = (search: string): IJaegerOptions => { + const params = new URLSearchParams(search); + const limit = params.get('limit'); + const maxDuration = params.get('maxDuration'); + const minDuration = params.get('minDuration'); + const operation = params.get('operation'); + const service = params.get('service'); + const tags = params.get('tags'); + const timeEnd = params.get('timeEnd'); + const timeStart = params.get('timeStart'); + + return { + limit: limit ? limit : '20', + maxDuration: maxDuration ? maxDuration : '', + minDuration: minDuration ? minDuration : '', + operation: operation ? operation : '', + queryName: '', + service: service ? service : '', + tags: tags ? tags : '', + timeEnd: timeEnd ? parseInt(timeEnd as string) : Math.floor(Date.now() / 1000), + timeStart: timeStart ? parseInt(timeStart as string) : Math.floor(Date.now() / 1000) - 3600, + }; +}; + +// getSpansPerServices returns the number of spans per service. +export const getSpansPerServices = (trace: ITrace): IServiceSpans[] => { + const services: IServiceSpans[] = Object.keys(trace.processes).map((process) => { + return { + service: trace.processes[process].serviceName, + spans: trace.spans.filter((span) => span.processID === process).length, + }; + }); + return services; +}; + +// getDuration returns the duration for a trace in milliseconds. +export const getDuration = (spans: ISpan[]): number => { + const startTimes: number[] = []; + const endTimes: number[] = []; + + for (const span of spans) { + startTimes.push(span.startTime); + endTimes.push(span.startTime + span.duration); + } + + return (Math.max(...endTimes) - Math.min(...startTimes)) / 1000; +}; + +export const formatTraceTime = (time: number): string => { + return formatTime(Math.floor(time / 1000000)); +}; + +// IMap is the interface for the map of spans in the createSpansTree function. +interface IMap { + [key: string]: number; +} + +// createSpansTree creates a tree of spans. This simplifies the frontend code in contrast to working with the flat array +// of spans. +export const createSpansTree = (spans: ISpan[], traceStartTime: number, duration: number): ISpan[] => { + const map: IMap = {}; + const roots: ISpan[] = []; + + for (let i = 0; i < spans.length; i++) { + map[spans[i].spanID] = i; + spans[i].childs = []; + + spans[i].offset = ((spans[i].startTime - traceStartTime) / 1000 / duration) * 100; + spans[i].fill = (spans[i].duration / 1000 / duration) * 100; + } + + for (let i = 0; i < spans.length; i++) { + const span = spans[i]; + + if (span.references && span.references.length > 0) { + const ref = span.references.filter((reference) => reference.refType === 'CHILD_OF'); + + if (ref.length > 0 && map.hasOwnProperty(ref[0].spanID)) { + spans[map[ref[0].spanID]].childs?.push(span); + } + } else { + roots.push(span); + } + } + + return roots; +}; diff --git a/app/src/plugins/jaeger/jaeger.css b/app/src/plugins/jaeger/jaeger.css new file mode 100644 index 000000000..6ccb897ec --- /dev/null +++ b/app/src/plugins/jaeger/jaeger.css @@ -0,0 +1,7 @@ +/* kobsio-jaeger-accordion-toggle + * We have to modify the width of the accordion toggle component, which is used for the span view, because we want to + * render the duration of a span on the right side of the toggle. */ +.kobsio-jaeger-accordion-toggle .pf-c-accordion__toggle-text { + width: 100%; + text-align: left; +} diff --git a/app/src/plugins/prometheus/PrometheusPlugin.tsx b/app/src/plugins/prometheus/PrometheusPlugin.tsx index fb23e4f7c..3a97bb3cd 100644 --- a/app/src/plugins/prometheus/PrometheusPlugin.tsx +++ b/app/src/plugins/prometheus/PrometheusPlugin.tsx @@ -1,6 +1,5 @@ import { Alert, AlertActionLink, AlertVariant } from '@patternfly/react-core'; import React, { useCallback, useEffect, useState } from 'react'; -import ChartAreaIcon from '@patternfly/react-icons/dist/js/icons/chart-area-icon'; import { GetVariablesRequest, @@ -87,7 +86,7 @@ const PrometheusPlugin: React.FunctionComponent<IPluginProps> = ({ title="Prometheus properties are missing" description="The Prometheus properties are missing in your CR for this application. Visit the documentation to learn more on how to use the Prometheus plugin in an Application CR." documentation="https://kobs.io" - icon={ChartAreaIcon} + type="prometheus" /> ); } diff --git a/app/src/proto/jaeger_grpc_web_pb.js b/app/src/proto/jaeger_grpc_web_pb.js new file mode 100644 index 000000000..339dcdfc9 --- /dev/null +++ b/app/src/proto/jaeger_grpc_web_pb.js @@ -0,0 +1,315 @@ +/** + * @fileoverview gRPC-Web generated client stub for plugins.jaeger + * @enhanceable + * @public + */ + +// GENERATED CODE -- DO NOT EDIT! + + +/* eslint-disable */ +// @ts-nocheck + + + +const grpc = {}; +grpc.web = require('grpc-web'); + +const proto = {}; +proto.plugins = {}; +proto.plugins.jaeger = require('./jaeger_pb.js'); + +/** + * @param {string} hostname + * @param {?Object} credentials + * @param {?Object} options + * @constructor + * @struct + * @final + */ +proto.plugins.jaeger.JaegerClient = + function(hostname, credentials, options) { + if (!options) options = {}; + options['format'] = 'text'; + + /** + * @private @const {!grpc.web.GrpcWebClientBase} The client + */ + this.client_ = new grpc.web.GrpcWebClientBase(options); + + /** + * @private @const {string} The hostname + */ + this.hostname_ = hostname; + +}; + + +/** + * @param {string} hostname + * @param {?Object} credentials + * @param {?Object} options + * @constructor + * @struct + * @final + */ +proto.plugins.jaeger.JaegerPromiseClient = + function(hostname, credentials, options) { + if (!options) options = {}; + options['format'] = 'text'; + + /** + * @private @const {!grpc.web.GrpcWebClientBase} The client + */ + this.client_ = new grpc.web.GrpcWebClientBase(options); + + /** + * @private @const {string} The hostname + */ + this.hostname_ = hostname; + +}; + + +/** + * @const + * @type {!grpc.web.MethodDescriptor< + * !proto.plugins.jaeger.GetOperationsRequest, + * !proto.plugins.jaeger.GetOperationsResponse>} + */ +const methodDescriptor_Jaeger_GetOperations = new grpc.web.MethodDescriptor( + '/plugins.jaeger.Jaeger/GetOperations', + grpc.web.MethodType.UNARY, + proto.plugins.jaeger.GetOperationsRequest, + proto.plugins.jaeger.GetOperationsResponse, + /** + * @param {!proto.plugins.jaeger.GetOperationsRequest} request + * @return {!Uint8Array} + */ + function(request) { + return request.serializeBinary(); + }, + proto.plugins.jaeger.GetOperationsResponse.deserializeBinary +); + + +/** + * @const + * @type {!grpc.web.AbstractClientBase.MethodInfo< + * !proto.plugins.jaeger.GetOperationsRequest, + * !proto.plugins.jaeger.GetOperationsResponse>} + */ +const methodInfo_Jaeger_GetOperations = new grpc.web.AbstractClientBase.MethodInfo( + proto.plugins.jaeger.GetOperationsResponse, + /** + * @param {!proto.plugins.jaeger.GetOperationsRequest} request + * @return {!Uint8Array} + */ + function(request) { + return request.serializeBinary(); + }, + proto.plugins.jaeger.GetOperationsResponse.deserializeBinary +); + + +/** + * @param {!proto.plugins.jaeger.GetOperationsRequest} request The + * request proto + * @param {?Object<string, string>} metadata User defined + * call metadata + * @param {function(?grpc.web.Error, ?proto.plugins.jaeger.GetOperationsResponse)} + * callback The callback function(error, response) + * @return {!grpc.web.ClientReadableStream<!proto.plugins.jaeger.GetOperationsResponse>|undefined} + * The XHR Node Readable Stream + */ +proto.plugins.jaeger.JaegerClient.prototype.getOperations = + function(request, metadata, callback) { + return this.client_.rpcCall(this.hostname_ + + '/plugins.jaeger.Jaeger/GetOperations', + request, + metadata || {}, + methodDescriptor_Jaeger_GetOperations, + callback); +}; + + +/** + * @param {!proto.plugins.jaeger.GetOperationsRequest} request The + * request proto + * @param {?Object<string, string>} metadata User defined + * call metadata + * @return {!Promise<!proto.plugins.jaeger.GetOperationsResponse>} + * Promise that resolves to the response + */ +proto.plugins.jaeger.JaegerPromiseClient.prototype.getOperations = + function(request, metadata) { + return this.client_.unaryCall(this.hostname_ + + '/plugins.jaeger.Jaeger/GetOperations', + request, + metadata || {}, + methodDescriptor_Jaeger_GetOperations); +}; + + +/** + * @const + * @type {!grpc.web.MethodDescriptor< + * !proto.plugins.jaeger.GetTracesRequest, + * !proto.plugins.jaeger.GetTracesResponse>} + */ +const methodDescriptor_Jaeger_GetTraces = new grpc.web.MethodDescriptor( + '/plugins.jaeger.Jaeger/GetTraces', + grpc.web.MethodType.UNARY, + proto.plugins.jaeger.GetTracesRequest, + proto.plugins.jaeger.GetTracesResponse, + /** + * @param {!proto.plugins.jaeger.GetTracesRequest} request + * @return {!Uint8Array} + */ + function(request) { + return request.serializeBinary(); + }, + proto.plugins.jaeger.GetTracesResponse.deserializeBinary +); + + +/** + * @const + * @type {!grpc.web.AbstractClientBase.MethodInfo< + * !proto.plugins.jaeger.GetTracesRequest, + * !proto.plugins.jaeger.GetTracesResponse>} + */ +const methodInfo_Jaeger_GetTraces = new grpc.web.AbstractClientBase.MethodInfo( + proto.plugins.jaeger.GetTracesResponse, + /** + * @param {!proto.plugins.jaeger.GetTracesRequest} request + * @return {!Uint8Array} + */ + function(request) { + return request.serializeBinary(); + }, + proto.plugins.jaeger.GetTracesResponse.deserializeBinary +); + + +/** + * @param {!proto.plugins.jaeger.GetTracesRequest} request The + * request proto + * @param {?Object<string, string>} metadata User defined + * call metadata + * @param {function(?grpc.web.Error, ?proto.plugins.jaeger.GetTracesResponse)} + * callback The callback function(error, response) + * @return {!grpc.web.ClientReadableStream<!proto.plugins.jaeger.GetTracesResponse>|undefined} + * The XHR Node Readable Stream + */ +proto.plugins.jaeger.JaegerClient.prototype.getTraces = + function(request, metadata, callback) { + return this.client_.rpcCall(this.hostname_ + + '/plugins.jaeger.Jaeger/GetTraces', + request, + metadata || {}, + methodDescriptor_Jaeger_GetTraces, + callback); +}; + + +/** + * @param {!proto.plugins.jaeger.GetTracesRequest} request The + * request proto + * @param {?Object<string, string>} metadata User defined + * call metadata + * @return {!Promise<!proto.plugins.jaeger.GetTracesResponse>} + * Promise that resolves to the response + */ +proto.plugins.jaeger.JaegerPromiseClient.prototype.getTraces = + function(request, metadata) { + return this.client_.unaryCall(this.hostname_ + + '/plugins.jaeger.Jaeger/GetTraces', + request, + metadata || {}, + methodDescriptor_Jaeger_GetTraces); +}; + + +/** + * @const + * @type {!grpc.web.MethodDescriptor< + * !proto.plugins.jaeger.GetTraceRequest, + * !proto.plugins.jaeger.GetTraceResponse>} + */ +const methodDescriptor_Jaeger_GetTrace = new grpc.web.MethodDescriptor( + '/plugins.jaeger.Jaeger/GetTrace', + grpc.web.MethodType.UNARY, + proto.plugins.jaeger.GetTraceRequest, + proto.plugins.jaeger.GetTraceResponse, + /** + * @param {!proto.plugins.jaeger.GetTraceRequest} request + * @return {!Uint8Array} + */ + function(request) { + return request.serializeBinary(); + }, + proto.plugins.jaeger.GetTraceResponse.deserializeBinary +); + + +/** + * @const + * @type {!grpc.web.AbstractClientBase.MethodInfo< + * !proto.plugins.jaeger.GetTraceRequest, + * !proto.plugins.jaeger.GetTraceResponse>} + */ +const methodInfo_Jaeger_GetTrace = new grpc.web.AbstractClientBase.MethodInfo( + proto.plugins.jaeger.GetTraceResponse, + /** + * @param {!proto.plugins.jaeger.GetTraceRequest} request + * @return {!Uint8Array} + */ + function(request) { + return request.serializeBinary(); + }, + proto.plugins.jaeger.GetTraceResponse.deserializeBinary +); + + +/** + * @param {!proto.plugins.jaeger.GetTraceRequest} request The + * request proto + * @param {?Object<string, string>} metadata User defined + * call metadata + * @param {function(?grpc.web.Error, ?proto.plugins.jaeger.GetTraceResponse)} + * callback The callback function(error, response) + * @return {!grpc.web.ClientReadableStream<!proto.plugins.jaeger.GetTraceResponse>|undefined} + * The XHR Node Readable Stream + */ +proto.plugins.jaeger.JaegerClient.prototype.getTrace = + function(request, metadata, callback) { + return this.client_.rpcCall(this.hostname_ + + '/plugins.jaeger.Jaeger/GetTrace', + request, + metadata || {}, + methodDescriptor_Jaeger_GetTrace, + callback); +}; + + +/** + * @param {!proto.plugins.jaeger.GetTraceRequest} request The + * request proto + * @param {?Object<string, string>} metadata User defined + * call metadata + * @return {!Promise<!proto.plugins.jaeger.GetTraceResponse>} + * Promise that resolves to the response + */ +proto.plugins.jaeger.JaegerPromiseClient.prototype.getTrace = + function(request, metadata) { + return this.client_.unaryCall(this.hostname_ + + '/plugins.jaeger.Jaeger/GetTrace', + request, + metadata || {}, + methodDescriptor_Jaeger_GetTrace); +}; + + +module.exports = proto.plugins.jaeger; + diff --git a/app/src/proto/jaeger_pb.d.ts b/app/src/proto/jaeger_pb.d.ts new file mode 100644 index 000000000..38184290a --- /dev/null +++ b/app/src/proto/jaeger_pb.d.ts @@ -0,0 +1,251 @@ +// package: plugins.jaeger +// file: jaeger.proto + +import * as jspb from "google-protobuf"; + +export class GetOperationsRequest extends jspb.Message { + getName(): string; + setName(value: string): void; + + getService(): string; + setService(value: string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetOperationsRequest.AsObject; + static toObject(includeInstance: boolean, msg: GetOperationsRequest): GetOperationsRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>}; + static serializeBinaryToWriter(message: GetOperationsRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetOperationsRequest; + static deserializeBinaryFromReader(message: GetOperationsRequest, reader: jspb.BinaryReader): GetOperationsRequest; +} + +export namespace GetOperationsRequest { + export type AsObject = { + name: string, + service: string, + } +} + +export class GetOperationsResponse extends jspb.Message { + clearServicesList(): void; + getServicesList(): Array<string>; + setServicesList(value: Array<string>): void; + addServices(value: string, index?: number): string; + + clearOperationsList(): void; + getOperationsList(): Array<Operation>; + setOperationsList(value: Array<Operation>): void; + addOperations(value?: Operation, index?: number): Operation; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetOperationsResponse.AsObject; + static toObject(includeInstance: boolean, msg: GetOperationsResponse): GetOperationsResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>}; + static serializeBinaryToWriter(message: GetOperationsResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetOperationsResponse; + static deserializeBinaryFromReader(message: GetOperationsResponse, reader: jspb.BinaryReader): GetOperationsResponse; +} + +export namespace GetOperationsResponse { + export type AsObject = { + servicesList: Array<string>, + operationsList: Array<Operation.AsObject>, + } +} + +export class GetTracesRequest extends jspb.Message { + getName(): string; + setName(value: string): void; + + getLimit(): string; + setLimit(value: string): void; + + getMaxduration(): string; + setMaxduration(value: string): void; + + getMinduration(): string; + setMinduration(value: string): void; + + getService(): string; + setService(value: string): void; + + getOperation(): string; + setOperation(value: string): void; + + getTags(): string; + setTags(value: string): void; + + getTimestart(): number; + setTimestart(value: number): void; + + getTimeend(): number; + setTimeend(value: number): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetTracesRequest.AsObject; + static toObject(includeInstance: boolean, msg: GetTracesRequest): GetTracesRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>}; + static serializeBinaryToWriter(message: GetTracesRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetTracesRequest; + static deserializeBinaryFromReader(message: GetTracesRequest, reader: jspb.BinaryReader): GetTracesRequest; +} + +export namespace GetTracesRequest { + export type AsObject = { + name: string, + limit: string, + maxduration: string, + minduration: string, + service: string, + operation: string, + tags: string, + timestart: number, + timeend: number, + } +} + +export class GetTracesResponse extends jspb.Message { + getTraces(): string; + setTraces(value: string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetTracesResponse.AsObject; + static toObject(includeInstance: boolean, msg: GetTracesResponse): GetTracesResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>}; + static serializeBinaryToWriter(message: GetTracesResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetTracesResponse; + static deserializeBinaryFromReader(message: GetTracesResponse, reader: jspb.BinaryReader): GetTracesResponse; +} + +export namespace GetTracesResponse { + export type AsObject = { + traces: string, + } +} + +export class GetTraceRequest extends jspb.Message { + getName(): string; + setName(value: string): void; + + getTraceid(): string; + setTraceid(value: string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetTraceRequest.AsObject; + static toObject(includeInstance: boolean, msg: GetTraceRequest): GetTraceRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>}; + static serializeBinaryToWriter(message: GetTraceRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetTraceRequest; + static deserializeBinaryFromReader(message: GetTraceRequest, reader: jspb.BinaryReader): GetTraceRequest; +} + +export namespace GetTraceRequest { + export type AsObject = { + name: string, + traceid: string, + } +} + +export class GetTraceResponse extends jspb.Message { + getTraces(): string; + setTraces(value: string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): GetTraceResponse.AsObject; + static toObject(includeInstance: boolean, msg: GetTraceResponse): GetTraceResponse.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>}; + static serializeBinaryToWriter(message: GetTraceResponse, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): GetTraceResponse; + static deserializeBinaryFromReader(message: GetTraceResponse, reader: jspb.BinaryReader): GetTraceResponse; +} + +export namespace GetTraceResponse { + export type AsObject = { + traces: string, + } +} + +export class Operation extends jspb.Message { + getName(): string; + setName(value: string): void; + + getSpankind(): string; + setSpankind(value: string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): Operation.AsObject; + static toObject(includeInstance: boolean, msg: Operation): Operation.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>}; + static serializeBinaryToWriter(message: Operation, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): Operation; + static deserializeBinaryFromReader(message: Operation, reader: jspb.BinaryReader): Operation; +} + +export namespace Operation { + export type AsObject = { + name: string, + spankind: string, + } +} + +export class Spec extends jspb.Message { + clearQueriesList(): void; + getQueriesList(): Array<Query>; + setQueriesList(value: Array<Query>): void; + addQueries(value?: Query, index?: number): Query; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): Spec.AsObject; + static toObject(includeInstance: boolean, msg: Spec): Spec.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>}; + static serializeBinaryToWriter(message: Spec, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): Spec; + static deserializeBinaryFromReader(message: Spec, reader: jspb.BinaryReader): Spec; +} + +export namespace Spec { + export type AsObject = { + queriesList: Array<Query.AsObject>, + } +} + +export class Query extends jspb.Message { + getName(): string; + setName(value: string): void; + + getService(): string; + setService(value: string): void; + + getOperation(): string; + setOperation(value: string): void; + + getTags(): string; + setTags(value: string): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): Query.AsObject; + static toObject(includeInstance: boolean, msg: Query): Query.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>}; + static serializeBinaryToWriter(message: Query, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): Query; + static deserializeBinaryFromReader(message: Query, reader: jspb.BinaryReader): Query; +} + +export namespace Query { + export type AsObject = { + name: string, + service: string, + operation: string, + tags: string, + } +} + diff --git a/app/src/proto/jaeger_pb.js b/app/src/proto/jaeger_pb.js new file mode 100644 index 000000000..fb400dee6 --- /dev/null +++ b/app/src/proto/jaeger_pb.js @@ -0,0 +1,1914 @@ +// source: jaeger.proto +/** + * @fileoverview + * @enhanceable + * @suppress {messageConventions} JS Compiler reports an error if a variable or + * field starts with 'MSG_' and isn't a translatable message. + * @public + */ +// GENERATED CODE -- DO NOT EDIT! +/* eslint-disable */ +// @ts-nocheck + +var jspb = require('google-protobuf'); +var goog = jspb; +var global = Function('return this')(); + +goog.exportSymbol('proto.plugins.jaeger.GetOperationsRequest', null, global); +goog.exportSymbol('proto.plugins.jaeger.GetOperationsResponse', null, global); +goog.exportSymbol('proto.plugins.jaeger.GetTraceRequest', null, global); +goog.exportSymbol('proto.plugins.jaeger.GetTraceResponse', null, global); +goog.exportSymbol('proto.plugins.jaeger.GetTracesRequest', null, global); +goog.exportSymbol('proto.plugins.jaeger.GetTracesResponse', null, global); +goog.exportSymbol('proto.plugins.jaeger.Operation', null, global); +goog.exportSymbol('proto.plugins.jaeger.Query', null, global); +goog.exportSymbol('proto.plugins.jaeger.Spec', null, global); +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.plugins.jaeger.GetOperationsRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.plugins.jaeger.GetOperationsRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.plugins.jaeger.GetOperationsRequest.displayName = 'proto.plugins.jaeger.GetOperationsRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.plugins.jaeger.GetOperationsResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.plugins.jaeger.GetOperationsResponse.repeatedFields_, null); +}; +goog.inherits(proto.plugins.jaeger.GetOperationsResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.plugins.jaeger.GetOperationsResponse.displayName = 'proto.plugins.jaeger.GetOperationsResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.plugins.jaeger.GetTracesRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.plugins.jaeger.GetTracesRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.plugins.jaeger.GetTracesRequest.displayName = 'proto.plugins.jaeger.GetTracesRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.plugins.jaeger.GetTracesResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.plugins.jaeger.GetTracesResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.plugins.jaeger.GetTracesResponse.displayName = 'proto.plugins.jaeger.GetTracesResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.plugins.jaeger.GetTraceRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.plugins.jaeger.GetTraceRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.plugins.jaeger.GetTraceRequest.displayName = 'proto.plugins.jaeger.GetTraceRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.plugins.jaeger.GetTraceResponse = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.plugins.jaeger.GetTraceResponse, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.plugins.jaeger.GetTraceResponse.displayName = 'proto.plugins.jaeger.GetTraceResponse'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.plugins.jaeger.Operation = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.plugins.jaeger.Operation, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.plugins.jaeger.Operation.displayName = 'proto.plugins.jaeger.Operation'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.plugins.jaeger.Spec = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, proto.plugins.jaeger.Spec.repeatedFields_, null); +}; +goog.inherits(proto.plugins.jaeger.Spec, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.plugins.jaeger.Spec.displayName = 'proto.plugins.jaeger.Spec'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.plugins.jaeger.Query = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.plugins.jaeger.Query, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.plugins.jaeger.Query.displayName = 'proto.plugins.jaeger.Query'; +} + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.plugins.jaeger.GetOperationsRequest.prototype.toObject = function(opt_includeInstance) { + return proto.plugins.jaeger.GetOperationsRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.plugins.jaeger.GetOperationsRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.GetOperationsRequest.toObject = function(includeInstance, msg) { + var f, obj = { + name: jspb.Message.getFieldWithDefault(msg, 1, ""), + service: jspb.Message.getFieldWithDefault(msg, 2, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.plugins.jaeger.GetOperationsRequest} + */ +proto.plugins.jaeger.GetOperationsRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.plugins.jaeger.GetOperationsRequest; + return proto.plugins.jaeger.GetOperationsRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.plugins.jaeger.GetOperationsRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.plugins.jaeger.GetOperationsRequest} + */ +proto.plugins.jaeger.GetOperationsRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setService(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.plugins.jaeger.GetOperationsRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.plugins.jaeger.GetOperationsRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.plugins.jaeger.GetOperationsRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.GetOperationsRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getName(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getService(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } +}; + + +/** + * optional string name = 1; + * @return {string} + */ +proto.plugins.jaeger.GetOperationsRequest.prototype.getName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetOperationsRequest} returns this + */ +proto.plugins.jaeger.GetOperationsRequest.prototype.setName = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string service = 2; + * @return {string} + */ +proto.plugins.jaeger.GetOperationsRequest.prototype.getService = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetOperationsRequest} returns this + */ +proto.plugins.jaeger.GetOperationsRequest.prototype.setService = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array<number>} + * @const + */ +proto.plugins.jaeger.GetOperationsResponse.repeatedFields_ = [1,2]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.plugins.jaeger.GetOperationsResponse.prototype.toObject = function(opt_includeInstance) { + return proto.plugins.jaeger.GetOperationsResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.plugins.jaeger.GetOperationsResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.GetOperationsResponse.toObject = function(includeInstance, msg) { + var f, obj = { + servicesList: (f = jspb.Message.getRepeatedField(msg, 1)) == null ? undefined : f, + operationsList: jspb.Message.toObjectList(msg.getOperationsList(), + proto.plugins.jaeger.Operation.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.plugins.jaeger.GetOperationsResponse} + */ +proto.plugins.jaeger.GetOperationsResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.plugins.jaeger.GetOperationsResponse; + return proto.plugins.jaeger.GetOperationsResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.plugins.jaeger.GetOperationsResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.plugins.jaeger.GetOperationsResponse} + */ +proto.plugins.jaeger.GetOperationsResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.addServices(value); + break; + case 2: + var value = new proto.plugins.jaeger.Operation; + reader.readMessage(value,proto.plugins.jaeger.Operation.deserializeBinaryFromReader); + msg.addOperations(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.plugins.jaeger.GetOperationsResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.plugins.jaeger.GetOperationsResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.plugins.jaeger.GetOperationsResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.GetOperationsResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getServicesList(); + if (f.length > 0) { + writer.writeRepeatedString( + 1, + f + ); + } + f = message.getOperationsList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 2, + f, + proto.plugins.jaeger.Operation.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated string services = 1; + * @return {!Array<string>} + */ +proto.plugins.jaeger.GetOperationsResponse.prototype.getServicesList = function() { + return /** @type {!Array<string>} */ (jspb.Message.getRepeatedField(this, 1)); +}; + + +/** + * @param {!Array<string>} value + * @return {!proto.plugins.jaeger.GetOperationsResponse} returns this + */ +proto.plugins.jaeger.GetOperationsResponse.prototype.setServicesList = function(value) { + return jspb.Message.setField(this, 1, value || []); +}; + + +/** + * @param {string} value + * @param {number=} opt_index + * @return {!proto.plugins.jaeger.GetOperationsResponse} returns this + */ +proto.plugins.jaeger.GetOperationsResponse.prototype.addServices = function(value, opt_index) { + return jspb.Message.addToRepeatedField(this, 1, value, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.plugins.jaeger.GetOperationsResponse} returns this + */ +proto.plugins.jaeger.GetOperationsResponse.prototype.clearServicesList = function() { + return this.setServicesList([]); +}; + + +/** + * repeated Operation operations = 2; + * @return {!Array<!proto.plugins.jaeger.Operation>} + */ +proto.plugins.jaeger.GetOperationsResponse.prototype.getOperationsList = function() { + return /** @type{!Array<!proto.plugins.jaeger.Operation>} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.plugins.jaeger.Operation, 2)); +}; + + +/** + * @param {!Array<!proto.plugins.jaeger.Operation>} value + * @return {!proto.plugins.jaeger.GetOperationsResponse} returns this +*/ +proto.plugins.jaeger.GetOperationsResponse.prototype.setOperationsList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 2, value); +}; + + +/** + * @param {!proto.plugins.jaeger.Operation=} opt_value + * @param {number=} opt_index + * @return {!proto.plugins.jaeger.Operation} + */ +proto.plugins.jaeger.GetOperationsResponse.prototype.addOperations = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 2, opt_value, proto.plugins.jaeger.Operation, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.plugins.jaeger.GetOperationsResponse} returns this + */ +proto.plugins.jaeger.GetOperationsResponse.prototype.clearOperationsList = function() { + return this.setOperationsList([]); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.plugins.jaeger.GetTracesRequest.prototype.toObject = function(opt_includeInstance) { + return proto.plugins.jaeger.GetTracesRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.plugins.jaeger.GetTracesRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.GetTracesRequest.toObject = function(includeInstance, msg) { + var f, obj = { + name: jspb.Message.getFieldWithDefault(msg, 1, ""), + limit: jspb.Message.getFieldWithDefault(msg, 2, ""), + maxduration: jspb.Message.getFieldWithDefault(msg, 3, ""), + minduration: jspb.Message.getFieldWithDefault(msg, 4, ""), + service: jspb.Message.getFieldWithDefault(msg, 5, ""), + operation: jspb.Message.getFieldWithDefault(msg, 6, ""), + tags: jspb.Message.getFieldWithDefault(msg, 7, ""), + timestart: jspb.Message.getFieldWithDefault(msg, 8, 0), + timeend: jspb.Message.getFieldWithDefault(msg, 9, 0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.plugins.jaeger.GetTracesRequest} + */ +proto.plugins.jaeger.GetTracesRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.plugins.jaeger.GetTracesRequest; + return proto.plugins.jaeger.GetTracesRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.plugins.jaeger.GetTracesRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.plugins.jaeger.GetTracesRequest} + */ +proto.plugins.jaeger.GetTracesRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setLimit(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setMaxduration(value); + break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.setMinduration(value); + break; + case 5: + var value = /** @type {string} */ (reader.readString()); + msg.setService(value); + break; + case 6: + var value = /** @type {string} */ (reader.readString()); + msg.setOperation(value); + break; + case 7: + var value = /** @type {string} */ (reader.readString()); + msg.setTags(value); + break; + case 8: + var value = /** @type {number} */ (reader.readInt64()); + msg.setTimestart(value); + break; + case 9: + var value = /** @type {number} */ (reader.readInt64()); + msg.setTimeend(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.plugins.jaeger.GetTracesRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.plugins.jaeger.GetTracesRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.plugins.jaeger.GetTracesRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.GetTracesRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getName(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getLimit(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getMaxduration(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getMinduration(); + if (f.length > 0) { + writer.writeString( + 4, + f + ); + } + f = message.getService(); + if (f.length > 0) { + writer.writeString( + 5, + f + ); + } + f = message.getOperation(); + if (f.length > 0) { + writer.writeString( + 6, + f + ); + } + f = message.getTags(); + if (f.length > 0) { + writer.writeString( + 7, + f + ); + } + f = message.getTimestart(); + if (f !== 0) { + writer.writeInt64( + 8, + f + ); + } + f = message.getTimeend(); + if (f !== 0) { + writer.writeInt64( + 9, + f + ); + } +}; + + +/** + * optional string name = 1; + * @return {string} + */ +proto.plugins.jaeger.GetTracesRequest.prototype.getName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetTracesRequest} returns this + */ +proto.plugins.jaeger.GetTracesRequest.prototype.setName = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string limit = 2; + * @return {string} + */ +proto.plugins.jaeger.GetTracesRequest.prototype.getLimit = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetTracesRequest} returns this + */ +proto.plugins.jaeger.GetTracesRequest.prototype.setLimit = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional string maxDuration = 3; + * @return {string} + */ +proto.plugins.jaeger.GetTracesRequest.prototype.getMaxduration = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetTracesRequest} returns this + */ +proto.plugins.jaeger.GetTracesRequest.prototype.setMaxduration = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + +/** + * optional string minDuration = 4; + * @return {string} + */ +proto.plugins.jaeger.GetTracesRequest.prototype.getMinduration = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetTracesRequest} returns this + */ +proto.plugins.jaeger.GetTracesRequest.prototype.setMinduration = function(value) { + return jspb.Message.setProto3StringField(this, 4, value); +}; + + +/** + * optional string service = 5; + * @return {string} + */ +proto.plugins.jaeger.GetTracesRequest.prototype.getService = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetTracesRequest} returns this + */ +proto.plugins.jaeger.GetTracesRequest.prototype.setService = function(value) { + return jspb.Message.setProto3StringField(this, 5, value); +}; + + +/** + * optional string operation = 6; + * @return {string} + */ +proto.plugins.jaeger.GetTracesRequest.prototype.getOperation = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 6, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetTracesRequest} returns this + */ +proto.plugins.jaeger.GetTracesRequest.prototype.setOperation = function(value) { + return jspb.Message.setProto3StringField(this, 6, value); +}; + + +/** + * optional string tags = 7; + * @return {string} + */ +proto.plugins.jaeger.GetTracesRequest.prototype.getTags = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 7, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetTracesRequest} returns this + */ +proto.plugins.jaeger.GetTracesRequest.prototype.setTags = function(value) { + return jspb.Message.setProto3StringField(this, 7, value); +}; + + +/** + * optional int64 timeStart = 8; + * @return {number} + */ +proto.plugins.jaeger.GetTracesRequest.prototype.getTimestart = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 8, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.plugins.jaeger.GetTracesRequest} returns this + */ +proto.plugins.jaeger.GetTracesRequest.prototype.setTimestart = function(value) { + return jspb.Message.setProto3IntField(this, 8, value); +}; + + +/** + * optional int64 timeEnd = 9; + * @return {number} + */ +proto.plugins.jaeger.GetTracesRequest.prototype.getTimeend = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 9, 0)); +}; + + +/** + * @param {number} value + * @return {!proto.plugins.jaeger.GetTracesRequest} returns this + */ +proto.plugins.jaeger.GetTracesRequest.prototype.setTimeend = function(value) { + return jspb.Message.setProto3IntField(this, 9, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.plugins.jaeger.GetTracesResponse.prototype.toObject = function(opt_includeInstance) { + return proto.plugins.jaeger.GetTracesResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.plugins.jaeger.GetTracesResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.GetTracesResponse.toObject = function(includeInstance, msg) { + var f, obj = { + traces: jspb.Message.getFieldWithDefault(msg, 1, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.plugins.jaeger.GetTracesResponse} + */ +proto.plugins.jaeger.GetTracesResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.plugins.jaeger.GetTracesResponse; + return proto.plugins.jaeger.GetTracesResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.plugins.jaeger.GetTracesResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.plugins.jaeger.GetTracesResponse} + */ +proto.plugins.jaeger.GetTracesResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setTraces(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.plugins.jaeger.GetTracesResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.plugins.jaeger.GetTracesResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.plugins.jaeger.GetTracesResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.GetTracesResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getTraces(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } +}; + + +/** + * optional string traces = 1; + * @return {string} + */ +proto.plugins.jaeger.GetTracesResponse.prototype.getTraces = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetTracesResponse} returns this + */ +proto.plugins.jaeger.GetTracesResponse.prototype.setTraces = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.plugins.jaeger.GetTraceRequest.prototype.toObject = function(opt_includeInstance) { + return proto.plugins.jaeger.GetTraceRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.plugins.jaeger.GetTraceRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.GetTraceRequest.toObject = function(includeInstance, msg) { + var f, obj = { + name: jspb.Message.getFieldWithDefault(msg, 1, ""), + traceid: jspb.Message.getFieldWithDefault(msg, 2, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.plugins.jaeger.GetTraceRequest} + */ +proto.plugins.jaeger.GetTraceRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.plugins.jaeger.GetTraceRequest; + return proto.plugins.jaeger.GetTraceRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.plugins.jaeger.GetTraceRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.plugins.jaeger.GetTraceRequest} + */ +proto.plugins.jaeger.GetTraceRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setTraceid(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.plugins.jaeger.GetTraceRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.plugins.jaeger.GetTraceRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.plugins.jaeger.GetTraceRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.GetTraceRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getName(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getTraceid(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } +}; + + +/** + * optional string name = 1; + * @return {string} + */ +proto.plugins.jaeger.GetTraceRequest.prototype.getName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetTraceRequest} returns this + */ +proto.plugins.jaeger.GetTraceRequest.prototype.setName = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string traceID = 2; + * @return {string} + */ +proto.plugins.jaeger.GetTraceRequest.prototype.getTraceid = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetTraceRequest} returns this + */ +proto.plugins.jaeger.GetTraceRequest.prototype.setTraceid = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.plugins.jaeger.GetTraceResponse.prototype.toObject = function(opt_includeInstance) { + return proto.plugins.jaeger.GetTraceResponse.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.plugins.jaeger.GetTraceResponse} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.GetTraceResponse.toObject = function(includeInstance, msg) { + var f, obj = { + traces: jspb.Message.getFieldWithDefault(msg, 1, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.plugins.jaeger.GetTraceResponse} + */ +proto.plugins.jaeger.GetTraceResponse.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.plugins.jaeger.GetTraceResponse; + return proto.plugins.jaeger.GetTraceResponse.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.plugins.jaeger.GetTraceResponse} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.plugins.jaeger.GetTraceResponse} + */ +proto.plugins.jaeger.GetTraceResponse.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setTraces(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.plugins.jaeger.GetTraceResponse.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.plugins.jaeger.GetTraceResponse.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.plugins.jaeger.GetTraceResponse} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.GetTraceResponse.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getTraces(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } +}; + + +/** + * optional string traces = 1; + * @return {string} + */ +proto.plugins.jaeger.GetTraceResponse.prototype.getTraces = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.GetTraceResponse} returns this + */ +proto.plugins.jaeger.GetTraceResponse.prototype.setTraces = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.plugins.jaeger.Operation.prototype.toObject = function(opt_includeInstance) { + return proto.plugins.jaeger.Operation.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.plugins.jaeger.Operation} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.Operation.toObject = function(includeInstance, msg) { + var f, obj = { + name: jspb.Message.getFieldWithDefault(msg, 1, ""), + spankind: jspb.Message.getFieldWithDefault(msg, 2, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.plugins.jaeger.Operation} + */ +proto.plugins.jaeger.Operation.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.plugins.jaeger.Operation; + return proto.plugins.jaeger.Operation.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.plugins.jaeger.Operation} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.plugins.jaeger.Operation} + */ +proto.plugins.jaeger.Operation.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setSpankind(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.plugins.jaeger.Operation.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.plugins.jaeger.Operation.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.plugins.jaeger.Operation} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.Operation.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getName(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getSpankind(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } +}; + + +/** + * optional string name = 1; + * @return {string} + */ +proto.plugins.jaeger.Operation.prototype.getName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.Operation} returns this + */ +proto.plugins.jaeger.Operation.prototype.setName = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string spanKind = 2; + * @return {string} + */ +proto.plugins.jaeger.Operation.prototype.getSpankind = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.Operation} returns this + */ +proto.plugins.jaeger.Operation.prototype.setSpankind = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + + +/** + * List of repeated fields within this message type. + * @private {!Array<number>} + * @const + */ +proto.plugins.jaeger.Spec.repeatedFields_ = [1]; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.plugins.jaeger.Spec.prototype.toObject = function(opt_includeInstance) { + return proto.plugins.jaeger.Spec.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.plugins.jaeger.Spec} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.Spec.toObject = function(includeInstance, msg) { + var f, obj = { + queriesList: jspb.Message.toObjectList(msg.getQueriesList(), + proto.plugins.jaeger.Query.toObject, includeInstance) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.plugins.jaeger.Spec} + */ +proto.plugins.jaeger.Spec.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.plugins.jaeger.Spec; + return proto.plugins.jaeger.Spec.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.plugins.jaeger.Spec} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.plugins.jaeger.Spec} + */ +proto.plugins.jaeger.Spec.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = new proto.plugins.jaeger.Query; + reader.readMessage(value,proto.plugins.jaeger.Query.deserializeBinaryFromReader); + msg.addQueries(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.plugins.jaeger.Spec.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.plugins.jaeger.Spec.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.plugins.jaeger.Spec} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.Spec.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getQueriesList(); + if (f.length > 0) { + writer.writeRepeatedMessage( + 1, + f, + proto.plugins.jaeger.Query.serializeBinaryToWriter + ); + } +}; + + +/** + * repeated Query queries = 1; + * @return {!Array<!proto.plugins.jaeger.Query>} + */ +proto.plugins.jaeger.Spec.prototype.getQueriesList = function() { + return /** @type{!Array<!proto.plugins.jaeger.Query>} */ ( + jspb.Message.getRepeatedWrapperField(this, proto.plugins.jaeger.Query, 1)); +}; + + +/** + * @param {!Array<!proto.plugins.jaeger.Query>} value + * @return {!proto.plugins.jaeger.Spec} returns this +*/ +proto.plugins.jaeger.Spec.prototype.setQueriesList = function(value) { + return jspb.Message.setRepeatedWrapperField(this, 1, value); +}; + + +/** + * @param {!proto.plugins.jaeger.Query=} opt_value + * @param {number=} opt_index + * @return {!proto.plugins.jaeger.Query} + */ +proto.plugins.jaeger.Spec.prototype.addQueries = function(opt_value, opt_index) { + return jspb.Message.addToRepeatedWrapperField(this, 1, opt_value, proto.plugins.jaeger.Query, opt_index); +}; + + +/** + * Clears the list making it empty but non-null. + * @return {!proto.plugins.jaeger.Spec} returns this + */ +proto.plugins.jaeger.Spec.prototype.clearQueriesList = function() { + return this.setQueriesList([]); +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_<name>, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.plugins.jaeger.Query.prototype.toObject = function(opt_includeInstance) { + return proto.plugins.jaeger.Query.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.plugins.jaeger.Query} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.Query.toObject = function(includeInstance, msg) { + var f, obj = { + name: jspb.Message.getFieldWithDefault(msg, 1, ""), + service: jspb.Message.getFieldWithDefault(msg, 2, ""), + operation: jspb.Message.getFieldWithDefault(msg, 3, ""), + tags: jspb.Message.getFieldWithDefault(msg, 4, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.plugins.jaeger.Query} + */ +proto.plugins.jaeger.Query.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.plugins.jaeger.Query; + return proto.plugins.jaeger.Query.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.plugins.jaeger.Query} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.plugins.jaeger.Query} + */ +proto.plugins.jaeger.Query.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setName(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setService(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setOperation(value); + break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.setTags(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.plugins.jaeger.Query.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.plugins.jaeger.Query.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.plugins.jaeger.Query} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.plugins.jaeger.Query.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getName(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getService(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getOperation(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getTags(); + if (f.length > 0) { + writer.writeString( + 4, + f + ); + } +}; + + +/** + * optional string name = 1; + * @return {string} + */ +proto.plugins.jaeger.Query.prototype.getName = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.Query} returns this + */ +proto.plugins.jaeger.Query.prototype.setName = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string service = 2; + * @return {string} + */ +proto.plugins.jaeger.Query.prototype.getService = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.Query} returns this + */ +proto.plugins.jaeger.Query.prototype.setService = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional string operation = 3; + * @return {string} + */ +proto.plugins.jaeger.Query.prototype.getOperation = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.Query} returns this + */ +proto.plugins.jaeger.Query.prototype.setOperation = function(value) { + return jspb.Message.setProto3StringField(this, 3, value); +}; + + +/** + * optional string tags = 4; + * @return {string} + */ +proto.plugins.jaeger.Query.prototype.getTags = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** + * @param {string} value + * @return {!proto.plugins.jaeger.Query} returns this + */ +proto.plugins.jaeger.Query.prototype.setTags = function(value) { + return jspb.Message.setProto3StringField(this, 4, value); +}; + + +goog.object.extend(exports, proto.plugins.jaeger); diff --git a/app/src/proto/jaeger_pb_service.d.ts b/app/src/proto/jaeger_pb_service.d.ts new file mode 100644 index 000000000..6440d7629 --- /dev/null +++ b/app/src/proto/jaeger_pb_service.d.ts @@ -0,0 +1,101 @@ +// package: plugins.jaeger +// file: jaeger.proto + +import * as jaeger_pb from "./jaeger_pb"; +import {grpc} from "@improbable-eng/grpc-web"; + +type JaegerGetOperations = { + readonly methodName: string; + readonly service: typeof Jaeger; + readonly requestStream: false; + readonly responseStream: false; + readonly requestType: typeof jaeger_pb.GetOperationsRequest; + readonly responseType: typeof jaeger_pb.GetOperationsResponse; +}; + +type JaegerGetTraces = { + readonly methodName: string; + readonly service: typeof Jaeger; + readonly requestStream: false; + readonly responseStream: false; + readonly requestType: typeof jaeger_pb.GetTracesRequest; + readonly responseType: typeof jaeger_pb.GetTracesResponse; +}; + +type JaegerGetTrace = { + readonly methodName: string; + readonly service: typeof Jaeger; + readonly requestStream: false; + readonly responseStream: false; + readonly requestType: typeof jaeger_pb.GetTraceRequest; + readonly responseType: typeof jaeger_pb.GetTraceResponse; +}; + +export class Jaeger { + static readonly serviceName: string; + static readonly GetOperations: JaegerGetOperations; + static readonly GetTraces: JaegerGetTraces; + static readonly GetTrace: JaegerGetTrace; +} + +export type ServiceError = { message: string, code: number; metadata: grpc.Metadata } +export type Status = { details: string, code: number; metadata: grpc.Metadata } + +interface UnaryResponse { + cancel(): void; +} +interface ResponseStream<T> { + cancel(): void; + on(type: 'data', handler: (message: T) => void): ResponseStream<T>; + on(type: 'end', handler: (status?: Status) => void): ResponseStream<T>; + on(type: 'status', handler: (status: Status) => void): ResponseStream<T>; +} +interface RequestStream<T> { + write(message: T): RequestStream<T>; + end(): void; + cancel(): void; + on(type: 'end', handler: (status?: Status) => void): RequestStream<T>; + on(type: 'status', handler: (status: Status) => void): RequestStream<T>; +} +interface BidirectionalStream<ReqT, ResT> { + write(message: ReqT): BidirectionalStream<ReqT, ResT>; + end(): void; + cancel(): void; + on(type: 'data', handler: (message: ResT) => void): BidirectionalStream<ReqT, ResT>; + on(type: 'end', handler: (status?: Status) => void): BidirectionalStream<ReqT, ResT>; + on(type: 'status', handler: (status: Status) => void): BidirectionalStream<ReqT, ResT>; +} + +export class JaegerClient { + readonly serviceHost: string; + + constructor(serviceHost: string, options?: grpc.RpcOptions); + getOperations( + requestMessage: jaeger_pb.GetOperationsRequest, + metadata: grpc.Metadata, + callback: (error: ServiceError|null, responseMessage: jaeger_pb.GetOperationsResponse|null) => void + ): UnaryResponse; + getOperations( + requestMessage: jaeger_pb.GetOperationsRequest, + callback: (error: ServiceError|null, responseMessage: jaeger_pb.GetOperationsResponse|null) => void + ): UnaryResponse; + getTraces( + requestMessage: jaeger_pb.GetTracesRequest, + metadata: grpc.Metadata, + callback: (error: ServiceError|null, responseMessage: jaeger_pb.GetTracesResponse|null) => void + ): UnaryResponse; + getTraces( + requestMessage: jaeger_pb.GetTracesRequest, + callback: (error: ServiceError|null, responseMessage: jaeger_pb.GetTracesResponse|null) => void + ): UnaryResponse; + getTrace( + requestMessage: jaeger_pb.GetTraceRequest, + metadata: grpc.Metadata, + callback: (error: ServiceError|null, responseMessage: jaeger_pb.GetTraceResponse|null) => void + ): UnaryResponse; + getTrace( + requestMessage: jaeger_pb.GetTraceRequest, + callback: (error: ServiceError|null, responseMessage: jaeger_pb.GetTraceResponse|null) => void + ): UnaryResponse; +} + diff --git a/app/src/proto/jaeger_pb_service.js b/app/src/proto/jaeger_pb_service.js new file mode 100644 index 000000000..2108566cf --- /dev/null +++ b/app/src/proto/jaeger_pb_service.js @@ -0,0 +1,141 @@ +// package: plugins.jaeger +// file: jaeger.proto + +var jaeger_pb = require("./jaeger_pb"); +var grpc = require("@improbable-eng/grpc-web").grpc; + +var Jaeger = (function () { + function Jaeger() {} + Jaeger.serviceName = "plugins.jaeger.Jaeger"; + return Jaeger; +}()); + +Jaeger.GetOperations = { + methodName: "GetOperations", + service: Jaeger, + requestStream: false, + responseStream: false, + requestType: jaeger_pb.GetOperationsRequest, + responseType: jaeger_pb.GetOperationsResponse +}; + +Jaeger.GetTraces = { + methodName: "GetTraces", + service: Jaeger, + requestStream: false, + responseStream: false, + requestType: jaeger_pb.GetTracesRequest, + responseType: jaeger_pb.GetTracesResponse +}; + +Jaeger.GetTrace = { + methodName: "GetTrace", + service: Jaeger, + requestStream: false, + responseStream: false, + requestType: jaeger_pb.GetTraceRequest, + responseType: jaeger_pb.GetTraceResponse +}; + +exports.Jaeger = Jaeger; + +function JaegerClient(serviceHost, options) { + this.serviceHost = serviceHost; + this.options = options || {}; +} + +JaegerClient.prototype.getOperations = function getOperations(requestMessage, metadata, callback) { + if (arguments.length === 2) { + callback = arguments[1]; + } + var client = grpc.unary(Jaeger.GetOperations, { + request: requestMessage, + host: this.serviceHost, + metadata: metadata, + transport: this.options.transport, + debug: this.options.debug, + onEnd: function (response) { + if (callback) { + if (response.status !== grpc.Code.OK) { + var err = new Error(response.statusMessage); + err.code = response.status; + err.metadata = response.trailers; + callback(err, null); + } else { + callback(null, response.message); + } + } + } + }); + return { + cancel: function () { + callback = null; + client.close(); + } + }; +}; + +JaegerClient.prototype.getTraces = function getTraces(requestMessage, metadata, callback) { + if (arguments.length === 2) { + callback = arguments[1]; + } + var client = grpc.unary(Jaeger.GetTraces, { + request: requestMessage, + host: this.serviceHost, + metadata: metadata, + transport: this.options.transport, + debug: this.options.debug, + onEnd: function (response) { + if (callback) { + if (response.status !== grpc.Code.OK) { + var err = new Error(response.statusMessage); + err.code = response.status; + err.metadata = response.trailers; + callback(err, null); + } else { + callback(null, response.message); + } + } + } + }); + return { + cancel: function () { + callback = null; + client.close(); + } + }; +}; + +JaegerClient.prototype.getTrace = function getTrace(requestMessage, metadata, callback) { + if (arguments.length === 2) { + callback = arguments[1]; + } + var client = grpc.unary(Jaeger.GetTrace, { + request: requestMessage, + host: this.serviceHost, + metadata: metadata, + transport: this.options.transport, + debug: this.options.debug, + onEnd: function (response) { + if (callback) { + if (response.status !== grpc.Code.OK) { + var err = new Error(response.statusMessage); + err.code = response.status; + err.metadata = response.trailers; + callback(err, null); + } else { + callback(null, response.message); + } + } + } + }); + return { + cancel: function () { + callback = null; + client.close(); + } + }; +}; + +exports.JaegerClient = JaegerClient; + diff --git a/app/src/proto/plugins_grpc_web_pb.js b/app/src/proto/plugins_grpc_web_pb.js index 4d1d8492f..5b042f500 100644 --- a/app/src/proto/plugins_grpc_web_pb.js +++ b/app/src/proto/plugins_grpc_web_pb.js @@ -19,6 +19,8 @@ grpc.web = require('grpc-web'); var prometheus_pb = require('./prometheus_pb.js') var elasticsearch_pb = require('./elasticsearch_pb.js') + +var jaeger_pb = require('./jaeger_pb.js') const proto = {}; proto.plugins = require('./plugins_pb.js'); diff --git a/app/src/proto/plugins_pb.d.ts b/app/src/proto/plugins_pb.d.ts index 5ba37299b..6043bfb02 100644 --- a/app/src/proto/plugins_pb.d.ts +++ b/app/src/proto/plugins_pb.d.ts @@ -4,6 +4,7 @@ import * as jspb from "google-protobuf"; import * as prometheus_pb from "./prometheus_pb"; import * as elasticsearch_pb from "./elasticsearch_pb"; +import * as jaeger_pb from "./jaeger_pb"; export class GetPluginsRequest extends jspb.Message { serializeBinary(): Uint8Array; @@ -85,6 +86,11 @@ export class Plugin extends jspb.Message { getElasticsearch(): elasticsearch_pb.Spec | undefined; setElasticsearch(value?: elasticsearch_pb.Spec): void; + hasJaeger(): boolean; + clearJaeger(): void; + getJaeger(): jaeger_pb.Spec | undefined; + setJaeger(value?: jaeger_pb.Spec): void; + serializeBinary(): Uint8Array; toObject(includeInstance?: boolean): Plugin.AsObject; static toObject(includeInstance: boolean, msg: Plugin): Plugin.AsObject; @@ -100,6 +106,7 @@ export namespace Plugin { name: string, prometheus?: prometheus_pb.Spec.AsObject, elasticsearch?: elasticsearch_pb.Spec.AsObject, + jaeger?: jaeger_pb.Spec.AsObject, } } diff --git a/app/src/proto/plugins_pb.js b/app/src/proto/plugins_pb.js index 121f6c0a1..45efd6d4a 100644 --- a/app/src/proto/plugins_pb.js +++ b/app/src/proto/plugins_pb.js @@ -18,6 +18,8 @@ var prometheus_pb = require('./prometheus_pb.js'); goog.object.extend(proto, prometheus_pb); var elasticsearch_pb = require('./elasticsearch_pb.js'); goog.object.extend(proto, elasticsearch_pb); +var jaeger_pb = require('./jaeger_pb.js'); +goog.object.extend(proto, jaeger_pb); goog.exportSymbol('proto.plugins.GetPluginsRequest', null, global); goog.exportSymbol('proto.plugins.GetPluginsResponse', null, global); goog.exportSymbol('proto.plugins.Plugin', null, global); @@ -591,7 +593,8 @@ proto.plugins.Plugin.toObject = function(includeInstance, msg) { var f, obj = { name: jspb.Message.getFieldWithDefault(msg, 1, ""), prometheus: (f = msg.getPrometheus()) && prometheus_pb.Spec.toObject(includeInstance, f), - elasticsearch: (f = msg.getElasticsearch()) && elasticsearch_pb.Spec.toObject(includeInstance, f) + elasticsearch: (f = msg.getElasticsearch()) && elasticsearch_pb.Spec.toObject(includeInstance, f), + jaeger: (f = msg.getJaeger()) && jaeger_pb.Spec.toObject(includeInstance, f) }; if (includeInstance) { @@ -642,6 +645,11 @@ proto.plugins.Plugin.deserializeBinaryFromReader = function(msg, reader) { reader.readMessage(value,elasticsearch_pb.Spec.deserializeBinaryFromReader); msg.setElasticsearch(value); break; + case 4: + var value = new jaeger_pb.Spec; + reader.readMessage(value,jaeger_pb.Spec.deserializeBinaryFromReader); + msg.setJaeger(value); + break; default: reader.skipField(); break; @@ -694,6 +702,14 @@ proto.plugins.Plugin.serializeBinaryToWriter = function(message, writer) { elasticsearch_pb.Spec.serializeBinaryToWriter ); } + f = message.getJaeger(); + if (f != null) { + writer.writeMessage( + 4, + f, + jaeger_pb.Spec.serializeBinaryToWriter + ); + } }; @@ -789,4 +805,41 @@ proto.plugins.Plugin.prototype.hasElasticsearch = function() { }; +/** + * optional jaeger.Spec jaeger = 4; + * @return {?proto.plugins.jaeger.Spec} + */ +proto.plugins.Plugin.prototype.getJaeger = function() { + return /** @type{?proto.plugins.jaeger.Spec} */ ( + jspb.Message.getWrapperField(this, jaeger_pb.Spec, 4)); +}; + + +/** + * @param {?proto.plugins.jaeger.Spec|undefined} value + * @return {!proto.plugins.Plugin} returns this +*/ +proto.plugins.Plugin.prototype.setJaeger = function(value) { + return jspb.Message.setWrapperField(this, 4, value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.plugins.Plugin} returns this + */ +proto.plugins.Plugin.prototype.clearJaeger = function() { + return this.setJaeger(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.plugins.Plugin.prototype.hasJaeger = function() { + return jspb.Message.getField(this, 4) != null; +}; + + goog.object.extend(exports, proto.plugins); diff --git a/app/src/utils/plugins.tsx b/app/src/utils/plugins.tsx index 4af945776..bc24a4eed 100644 --- a/app/src/utils/plugins.tsx +++ b/app/src/utils/plugins.tsx @@ -2,10 +2,12 @@ import React from 'react'; import ElasticsearchPage from 'plugins/elasticsearch/ElasticsearchPage'; import ElasticsearchPlugin from 'plugins/elasticsearch/ElasticsearchPlugin'; +import JaegerPage from 'plugins/jaeger/JaegerPage'; +import JaegerPlugin from 'plugins/jaeger/JaegerPlugin'; import PrometheusPage from 'plugins/prometheus/PrometheusPage'; import PrometheusPlugin from 'plugins/prometheus/PrometheusPlugin'; -import { Plugin as IProtoPlugin } from 'proto/plugins_pb'; +import { Plugin as IProtoPlugin } from 'proto/plugins_grpc_web_pb'; // IPluginPageProps is the interface for the properties, which are passed to the page implementation of a plugin. This // is the name and the description of the plugin. @@ -44,6 +46,10 @@ export const plugins: IPlugins = { page: ElasticsearchPage, plugin: ElasticsearchPlugin, }, + jaeger: { + page: JaegerPage, + plugin: JaegerPlugin, + }, prometheus: { page: PrometheusPage, plugin: PrometheusPlugin, diff --git a/app/src/utils/resources.tsx b/app/src/utils/resources.tsx index 657e33cdc..777371bda 100644 --- a/app/src/utils/resources.tsx +++ b/app/src/utils/resources.tsx @@ -13,7 +13,7 @@ import { JSONPath } from 'jsonpath-plus'; import React from 'react'; import SearchIcon from '@patternfly/react-icons/dist/js/icons/search-icon'; -import { CRD, Resources as ProtoResources } from 'proto/clusters_pb'; +import { CRD, Resources as ProtoResources } from 'proto/clusters_grpc_web_pb'; import { timeDifference } from 'utils/helpers'; // TScope is the scope of a resource, which can be namespaced or cluster. diff --git a/deploy/docker/kobs/config.yaml b/deploy/docker/kobs/config.yaml index 92cba4ba8..4aad440e2 100644 --- a/deploy/docker/kobs/config.yaml +++ b/deploy/docker/kobs/config.yaml @@ -21,9 +21,9 @@ elasticsearch: token: jaeger: - - name: - description: - address: + - name: Jaeger + description: Jaeger can be used for the traces of your application. + address: http://localhost:16686 username: password: token: diff --git a/deploy/kustomize/crds/kobs.io_applications.yaml b/deploy/kustomize/crds/kobs.io_applications.yaml index ab854d942..b148925a3 100644 --- a/deploy/kustomize/crds/kobs.io_applications.yaml +++ b/deploy/kustomize/crds/kobs.io_applications.yaml @@ -101,6 +101,22 @@ spec: type: object type: array type: object + jaeger: + properties: + queries: + items: + properties: + name: + type: string + operation: + type: string + service: + type: string + tags: + type: string + type: object + type: array + type: object name: type: string prometheus: diff --git a/pkg/api/plugins/jaeger/jaeger.go b/pkg/api/plugins/jaeger/jaeger.go new file mode 100644 index 000000000..bccd8ce32 --- /dev/null +++ b/pkg/api/plugins/jaeger/jaeger.go @@ -0,0 +1,248 @@ +package jaeger + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + + jaegerProto "github.com/kobsio/kobs/pkg/api/plugins/jaeger/proto" + pluginsProto "github.com/kobsio/kobs/pkg/api/plugins/plugins/proto" + "github.com/kobsio/kobs/pkg/api/plugins/plugins/shared" + + "github.com/sirupsen/logrus" + "google.golang.org/grpc" +) + +var ( + log = logrus.WithFields(logrus.Fields{"package": "jaeger"}) +) + +type Config struct { + Name string `yaml:"name"` + Description string `yaml:"description"` + Address string `yaml:"address"` + Username string `yaml:"username"` + Password string `yaml:"password"` + Token string `yaml:"token"` +} + +// ResponseDataServices is the structure of the response for a services request against the Jaeger API. +type ResponseDataServices struct { + Data []string `json:"data"` +} + +// ResponseDataOperations is the structure of the response for a operations request against the Jaeger API. +type ResponseDataOperations struct { + Data []*jaegerProto.Operation `json:"data"` +} + +// ResponseError is the structure for a failed Jaeger API request. +type ResponseError struct { + Errors []struct { + Code int `json:"code"` + Msg string `json:"msg"` + } `json:"errors"` +} + +type Instance struct { + name string + address string + client *http.Client +} + +// doRequest is a helper function to run a request against a Jaeger instance for the given path. It returns the body or +// if the request failed the error message. +func (i *Instance) doRequest(url string) ([]byte, error) { + req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s%s", i.address, url), nil) + if err != nil { + return nil, err + } + + resp, err := i.client.Do(req) + if err != nil { + return nil, err + } + + defer resp.Body.Close() + + if resp.StatusCode >= 200 && resp.StatusCode < 300 { + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + return body, nil + } + + var res ResponseError + + err = json.NewDecoder(resp.Body).Decode(&res) + if err != nil { + return nil, err + } + + if len(res.Errors) > 0 { + return nil, fmt.Errorf(res.Errors[0].Msg) + } + + return nil, fmt.Errorf("%v", res) +} + +type Jaeger struct { + jaegerProto.UnimplementedJaegerServer + instances []*Instance +} + +func (j *Jaeger) getInstace(name string) *Instance { + for _, i := range j.instances { + if i.name == name { + return i + } + } + + return nil +} + +func (j *Jaeger) GetOperations(ctx context.Context, getOperationsRequest *jaegerProto.GetOperationsRequest) (*jaegerProto.GetOperationsResponse, error) { + if getOperationsRequest == nil { + return nil, fmt.Errorf("request data is missing") + } + + instance := j.getInstace(getOperationsRequest.Name) + if instance == nil { + return nil, fmt.Errorf("invalid name for Jaeger plugin") + } + + log.WithFields(logrus.Fields{"service": getOperationsRequest.Service}).Tracef("GetOperations") + + var services []string + var service string + if getOperationsRequest.Service == "" { + body, err := instance.doRequest("/api/services") + if err != nil { + return nil, err + } + + var response ResponseDataServices + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + + services = response.Data + service = services[0] + + log.WithFields(logrus.Fields{"count": len(services)}).Tracef("GetOperations retrieved services") + } else { + service = getOperationsRequest.Service + } + + body, err := instance.doRequest(fmt.Sprintf("/api/operations?service=%s", service)) + if err != nil { + return nil, err + } + + var response ResponseDataOperations + err = json.Unmarshal(body, &response) + if err != nil { + return nil, err + } + + log.WithFields(logrus.Fields{"count": len(response.Data)}).Tracef("GetOperations retrieved operations") + + return &jaegerProto.GetOperationsResponse{ + Services: services, + Operations: response.Data, + }, nil +} + +func (j *Jaeger) GetTraces(ctx context.Context, getTracesRequest *jaegerProto.GetTracesRequest) (*jaegerProto.GetTracesResponse, error) { + if getTracesRequest == nil { + return nil, fmt.Errorf("request data is missing") + } + + instance := j.getInstace(getTracesRequest.Name) + if instance == nil { + return nil, fmt.Errorf("invalid name for Jaeger plugin") + } + + log.WithFields(logrus.Fields{"service": getTracesRequest.Service, "operation": getTracesRequest.Operation, "tags": getTracesRequest.Tags}).Tracef("GetTraces") + + body, err := instance.doRequest(fmt.Sprintf("/api/traces?end=%d&limit=%s&lookback=custom&maxDuration=%s&minDuration=%s&operation=%s&service=%s&start=%d", getTracesRequest.TimeEnd*1000000, getTracesRequest.Limit, getTracesRequest.MaxDuration, getTracesRequest.MinDuration, getTracesRequest.Operation, getTracesRequest.Service, getTracesRequest.TimeStart*1000000)) + if err != nil { + return nil, err + } + + return &jaegerProto.GetTracesResponse{ + Traces: string(body), + }, nil +} + +func (j *Jaeger) GetTrace(ctx context.Context, getTraceRequest *jaegerProto.GetTraceRequest) (*jaegerProto.GetTraceResponse, error) { + if getTraceRequest == nil { + return nil, fmt.Errorf("request data is missing") + } + + instance := j.getInstace(getTraceRequest.Name) + if instance == nil { + return nil, fmt.Errorf("invalid name for Jaeger plugin") + } + + log.WithFields(logrus.Fields{"traceID": getTraceRequest.TraceID}).Tracef("GetTrace") + + body, err := instance.doRequest(fmt.Sprintf("/api/traces/%s", getTraceRequest.TraceID)) + if err != nil { + return nil, err + } + + return &jaegerProto.GetTraceResponse{ + Traces: string(body), + }, nil +} + +func Register(cfg []Config, grpcServer *grpc.Server) ([]*pluginsProto.PluginShort, error) { + log.Tracef("Register Jaeger Plugin.") + + var pluginDetails []*pluginsProto.PluginShort + var instances []*Instance + + for _, config := range cfg { + roundTripper := shared.DefaultRoundTripper + + if config.Username != "" && config.Password != "" { + roundTripper = shared.BasicAuthTransport{ + Transport: roundTripper, + Username: config.Username, + Password: config.Password, + } + } + + if config.Token != "" { + roundTripper = shared.TokenAuthTransporter{ + Transport: roundTripper, + Token: config.Token, + } + } + + pluginDetails = append(pluginDetails, &pluginsProto.PluginShort{ + Name: config.Name, + Description: config.Description, + Type: "jaeger", + }) + instances = append(instances, &Instance{ + name: config.Name, + address: config.Address, + client: &http.Client{ + Transport: roundTripper, + }, + }) + } + + jaegerProto.RegisterJaegerServer(grpcServer, &Jaeger{ + instances: instances, + }) + + return pluginDetails, nil +} diff --git a/pkg/api/plugins/jaeger/proto/jaeger.pb.go b/pkg/api/plugins/jaeger/proto/jaeger.pb.go new file mode 100644 index 000000000..1de7a8f55 --- /dev/null +++ b/pkg/api/plugins/jaeger/proto/jaeger.pb.go @@ -0,0 +1,824 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.14.0 +// source: jaeger.proto + +package proto + +import ( + proto "github.com/golang/protobuf/proto" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +type GetOperationsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Service string `protobuf:"bytes,2,opt,name=service,proto3" json:"service,omitempty"` +} + +func (x *GetOperationsRequest) Reset() { + *x = GetOperationsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_jaeger_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetOperationsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetOperationsRequest) ProtoMessage() {} + +func (x *GetOperationsRequest) ProtoReflect() protoreflect.Message { + mi := &file_jaeger_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetOperationsRequest.ProtoReflect.Descriptor instead. +func (*GetOperationsRequest) Descriptor() ([]byte, []int) { + return file_jaeger_proto_rawDescGZIP(), []int{0} +} + +func (x *GetOperationsRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *GetOperationsRequest) GetService() string { + if x != nil { + return x.Service + } + return "" +} + +type GetOperationsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Services []string `protobuf:"bytes,1,rep,name=services,proto3" json:"services,omitempty"` + Operations []*Operation `protobuf:"bytes,2,rep,name=operations,proto3" json:"operations,omitempty"` +} + +func (x *GetOperationsResponse) Reset() { + *x = GetOperationsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_jaeger_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetOperationsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetOperationsResponse) ProtoMessage() {} + +func (x *GetOperationsResponse) ProtoReflect() protoreflect.Message { + mi := &file_jaeger_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetOperationsResponse.ProtoReflect.Descriptor instead. +func (*GetOperationsResponse) Descriptor() ([]byte, []int) { + return file_jaeger_proto_rawDescGZIP(), []int{1} +} + +func (x *GetOperationsResponse) GetServices() []string { + if x != nil { + return x.Services + } + return nil +} + +func (x *GetOperationsResponse) GetOperations() []*Operation { + if x != nil { + return x.Operations + } + return nil +} + +type GetTracesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Limit string `protobuf:"bytes,2,opt,name=limit,proto3" json:"limit,omitempty"` + MaxDuration string `protobuf:"bytes,3,opt,name=maxDuration,proto3" json:"maxDuration,omitempty"` + MinDuration string `protobuf:"bytes,4,opt,name=minDuration,proto3" json:"minDuration,omitempty"` + Service string `protobuf:"bytes,5,opt,name=service,proto3" json:"service,omitempty"` + Operation string `protobuf:"bytes,6,opt,name=operation,proto3" json:"operation,omitempty"` + Tags string `protobuf:"bytes,7,opt,name=tags,proto3" json:"tags,omitempty"` + TimeStart int64 `protobuf:"varint,8,opt,name=timeStart,proto3" json:"timeStart,omitempty"` + TimeEnd int64 `protobuf:"varint,9,opt,name=timeEnd,proto3" json:"timeEnd,omitempty"` +} + +func (x *GetTracesRequest) Reset() { + *x = GetTracesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_jaeger_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTracesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTracesRequest) ProtoMessage() {} + +func (x *GetTracesRequest) ProtoReflect() protoreflect.Message { + mi := &file_jaeger_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTracesRequest.ProtoReflect.Descriptor instead. +func (*GetTracesRequest) Descriptor() ([]byte, []int) { + return file_jaeger_proto_rawDescGZIP(), []int{2} +} + +func (x *GetTracesRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *GetTracesRequest) GetLimit() string { + if x != nil { + return x.Limit + } + return "" +} + +func (x *GetTracesRequest) GetMaxDuration() string { + if x != nil { + return x.MaxDuration + } + return "" +} + +func (x *GetTracesRequest) GetMinDuration() string { + if x != nil { + return x.MinDuration + } + return "" +} + +func (x *GetTracesRequest) GetService() string { + if x != nil { + return x.Service + } + return "" +} + +func (x *GetTracesRequest) GetOperation() string { + if x != nil { + return x.Operation + } + return "" +} + +func (x *GetTracesRequest) GetTags() string { + if x != nil { + return x.Tags + } + return "" +} + +func (x *GetTracesRequest) GetTimeStart() int64 { + if x != nil { + return x.TimeStart + } + return 0 +} + +func (x *GetTracesRequest) GetTimeEnd() int64 { + if x != nil { + return x.TimeEnd + } + return 0 +} + +type GetTracesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Traces string `protobuf:"bytes,1,opt,name=traces,proto3" json:"traces,omitempty"` +} + +func (x *GetTracesResponse) Reset() { + *x = GetTracesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_jaeger_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTracesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTracesResponse) ProtoMessage() {} + +func (x *GetTracesResponse) ProtoReflect() protoreflect.Message { + mi := &file_jaeger_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTracesResponse.ProtoReflect.Descriptor instead. +func (*GetTracesResponse) Descriptor() ([]byte, []int) { + return file_jaeger_proto_rawDescGZIP(), []int{3} +} + +func (x *GetTracesResponse) GetTraces() string { + if x != nil { + return x.Traces + } + return "" +} + +type GetTraceRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + TraceID string `protobuf:"bytes,2,opt,name=traceID,proto3" json:"traceID,omitempty"` +} + +func (x *GetTraceRequest) Reset() { + *x = GetTraceRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_jaeger_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTraceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTraceRequest) ProtoMessage() {} + +func (x *GetTraceRequest) ProtoReflect() protoreflect.Message { + mi := &file_jaeger_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTraceRequest.ProtoReflect.Descriptor instead. +func (*GetTraceRequest) Descriptor() ([]byte, []int) { + return file_jaeger_proto_rawDescGZIP(), []int{4} +} + +func (x *GetTraceRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *GetTraceRequest) GetTraceID() string { + if x != nil { + return x.TraceID + } + return "" +} + +type GetTraceResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Traces string `protobuf:"bytes,1,opt,name=traces,proto3" json:"traces,omitempty"` +} + +func (x *GetTraceResponse) Reset() { + *x = GetTraceResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_jaeger_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetTraceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTraceResponse) ProtoMessage() {} + +func (x *GetTraceResponse) ProtoReflect() protoreflect.Message { + mi := &file_jaeger_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTraceResponse.ProtoReflect.Descriptor instead. +func (*GetTraceResponse) Descriptor() ([]byte, []int) { + return file_jaeger_proto_rawDescGZIP(), []int{5} +} + +func (x *GetTraceResponse) GetTraces() string { + if x != nil { + return x.Traces + } + return "" +} + +type Operation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + SpanKind string `protobuf:"bytes,2,opt,name=spanKind,proto3" json:"spanKind,omitempty"` +} + +func (x *Operation) Reset() { + *x = Operation{} + if protoimpl.UnsafeEnabled { + mi := &file_jaeger_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Operation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Operation) ProtoMessage() {} + +func (x *Operation) ProtoReflect() protoreflect.Message { + mi := &file_jaeger_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Operation.ProtoReflect.Descriptor instead. +func (*Operation) Descriptor() ([]byte, []int) { + return file_jaeger_proto_rawDescGZIP(), []int{6} +} + +func (x *Operation) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Operation) GetSpanKind() string { + if x != nil { + return x.SpanKind + } + return "" +} + +type Spec struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Queries []*Query `protobuf:"bytes,1,rep,name=queries,proto3" json:"queries,omitempty"` +} + +func (x *Spec) Reset() { + *x = Spec{} + if protoimpl.UnsafeEnabled { + mi := &file_jaeger_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Spec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Spec) ProtoMessage() {} + +func (x *Spec) ProtoReflect() protoreflect.Message { + mi := &file_jaeger_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Spec.ProtoReflect.Descriptor instead. +func (*Spec) Descriptor() ([]byte, []int) { + return file_jaeger_proto_rawDescGZIP(), []int{7} +} + +func (x *Spec) GetQueries() []*Query { + if x != nil { + return x.Queries + } + return nil +} + +type Query struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Service string `protobuf:"bytes,2,opt,name=service,proto3" json:"service,omitempty"` + Operation string `protobuf:"bytes,3,opt,name=operation,proto3" json:"operation,omitempty"` + Tags string `protobuf:"bytes,4,opt,name=tags,proto3" json:"tags,omitempty"` +} + +func (x *Query) Reset() { + *x = Query{} + if protoimpl.UnsafeEnabled { + mi := &file_jaeger_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Query) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Query) ProtoMessage() {} + +func (x *Query) ProtoReflect() protoreflect.Message { + mi := &file_jaeger_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Query.ProtoReflect.Descriptor instead. +func (*Query) Descriptor() ([]byte, []int) { + return file_jaeger_proto_rawDescGZIP(), []int{8} +} + +func (x *Query) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Query) GetService() string { + if x != nil { + return x.Service + } + return "" +} + +func (x *Query) GetOperation() string { + if x != nil { + return x.Operation + } + return "" +} + +func (x *Query) GetTags() string { + if x != nil { + return x.Tags + } + return "" +} + +var File_jaeger_proto protoreflect.FileDescriptor + +var file_jaeger_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x22, 0x44, + 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x22, 0x6e, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, + 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x6f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x2e, 0x4f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x84, 0x02, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x69, + 0x6d, 0x69, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x61, 0x78, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x69, 0x6e, 0x44, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x69, 0x6e, 0x44, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x61, 0x67, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x45, 0x6e, 0x64, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x45, 0x6e, 0x64, 0x22, 0x2b, 0x0a, 0x11, 0x47, + 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x22, 0x3f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, + 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x44, 0x22, 0x2a, 0x0a, 0x10, 0x47, 0x65, 0x74, + 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x74, 0x72, 0x61, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, + 0x72, 0x61, 0x63, 0x65, 0x73, 0x22, 0x3b, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x70, 0x61, 0x6e, 0x4b, 0x69, + 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x70, 0x61, 0x6e, 0x4b, 0x69, + 0x6e, 0x64, 0x22, 0x37, 0x0a, 0x04, 0x53, 0x70, 0x65, 0x63, 0x12, 0x2f, 0x0a, 0x07, 0x71, 0x75, + 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x52, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0x67, 0x0a, 0x05, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x74, 0x61, 0x67, 0x73, 0x32, 0x8d, 0x02, 0x0a, 0x06, 0x4a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x12, + 0x5e, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x24, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x6a, 0x61, 0x65, 0x67, 0x65, + 0x72, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, + 0x2e, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x52, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x2e, 0x47, 0x65, + 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, + 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x2e, + 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x4f, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x12, + 0x1f, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, + 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x20, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x6a, 0x61, 0x65, 0x67, 0x65, + 0x72, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x42, 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x6b, 0x6f, 0x62, 0x73, 0x69, 0x6f, 0x2f, 0x6b, 0x6f, 0x62, 0x73, 0x2f, 0x70, + 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2f, 0x6a, + 0x61, 0x65, 0x67, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, +} + +var ( + file_jaeger_proto_rawDescOnce sync.Once + file_jaeger_proto_rawDescData = file_jaeger_proto_rawDesc +) + +func file_jaeger_proto_rawDescGZIP() []byte { + file_jaeger_proto_rawDescOnce.Do(func() { + file_jaeger_proto_rawDescData = protoimpl.X.CompressGZIP(file_jaeger_proto_rawDescData) + }) + return file_jaeger_proto_rawDescData +} + +var file_jaeger_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_jaeger_proto_goTypes = []interface{}{ + (*GetOperationsRequest)(nil), // 0: plugins.jaeger.GetOperationsRequest + (*GetOperationsResponse)(nil), // 1: plugins.jaeger.GetOperationsResponse + (*GetTracesRequest)(nil), // 2: plugins.jaeger.GetTracesRequest + (*GetTracesResponse)(nil), // 3: plugins.jaeger.GetTracesResponse + (*GetTraceRequest)(nil), // 4: plugins.jaeger.GetTraceRequest + (*GetTraceResponse)(nil), // 5: plugins.jaeger.GetTraceResponse + (*Operation)(nil), // 6: plugins.jaeger.Operation + (*Spec)(nil), // 7: plugins.jaeger.Spec + (*Query)(nil), // 8: plugins.jaeger.Query +} +var file_jaeger_proto_depIdxs = []int32{ + 6, // 0: plugins.jaeger.GetOperationsResponse.operations:type_name -> plugins.jaeger.Operation + 8, // 1: plugins.jaeger.Spec.queries:type_name -> plugins.jaeger.Query + 0, // 2: plugins.jaeger.Jaeger.GetOperations:input_type -> plugins.jaeger.GetOperationsRequest + 2, // 3: plugins.jaeger.Jaeger.GetTraces:input_type -> plugins.jaeger.GetTracesRequest + 4, // 4: plugins.jaeger.Jaeger.GetTrace:input_type -> plugins.jaeger.GetTraceRequest + 1, // 5: plugins.jaeger.Jaeger.GetOperations:output_type -> plugins.jaeger.GetOperationsResponse + 3, // 6: plugins.jaeger.Jaeger.GetTraces:output_type -> plugins.jaeger.GetTracesResponse + 5, // 7: plugins.jaeger.Jaeger.GetTrace:output_type -> plugins.jaeger.GetTraceResponse + 5, // [5:8] is the sub-list for method output_type + 2, // [2:5] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_jaeger_proto_init() } +func file_jaeger_proto_init() { + if File_jaeger_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_jaeger_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetOperationsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_jaeger_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetOperationsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_jaeger_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTracesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_jaeger_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTracesResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_jaeger_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTraceRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_jaeger_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetTraceResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_jaeger_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Operation); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_jaeger_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Spec); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_jaeger_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Query); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_jaeger_proto_rawDesc, + NumEnums: 0, + NumMessages: 9, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_jaeger_proto_goTypes, + DependencyIndexes: file_jaeger_proto_depIdxs, + MessageInfos: file_jaeger_proto_msgTypes, + }.Build() + File_jaeger_proto = out.File + file_jaeger_proto_rawDesc = nil + file_jaeger_proto_goTypes = nil + file_jaeger_proto_depIdxs = nil +} diff --git a/pkg/api/plugins/jaeger/proto/jaeger_deepcopy.gen.go b/pkg/api/plugins/jaeger/proto/jaeger_deepcopy.gen.go new file mode 100644 index 000000000..44b906965 --- /dev/null +++ b/pkg/api/plugins/jaeger/proto/jaeger_deepcopy.gen.go @@ -0,0 +1,204 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: jaeger.proto + +package proto + +import ( + fmt "fmt" + proto "github.com/gogo/protobuf/proto" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// DeepCopyInto supports using GetOperationsRequest within kubernetes types, where deepcopy-gen is used. +func (in *GetOperationsRequest) DeepCopyInto(out *GetOperationsRequest) { + p := proto.Clone(in).(*GetOperationsRequest) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GetOperationsRequest. Required by controller-gen. +func (in *GetOperationsRequest) DeepCopy() *GetOperationsRequest { + if in == nil { + return nil + } + out := new(GetOperationsRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GetOperationsRequest. Required by controller-gen. +func (in *GetOperationsRequest) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using GetOperationsResponse within kubernetes types, where deepcopy-gen is used. +func (in *GetOperationsResponse) DeepCopyInto(out *GetOperationsResponse) { + p := proto.Clone(in).(*GetOperationsResponse) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GetOperationsResponse. Required by controller-gen. +func (in *GetOperationsResponse) DeepCopy() *GetOperationsResponse { + if in == nil { + return nil + } + out := new(GetOperationsResponse) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GetOperationsResponse. Required by controller-gen. +func (in *GetOperationsResponse) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using GetTracesRequest within kubernetes types, where deepcopy-gen is used. +func (in *GetTracesRequest) DeepCopyInto(out *GetTracesRequest) { + p := proto.Clone(in).(*GetTracesRequest) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GetTracesRequest. Required by controller-gen. +func (in *GetTracesRequest) DeepCopy() *GetTracesRequest { + if in == nil { + return nil + } + out := new(GetTracesRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GetTracesRequest. Required by controller-gen. +func (in *GetTracesRequest) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using GetTracesResponse within kubernetes types, where deepcopy-gen is used. +func (in *GetTracesResponse) DeepCopyInto(out *GetTracesResponse) { + p := proto.Clone(in).(*GetTracesResponse) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GetTracesResponse. Required by controller-gen. +func (in *GetTracesResponse) DeepCopy() *GetTracesResponse { + if in == nil { + return nil + } + out := new(GetTracesResponse) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GetTracesResponse. Required by controller-gen. +func (in *GetTracesResponse) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using GetTraceRequest within kubernetes types, where deepcopy-gen is used. +func (in *GetTraceRequest) DeepCopyInto(out *GetTraceRequest) { + p := proto.Clone(in).(*GetTraceRequest) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GetTraceRequest. Required by controller-gen. +func (in *GetTraceRequest) DeepCopy() *GetTraceRequest { + if in == nil { + return nil + } + out := new(GetTraceRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GetTraceRequest. Required by controller-gen. +func (in *GetTraceRequest) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using GetTraceResponse within kubernetes types, where deepcopy-gen is used. +func (in *GetTraceResponse) DeepCopyInto(out *GetTraceResponse) { + p := proto.Clone(in).(*GetTraceResponse) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GetTraceResponse. Required by controller-gen. +func (in *GetTraceResponse) DeepCopy() *GetTraceResponse { + if in == nil { + return nil + } + out := new(GetTraceResponse) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new GetTraceResponse. Required by controller-gen. +func (in *GetTraceResponse) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using Operation within kubernetes types, where deepcopy-gen is used. +func (in *Operation) DeepCopyInto(out *Operation) { + p := proto.Clone(in).(*Operation) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Operation. Required by controller-gen. +func (in *Operation) DeepCopy() *Operation { + if in == nil { + return nil + } + out := new(Operation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Operation. Required by controller-gen. +func (in *Operation) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using Spec within kubernetes types, where deepcopy-gen is used. +func (in *Spec) DeepCopyInto(out *Spec) { + p := proto.Clone(in).(*Spec) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec. Required by controller-gen. +func (in *Spec) DeepCopy() *Spec { + if in == nil { + return nil + } + out := new(Spec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Spec. Required by controller-gen. +func (in *Spec) DeepCopyInterface() interface{} { + return in.DeepCopy() +} + +// DeepCopyInto supports using Query within kubernetes types, where deepcopy-gen is used. +func (in *Query) DeepCopyInto(out *Query) { + p := proto.Clone(in).(*Query) + *out = *p +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Query. Required by controller-gen. +func (in *Query) DeepCopy() *Query { + if in == nil { + return nil + } + out := new(Query) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInterface is an autogenerated deepcopy function, copying the receiver, creating a new Query. Required by controller-gen. +func (in *Query) DeepCopyInterface() interface{} { + return in.DeepCopy() +} diff --git a/pkg/api/plugins/jaeger/proto/jaeger_grpc.pb.go b/pkg/api/plugins/jaeger/proto/jaeger_grpc.pb.go new file mode 100644 index 000000000..55e9b1b18 --- /dev/null +++ b/pkg/api/plugins/jaeger/proto/jaeger_grpc.pb.go @@ -0,0 +1,173 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. + +package proto + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// JaegerClient is the client API for Jaeger service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type JaegerClient interface { + GetOperations(ctx context.Context, in *GetOperationsRequest, opts ...grpc.CallOption) (*GetOperationsResponse, error) + GetTraces(ctx context.Context, in *GetTracesRequest, opts ...grpc.CallOption) (*GetTracesResponse, error) + GetTrace(ctx context.Context, in *GetTraceRequest, opts ...grpc.CallOption) (*GetTraceResponse, error) +} + +type jaegerClient struct { + cc grpc.ClientConnInterface +} + +func NewJaegerClient(cc grpc.ClientConnInterface) JaegerClient { + return &jaegerClient{cc} +} + +func (c *jaegerClient) GetOperations(ctx context.Context, in *GetOperationsRequest, opts ...grpc.CallOption) (*GetOperationsResponse, error) { + out := new(GetOperationsResponse) + err := c.cc.Invoke(ctx, "/plugins.jaeger.Jaeger/GetOperations", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *jaegerClient) GetTraces(ctx context.Context, in *GetTracesRequest, opts ...grpc.CallOption) (*GetTracesResponse, error) { + out := new(GetTracesResponse) + err := c.cc.Invoke(ctx, "/plugins.jaeger.Jaeger/GetTraces", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *jaegerClient) GetTrace(ctx context.Context, in *GetTraceRequest, opts ...grpc.CallOption) (*GetTraceResponse, error) { + out := new(GetTraceResponse) + err := c.cc.Invoke(ctx, "/plugins.jaeger.Jaeger/GetTrace", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// JaegerServer is the server API for Jaeger service. +// All implementations must embed UnimplementedJaegerServer +// for forward compatibility +type JaegerServer interface { + GetOperations(context.Context, *GetOperationsRequest) (*GetOperationsResponse, error) + GetTraces(context.Context, *GetTracesRequest) (*GetTracesResponse, error) + GetTrace(context.Context, *GetTraceRequest) (*GetTraceResponse, error) + mustEmbedUnimplementedJaegerServer() +} + +// UnimplementedJaegerServer must be embedded to have forward compatible implementations. +type UnimplementedJaegerServer struct { +} + +func (UnimplementedJaegerServer) GetOperations(context.Context, *GetOperationsRequest) (*GetOperationsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetOperations not implemented") +} +func (UnimplementedJaegerServer) GetTraces(context.Context, *GetTracesRequest) (*GetTracesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetTraces not implemented") +} +func (UnimplementedJaegerServer) GetTrace(context.Context, *GetTraceRequest) (*GetTraceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetTrace not implemented") +} +func (UnimplementedJaegerServer) mustEmbedUnimplementedJaegerServer() {} + +// UnsafeJaegerServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to JaegerServer will +// result in compilation errors. +type UnsafeJaegerServer interface { + mustEmbedUnimplementedJaegerServer() +} + +func RegisterJaegerServer(s grpc.ServiceRegistrar, srv JaegerServer) { + s.RegisterService(&Jaeger_ServiceDesc, srv) +} + +func _Jaeger_GetOperations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetOperationsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(JaegerServer).GetOperations(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/plugins.jaeger.Jaeger/GetOperations", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(JaegerServer).GetOperations(ctx, req.(*GetOperationsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Jaeger_GetTraces_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTracesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(JaegerServer).GetTraces(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/plugins.jaeger.Jaeger/GetTraces", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(JaegerServer).GetTraces(ctx, req.(*GetTracesRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _Jaeger_GetTrace_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTraceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(JaegerServer).GetTrace(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/plugins.jaeger.Jaeger/GetTrace", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(JaegerServer).GetTrace(ctx, req.(*GetTraceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Jaeger_ServiceDesc is the grpc.ServiceDesc for Jaeger service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Jaeger_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "plugins.jaeger.Jaeger", + HandlerType: (*JaegerServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetOperations", + Handler: _Jaeger_GetOperations_Handler, + }, + { + MethodName: "GetTraces", + Handler: _Jaeger_GetTraces_Handler, + }, + { + MethodName: "GetTrace", + Handler: _Jaeger_GetTrace_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "jaeger.proto", +} diff --git a/pkg/api/plugins/plugins/plugins.go b/pkg/api/plugins/plugins/plugins.go index 374c5aff8..56f30e89f 100644 --- a/pkg/api/plugins/plugins/plugins.go +++ b/pkg/api/plugins/plugins/plugins.go @@ -6,6 +6,7 @@ import ( "github.com/kobsio/kobs/pkg/api/plugins/clusters" clustersProto "github.com/kobsio/kobs/pkg/api/plugins/clusters/proto" "github.com/kobsio/kobs/pkg/api/plugins/elasticsearch" + "github.com/kobsio/kobs/pkg/api/plugins/jaeger" pluginsProto "github.com/kobsio/kobs/pkg/api/plugins/plugins/proto" "github.com/kobsio/kobs/pkg/api/plugins/prometheus" "github.com/kobsio/kobs/pkg/config" @@ -62,9 +63,16 @@ func Register(cfg *config.Config, grpcServer *grpc.Server) error { return err } + jaegerInstances, err := jaeger.Register(cfg.Jaeger, grpcServer) + if err != nil { + log.WithError(err).WithFields(logrus.Fields{"plugin": "jaeger"}).Errorf("Failed to register Jaeger plugin.") + return err + } + var plugins []*pluginsProto.PluginShort plugins = append(plugins, prometheusInstances...) plugins = append(plugins, elasticsearchInstances...) + plugins = append(plugins, jaegerInstances...) pluginsProto.RegisterPluginsServer(grpcServer, &Plugins{ plugins: plugins, diff --git a/pkg/api/plugins/plugins/proto/plugins.pb.go b/pkg/api/plugins/plugins/proto/plugins.pb.go index b9a88a19b..6d9bd4528 100644 --- a/pkg/api/plugins/plugins/proto/plugins.pb.go +++ b/pkg/api/plugins/plugins/proto/plugins.pb.go @@ -9,6 +9,7 @@ package proto import ( proto "github.com/golang/protobuf/proto" proto2 "github.com/kobsio/kobs/pkg/api/plugins/elasticsearch/proto" + proto3 "github.com/kobsio/kobs/pkg/api/plugins/jaeger/proto" proto1 "github.com/kobsio/kobs/pkg/api/plugins/prometheus/proto" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" @@ -191,6 +192,7 @@ type Plugin struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Prometheus *proto1.Spec `protobuf:"bytes,2,opt,name=prometheus,proto3" json:"prometheus,omitempty"` Elasticsearch *proto2.Spec `protobuf:"bytes,3,opt,name=elasticsearch,proto3" json:"elasticsearch,omitempty"` + Jaeger *proto3.Spec `protobuf:"bytes,4,opt,name=jaeger,proto3" json:"jaeger,omitempty"` } func (x *Plugin) Reset() { @@ -246,44 +248,54 @@ func (x *Plugin) GetElasticsearch() *proto2.Spec { return nil } +func (x *Plugin) GetJaeger() *proto3.Spec { + if x != nil { + return x.Jaeger + } + return nil +} + var File_plugins_proto protoreflect.FileDescriptor var file_plugins_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x1a, 0x10, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x13, 0x65, 0x6c, 0x61, 0x73, - 0x74, 0x69, 0x63, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0x13, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x22, 0x44, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x70, 0x6c, - 0x75, 0x67, 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6c, - 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x53, 0x68, 0x6f, 0x72, - 0x74, 0x52, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x22, 0x57, 0x0a, 0x0b, 0x50, 0x6c, - 0x75, 0x67, 0x69, 0x6e, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x22, 0x99, 0x01, 0x0a, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, - 0x2e, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x53, 0x70, 0x65, 0x63, - 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x12, 0x41, 0x0a, 0x0d, - 0x65, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x65, 0x6c, - 0x61, 0x73, 0x74, 0x69, 0x63, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x53, 0x70, 0x65, 0x63, - 0x52, 0x0d, 0x65, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x32, - 0x52, 0x0a, 0x07, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x47, 0x65, - 0x74, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x12, 0x1a, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, - 0x6e, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x47, - 0x65, 0x74, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, - 0x6d, 0x2f, 0x6b, 0x6f, 0x62, 0x73, 0x69, 0x6f, 0x2f, 0x6b, 0x6f, 0x62, 0x73, 0x2f, 0x70, 0x6b, - 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2f, 0x70, 0x6c, - 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x74, 0x69, 0x63, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x0c, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x13, 0x0a, + 0x11, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x22, 0x44, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x73, 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x52, + 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x22, 0x57, 0x0a, 0x0b, 0x50, 0x6c, 0x75, 0x67, + 0x69, 0x6e, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x22, 0xc7, 0x01, 0x0a, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x38, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x2e, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0a, + 0x70, 0x72, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x65, 0x75, 0x73, 0x12, 0x41, 0x0a, 0x0d, 0x65, 0x6c, + 0x61, 0x73, 0x74, 0x69, 0x63, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x65, 0x6c, 0x61, 0x73, + 0x74, 0x69, 0x63, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x53, 0x70, 0x65, 0x63, 0x52, 0x0d, + 0x65, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x2c, 0x0a, + 0x06, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x2e, 0x53, + 0x70, 0x65, 0x63, 0x52, 0x06, 0x6a, 0x61, 0x65, 0x67, 0x65, 0x72, 0x32, 0x52, 0x0a, 0x07, 0x50, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x12, 0x47, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x75, + 0x67, 0x69, 0x6e, 0x73, 0x12, 0x1a, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x47, + 0x65, 0x74, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1b, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, + 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x6f, + 0x62, 0x73, 0x69, 0x6f, 0x2f, 0x6b, 0x6f, 0x62, 0x73, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, + 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -306,18 +318,20 @@ var file_plugins_proto_goTypes = []interface{}{ (*Plugin)(nil), // 3: plugins.Plugin (*proto1.Spec)(nil), // 4: plugins.prometheus.Spec (*proto2.Spec)(nil), // 5: plugins.elasticsearch.Spec + (*proto3.Spec)(nil), // 6: plugins.jaeger.Spec } var file_plugins_proto_depIdxs = []int32{ 2, // 0: plugins.GetPluginsResponse.plugins:type_name -> plugins.PluginShort 4, // 1: plugins.Plugin.prometheus:type_name -> plugins.prometheus.Spec 5, // 2: plugins.Plugin.elasticsearch:type_name -> plugins.elasticsearch.Spec - 0, // 3: plugins.Plugins.GetPlugins:input_type -> plugins.GetPluginsRequest - 1, // 4: plugins.Plugins.GetPlugins:output_type -> plugins.GetPluginsResponse - 4, // [4:5] is the sub-list for method output_type - 3, // [3:4] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 6, // 3: plugins.Plugin.jaeger:type_name -> plugins.jaeger.Spec + 0, // 4: plugins.Plugins.GetPlugins:input_type -> plugins.GetPluginsRequest + 1, // 5: plugins.Plugins.GetPlugins:output_type -> plugins.GetPluginsResponse + 5, // [5:6] is the sub-list for method output_type + 4, // [4:5] is the sub-list for method input_type + 4, // [4:4] is the sub-list for extension type_name + 4, // [4:4] is the sub-list for extension extendee + 0, // [0:4] is the sub-list for field type_name } func init() { file_plugins_proto_init() } diff --git a/pkg/api/plugins/plugins/proto/plugins_deepcopy.gen.go b/pkg/api/plugins/plugins/proto/plugins_deepcopy.gen.go index 5fe4d16a4..22aaf71a6 100644 --- a/pkg/api/plugins/plugins/proto/plugins_deepcopy.gen.go +++ b/pkg/api/plugins/plugins/proto/plugins_deepcopy.gen.go @@ -7,6 +7,7 @@ import ( fmt "fmt" proto "github.com/gogo/protobuf/proto" _ "github.com/kobsio/kobs/pkg/api/plugins/elasticsearch/proto" + _ "github.com/kobsio/kobs/pkg/api/plugins/jaeger/proto" _ "github.com/kobsio/kobs/pkg/api/plugins/prometheus/proto" math "math" ) diff --git a/pkg/config/config.go b/pkg/config/config.go index da8a82b72..76078b924 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -6,6 +6,7 @@ import ( "github.com/kobsio/kobs/pkg/api/plugins/clusters" "github.com/kobsio/kobs/pkg/api/plugins/elasticsearch" + "github.com/kobsio/kobs/pkg/api/plugins/jaeger" "github.com/kobsio/kobs/pkg/api/plugins/prometheus" "gopkg.in/yaml.v2" @@ -16,6 +17,7 @@ type Config struct { Clusters clusters.Config `yaml:"clusters"` Prometheus []prometheus.Config `yaml:"prometheus"` Elasticsearch []elasticsearch.Config `yaml:"elasticsearch"` + Jaeger []jaeger.Config `yaml:"jaeger"` } // Load the configuration for kobs. Most of the configuration options are available as command-line flag, but we also diff --git a/proto/jaeger.proto b/proto/jaeger.proto new file mode 100644 index 000000000..913bd8a3c --- /dev/null +++ b/proto/jaeger.proto @@ -0,0 +1,62 @@ +syntax = "proto3"; +package plugins.jaeger; + +option go_package = "github.com/kobsio/kobs/pkg/api/plugins/jaeger/proto"; + +// Jaeger is the service to get traces from a configured Jaeger instance. +service Jaeger { + rpc GetOperations(GetOperationsRequest) returns (GetOperationsResponse) {} + rpc GetTraces(GetTracesRequest) returns (GetTracesResponse) {} + rpc GetTrace(GetTraceRequest) returns (GetTraceResponse) {} +} + +message GetOperationsRequest { + string name = 1; + string service = 2; +} + +message GetOperationsResponse { + repeated string services = 1; + repeated Operation operations = 2; +} + +message GetTracesRequest { + string name = 1; + string limit = 2; + string maxDuration = 3; + string minDuration = 4; + string service = 5; + string operation = 6; + string tags = 7; + int64 timeStart = 8; + int64 timeEnd = 9; +} + +message GetTracesResponse { + string traces = 1; +} + +message GetTraceRequest { + string name = 1; + string traceID = 2; +} + +message GetTraceResponse { + string traces = 1; +} + +message Operation { + string name = 1; + string spanKind = 2; +} + +message Spec { + repeated Query queries = 1; +} + +message Query { + string name = 1; + string service = 2; + string operation = 3; + string tags = 4; +} diff --git a/proto/plugins.proto b/proto/plugins.proto index c2e02829e..fc3dc908b 100644 --- a/proto/plugins.proto +++ b/proto/plugins.proto @@ -5,6 +5,7 @@ option go_package = "github.com/kobsio/kobs/pkg/api/plugins/plugins/proto"; import "prometheus.proto"; import "elasticsearch.proto"; +import "jaeger.proto"; // Plugins is the service to get all configured and loaded plugins. service Plugins { @@ -35,4 +36,5 @@ message Plugin { string name = 1; prometheus.Spec prometheus = 2; elasticsearch.Spec elasticsearch = 3; + jaeger.Spec jaeger = 4; }