fix: address review comments
Signed-off-by: Isaiah Thiessen <isaiah.thiessen@telus.com>
This commit is contained in:
@@ -29,7 +29,7 @@
|
||||
"@backstage/plugin-cloudbuild": "^0.3.6-next.1",
|
||||
"@backstage/plugin-code-coverage": "^0.1.33-next.1",
|
||||
"@backstage/plugin-cost-insights": "^0.11.28-next.1",
|
||||
"@backstage/plugin-dynatrace": "^0.1.0",
|
||||
"@backstage/plugin-dynatrace": "^0.0.0",
|
||||
"@backstage/plugin-explore": "^0.3.37-next.1",
|
||||
"@backstage/plugin-gcalendar": "^0.3.2-next.1",
|
||||
"@backstage/plugin-gcp-projects": "^0.3.25-next.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@backstage/plugin-dynatrace",
|
||||
"version": "0.1.0",
|
||||
"version": "0.0.0",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -23,7 +23,7 @@ export type DynatraceEntity = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type Problem = {
|
||||
export type DynatraceProblem = {
|
||||
problemId: string;
|
||||
impactLevel: string;
|
||||
status: string;
|
||||
@@ -35,8 +35,8 @@ export type Problem = {
|
||||
affectedEntities: Array<DynatraceEntity>;
|
||||
};
|
||||
|
||||
export interface Problems {
|
||||
problems: Array<Problem>;
|
||||
export interface DynatraceProblems {
|
||||
problems: Array<DynatraceProblem>;
|
||||
}
|
||||
|
||||
export const dynatraceApiRef = createApiRef<DynatraceApi>({
|
||||
@@ -44,5 +44,7 @@ export const dynatraceApiRef = createApiRef<DynatraceApi>({
|
||||
});
|
||||
|
||||
export type DynatraceApi = {
|
||||
getProblems(dynatraceEntityId: string): Promise<Problems | undefined>;
|
||||
getDynatraceProblems(
|
||||
dynatraceEntityId: string,
|
||||
): Promise<DynatraceProblems | undefined>;
|
||||
};
|
||||
|
||||
@@ -13,23 +13,30 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import fetch from 'cross-fetch';
|
||||
import { Problems, DynatraceApi } from './DynatraceApi';
|
||||
import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';
|
||||
import { DynatraceProblems, DynatraceApi } from './DynatraceApi';
|
||||
import {
|
||||
DiscoveryApi,
|
||||
IdentityApi,
|
||||
FetchApi,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
export class DynatraceClient implements DynatraceApi {
|
||||
discoveryApi: DiscoveryApi;
|
||||
identityApi: IdentityApi;
|
||||
fetchApi: FetchApi;
|
||||
|
||||
constructor({
|
||||
discoveryApi,
|
||||
identityApi,
|
||||
fetchApi,
|
||||
}: {
|
||||
discoveryApi: DiscoveryApi;
|
||||
identityApi: IdentityApi;
|
||||
fetchApi: FetchApi;
|
||||
}) {
|
||||
this.discoveryApi = discoveryApi;
|
||||
this.identityApi = identityApi;
|
||||
this.fetchApi = fetchApi;
|
||||
}
|
||||
|
||||
private async callApi<T>(
|
||||
@@ -39,7 +46,7 @@ export class DynatraceClient implements DynatraceApi {
|
||||
const { token: idToken } = await this.identityApi.getCredentials();
|
||||
|
||||
const apiUrl = `${await this.discoveryApi.getBaseUrl('proxy')}/dynatrace`;
|
||||
const response = await fetch(
|
||||
const response = await this.fetchApi.fetch(
|
||||
`${apiUrl}/${path}?${new URLSearchParams(query).toString()}`,
|
||||
{
|
||||
headers: {
|
||||
@@ -54,7 +61,9 @@ export class DynatraceClient implements DynatraceApi {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async getProblems(dynatraceEntityId: string): Promise<Problems | undefined> {
|
||||
async getDynatraceProblems(
|
||||
dynatraceEntityId: string,
|
||||
): Promise<DynatraceProblems | undefined> {
|
||||
if (!dynatraceEntityId) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export type { Problems, Problem, DynatraceEntity } from './DynatraceApi';
|
||||
export type {
|
||||
DynatraceProblems,
|
||||
DynatraceProblem,
|
||||
DynatraceEntity,
|
||||
} from './DynatraceApi';
|
||||
export { dynatraceApiRef } from './DynatraceApi';
|
||||
export { DynatraceClient } from './DynatraceClient';
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { Problem } from '../../../api/DynatraceApi';
|
||||
import { DynatraceProblem } from '../../../api/DynatraceApi';
|
||||
import { StatusError, StatusOK } from '@backstage/core-components';
|
||||
|
||||
export const ProblemStatus = ({ status }: Partial<Problem>) => {
|
||||
export const ProblemStatus = ({ status }: Partial<DynatraceProblem>) => {
|
||||
switch (status?.toLocaleLowerCase()) {
|
||||
case 'open':
|
||||
return (
|
||||
|
||||
@@ -22,7 +22,7 @@ import { ApiProvider, ConfigReader } from '@backstage/core-app-api';
|
||||
import { configApiRef } from '@backstage/core-plugin-api';
|
||||
|
||||
const mockDynatraceApi = {
|
||||
getProblems: jest.fn(),
|
||||
getDynatraceProblems: jest.fn(),
|
||||
};
|
||||
const apis = TestApiRegistry.from(
|
||||
[dynatraceApiRef, mockDynatraceApi],
|
||||
@@ -31,7 +31,9 @@ const apis = TestApiRegistry.from(
|
||||
|
||||
describe('ProblemStatus', () => {
|
||||
it('renders a table with problem data', async () => {
|
||||
mockDynatraceApi.getProblems = jest.fn().mockResolvedValue({ problems });
|
||||
mockDynatraceApi.getDynatraceProblems = jest
|
||||
.fn()
|
||||
.mockResolvedValue({ problems });
|
||||
const rendered = await renderInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<ProblemsList dynatraceEntityId="example-service-3" />
|
||||
@@ -40,7 +42,7 @@ describe('ProblemStatus', () => {
|
||||
expect(await rendered.findByText('example-service')).toBeInTheDocument();
|
||||
});
|
||||
it('renders "nothing to report :)" if no problems are found', async () => {
|
||||
mockDynatraceApi.getProblems = jest.fn().mockResolvedValue({});
|
||||
mockDynatraceApi.getDynatraceProblems = jest.fn().mockResolvedValue({});
|
||||
const rendered = await renderInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<ProblemsList dynatraceEntityId="example-service-3" />
|
||||
|
||||
@@ -29,8 +29,7 @@ export const ProblemsList = (props: ProblemsListProps) => {
|
||||
const { dynatraceEntityId } = props;
|
||||
const dynatraceApi = useApi(dynatraceApiRef);
|
||||
const { value, loading, error } = useAsync(async () => {
|
||||
const r = await dynatraceApi.getProblems(dynatraceEntityId);
|
||||
return r;
|
||||
return dynatraceApi.getDynatraceProblems(dynatraceEntityId);
|
||||
}, [dynatraceApi, dynatraceEntityId]);
|
||||
const problems = value?.problems;
|
||||
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import { Table, TableColumn } from '@backstage/core-components';
|
||||
import { Problem } from '../../../api/DynatraceApi';
|
||||
import { DynatraceProblem } from '../../../api/DynatraceApi';
|
||||
import { ProblemStatus } from '../ProblemStatus';
|
||||
import { configApiRef } from '@backstage/core-plugin-api';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import { Link } from '@material-ui/core';
|
||||
|
||||
type ProblemsTableProps = {
|
||||
problems: Problem[];
|
||||
problems: DynatraceProblem[];
|
||||
};
|
||||
|
||||
export const ProblemsTable = ({ problems }: ProblemsTableProps) => {
|
||||
@@ -32,7 +32,7 @@ export const ProblemsTable = ({ problems }: ProblemsTableProps) => {
|
||||
{
|
||||
title: 'Title',
|
||||
field: 'title',
|
||||
render: (row: Partial<Problem>) => (
|
||||
render: (row: Partial<DynatraceProblem>) => (
|
||||
<Link
|
||||
href={`${dynatraceBaseUrl}/#problems/problemdetails;pid=${row.problemId}`}
|
||||
>
|
||||
@@ -43,29 +43,32 @@ export const ProblemsTable = ({ problems }: ProblemsTableProps) => {
|
||||
{
|
||||
title: 'Status',
|
||||
field: 'status',
|
||||
render: (row: Partial<Problem>) => <ProblemStatus status={row.status} />,
|
||||
render: (row: Partial<DynatraceProblem>) => (
|
||||
<ProblemStatus status={row.status} />
|
||||
),
|
||||
},
|
||||
{ title: 'Severity', field: 'severityLevel' },
|
||||
{
|
||||
title: 'Root Cause',
|
||||
field: 'rootCauseEntity',
|
||||
render: (row: Partial<Problem>) => row.rootCauseEntity?.name,
|
||||
render: (row: Partial<DynatraceProblem>) => row.rootCauseEntity?.name,
|
||||
},
|
||||
{
|
||||
title: 'Affected',
|
||||
field: 'affectedEntities',
|
||||
render: (row: Partial<Problem>) => row.affectedEntities?.map(e => e.name),
|
||||
render: (row: Partial<DynatraceProblem>) =>
|
||||
row.affectedEntities?.map(e => e.name),
|
||||
},
|
||||
{
|
||||
title: 'Start Time',
|
||||
field: 'startTime',
|
||||
render: (row: Partial<Problem>) =>
|
||||
render: (row: Partial<DynatraceProblem>) =>
|
||||
new Date(row.startTime || 0).toString(),
|
||||
},
|
||||
{
|
||||
title: 'End Time',
|
||||
field: 'endTime',
|
||||
render: (row: Partial<Problem>) =>
|
||||
render: (row: Partial<DynatraceProblem>) =>
|
||||
row.endTime === -1 ? 'ongoing' : new Date(row.endTime || 0).toString(),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
createPlugin,
|
||||
discoveryApiRef,
|
||||
identityApiRef,
|
||||
fetchApiRef,
|
||||
createRoutableExtension,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
@@ -38,11 +39,13 @@ export const dynatracePlugin = createPlugin({
|
||||
deps: {
|
||||
discoveryApi: discoveryApiRef,
|
||||
identityApi: identityApiRef,
|
||||
fetchApi: fetchApiRef,
|
||||
},
|
||||
factory: ({ discoveryApi, identityApi }) =>
|
||||
factory: ({ discoveryApi, identityApi, fetchApi }) =>
|
||||
new DynatraceClient({
|
||||
discoveryApi,
|
||||
identityApi,
|
||||
fetchApi,
|
||||
}),
|
||||
}),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user