Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix loading of Jaeger services #14

Merged
merged 1 commit into from
Mar 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ NOTE: As semantic versioning states all 0.y.z releases can contain breaking chan

- [#1](https://github.com/kobsio/kobs/pull/1): Fix mobile layout for the cluster and namespace filter by using a Toolbar instead of FlexItems.
- [#9](https://github.com/kobsio/kobs/pull/9): Fix time parsing for the datasource options.
- [#14](https://github.com/kobsio/kobs/pull/14): Fix loading of Jaeger services, when a user opend the Jaeger plugin, where the `service` query parameter was already present.

### Changed

Expand Down
64 changes: 46 additions & 18 deletions app/src/plugins/jaeger/JaegerPageToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ 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 {
GetOperationsRequest,
GetOperationsResponse,
GetServicesRequest,
GetServicesResponse,
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';
Expand Down Expand Up @@ -82,23 +88,36 @@ const JaegerPageToolbar: React.FunctionComponent<IJaegerPageToolbarProps> = ({
}
};

// fetchOperations is used to retrieve the operations for the given service or if no service is specified also a list
// of services.
// fetchServices is used to retrieve the services from Jaeger.
const fetchServices = useCallback(async (): Promise<void> => {
try {
const getServicesRequest = new GetServicesRequest();
getServicesRequest.setName(name);

const getServicesResponse: GetServicesResponse = await jaegerService.getServices(getServicesRequest, null);
const { servicesList } = getServicesResponse.toObject();

setData({ error: '', operations: [], services: servicesList });
} catch (err) {
setData({ error: err.message, operations: [], services: [] });
}
}, [name]);

// fetchOperations is used to retrieve the operations for the given service. We only can fetch the operations, when a
// user has selected an service.
const fetchOperations = useCallback(async (): Promise<void> => {
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 {
if (options.service !== '') {
const getOperationsRequest = new GetOperationsRequest();
getOperationsRequest.setName(name);
getOperationsRequest.setService(options.service);

const getOperationsResponse: GetOperationsResponse = await jaegerService.getOperations(
getOperationsRequest,
null,
);
const { operationsList } = getOperationsResponse.toObject();

setData((d) => {
return { ...d, error: '', operations: operationsList.map((operation) => operation.name) };
});
Expand All @@ -108,7 +127,12 @@ const JaegerPageToolbar: React.FunctionComponent<IJaegerPageToolbarProps> = ({
}
}, [name, options.service]);

// useEffect is used to call the fetchOperations function everytime the Jaeger the service is changed are changed.
// useEffect is used to call the fetchServices function.
useEffect(() => {
fetchServices();
}, [fetchServices]);

// useEffect is used to call the fetchOperations function everytime the Jaeger service is changed are changed.
useEffect(() => {
fetchOperations();
}, [fetchOperations]);
Expand Down Expand Up @@ -137,6 +161,7 @@ const JaegerPageToolbar: React.FunctionComponent<IJaegerPageToolbarProps> = ({
<ToolbarGroup style={{ width: '100%' }}>
<ToolbarItem style={{ width: '100%' }}>
<JaegerPageToolbarSelect
isOperations={false}
placeholder="Select service"
items={data.services}
selectedItem={options.service}
Expand All @@ -145,10 +170,13 @@ const JaegerPageToolbar: React.FunctionComponent<IJaegerPageToolbarProps> = ({
</ToolbarItem>
<ToolbarItem style={{ width: '100%' }}>
<JaegerPageToolbarSelect
isOperations={true}
placeholder="Select operation"
items={data.operations}
selectedItem={options.operation}
selectItem={(item: string): void => setOptions({ ...options, operation: item })}
selectItem={(item: string): void =>
setOptions({ ...options, operation: item === 'All Operations' ? '' : item })
}
/>
</ToolbarItem>
<ToolbarItem variant="label">Tags</ToolbarItem>
Expand Down
21 changes: 16 additions & 5 deletions app/src/plugins/jaeger/JaegerPageToolbarSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@ import React, { useState } from 'react';
import { Select, SelectOption, SelectOptionObject, SelectVariant } from '@patternfly/react-core';

interface IJaegerPageToolbarSelectProps {
isOperations: boolean;
placeholder: string;
items: string[];
selectedItem: string;
selectItem: (item: string) => void;
}

// JaegerPageToolbarSelect provides a select box for the services and operations for Jaeger.
// JaegerPageToolbarSelect provides a select box for the services and operations for Jaeger. The "isOperations" value is
// needed to provide a special handling, when the user doesn't want to specify an operation, but has selected one
// already. For that we have the special 'All Operations' handling, which is only used within this component. If the
// user selects this item, the selectItem function in the parent component will ignore it.
const JaegerPageToolbarSelect: React.FunctionComponent<IJaegerPageToolbarSelectProps> = ({
isOperations,
placeholder,
items,
selectedItem,
Expand All @@ -27,19 +32,25 @@ const JaegerPageToolbarSelect: React.FunctionComponent<IJaegerPageToolbarSelectP
setShow(false);
};

const options =
isOperations && items.length > 0
? [
<SelectOption key={-1} value="All Operations" />,
...items.map((item, index) => <SelectOption key={index} value={item} />),
]
: items.map((item, index) => <SelectOption key={index} value={item} />);

return (
<Select
variant={SelectVariant.single}
typeAheadAriaLabel={placeholder}
placeholderText={placeholder}
onToggle={(): void => setShow(!show)}
onSelect={changeItem}
selections={selectedItem}
selections={isOperations && selectedItem === '' && items.length > 0 ? 'All Operations' : selectedItem}
isOpen={show}
>
{items.map((item, index) => (
<SelectOption key={index} value={item} />
))}
{options}
</Select>
);
};
Expand Down
2 changes: 1 addition & 1 deletion app/src/plugins/jaeger/JaegerSpanLogs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const JaegerSpanLogs: React.FunctionComponent<IJaegerSpanLogsProps> = ({ logs }:
isExpanded={expanded.includes(`logs-accordion-${index}`)}
id={`resources-toggle-${index}`}
>
{formatTraceTime(log.timestamp)} ()
{formatTraceTime(log.timestamp)}
</AccordionToggle>
<AccordionContent
id={`resources-content-${index}`}
Expand Down
80 changes: 80 additions & 0 deletions app/src/proto/jaeger_grpc_web_pb.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,86 @@ proto.plugins.jaeger.JaegerPromiseClient =
};


/**
* @const
* @type {!grpc.web.MethodDescriptor<
* !proto.plugins.jaeger.GetServicesRequest,
* !proto.plugins.jaeger.GetServicesResponse>}
*/
const methodDescriptor_Jaeger_GetServices = new grpc.web.MethodDescriptor(
'/plugins.jaeger.Jaeger/GetServices',
grpc.web.MethodType.UNARY,
proto.plugins.jaeger.GetServicesRequest,
proto.plugins.jaeger.GetServicesResponse,
/**
* @param {!proto.plugins.jaeger.GetServicesRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.plugins.jaeger.GetServicesResponse.deserializeBinary
);


/**
* @const
* @type {!grpc.web.AbstractClientBase.MethodInfo<
* !proto.plugins.jaeger.GetServicesRequest,
* !proto.plugins.jaeger.GetServicesResponse>}
*/
const methodInfo_Jaeger_GetServices = new grpc.web.AbstractClientBase.MethodInfo(
proto.plugins.jaeger.GetServicesResponse,
/**
* @param {!proto.plugins.jaeger.GetServicesRequest} request
* @return {!Uint8Array}
*/
function(request) {
return request.serializeBinary();
},
proto.plugins.jaeger.GetServicesResponse.deserializeBinary
);


/**
* @param {!proto.plugins.jaeger.GetServicesRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @param {function(?grpc.web.Error, ?proto.plugins.jaeger.GetServicesResponse)}
* callback The callback function(error, response)
* @return {!grpc.web.ClientReadableStream<!proto.plugins.jaeger.GetServicesResponse>|undefined}
* The XHR Node Readable Stream
*/
proto.plugins.jaeger.JaegerClient.prototype.getServices =
function(request, metadata, callback) {
return this.client_.rpcCall(this.hostname_ +
'/plugins.jaeger.Jaeger/GetServices',
request,
metadata || {},
methodDescriptor_Jaeger_GetServices,
callback);
};


/**
* @param {!proto.plugins.jaeger.GetServicesRequest} request The
* request proto
* @param {?Object<string, string>} metadata User defined
* call metadata
* @return {!Promise<!proto.plugins.jaeger.GetServicesResponse>}
* Promise that resolves to the response
*/
proto.plugins.jaeger.JaegerPromiseClient.prototype.getServices =
function(request, metadata) {
return this.client_.unaryCall(this.hostname_ +
'/plugins.jaeger.Jaeger/GetServices',
request,
metadata || {},
methodDescriptor_Jaeger_GetServices);
};


/**
* @const
* @type {!grpc.web.MethodDescriptor<
Expand Down
48 changes: 42 additions & 6 deletions app/src/proto/jaeger_pb.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,48 @@

import * as jspb from "google-protobuf";

export class GetServicesRequest extends jspb.Message {
getName(): string;
setName(value: string): void;

serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetServicesRequest.AsObject;
static toObject(includeInstance: boolean, msg: GetServicesRequest): GetServicesRequest.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: GetServicesRequest, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetServicesRequest;
static deserializeBinaryFromReader(message: GetServicesRequest, reader: jspb.BinaryReader): GetServicesRequest;
}

export namespace GetServicesRequest {
export type AsObject = {
name: string,
}
}

export class GetServicesResponse extends jspb.Message {
clearServicesList(): void;
getServicesList(): Array<string>;
setServicesList(value: Array<string>): void;
addServices(value: string, index?: number): string;

serializeBinary(): Uint8Array;
toObject(includeInstance?: boolean): GetServicesResponse.AsObject;
static toObject(includeInstance: boolean, msg: GetServicesResponse): GetServicesResponse.AsObject;
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
static serializeBinaryToWriter(message: GetServicesResponse, writer: jspb.BinaryWriter): void;
static deserializeBinary(bytes: Uint8Array): GetServicesResponse;
static deserializeBinaryFromReader(message: GetServicesResponse, reader: jspb.BinaryReader): GetServicesResponse;
}

export namespace GetServicesResponse {
export type AsObject = {
servicesList: Array<string>,
}
}

export class GetOperationsRequest extends jspb.Message {
getName(): string;
setName(value: string): void;
Expand All @@ -28,11 +70,6 @@ export namespace GetOperationsRequest {
}

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;
Expand All @@ -50,7 +87,6 @@ export class GetOperationsResponse extends jspb.Message {

export namespace GetOperationsResponse {
export type AsObject = {
servicesList: Array<string>,
operationsList: Array<Operation.AsObject>,
}
}
Expand Down
Loading