Merge pull request #11754 from isand3r/master
feat: add dynatrace plugin
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-dynatrace': minor
|
||||
---
|
||||
|
||||
Adds Dynatrace plugin
|
||||
@@ -85,6 +85,8 @@ dockerfiles
|
||||
Dockerize
|
||||
dockerode
|
||||
Docusaurus
|
||||
dynatrace
|
||||
Dynatrace
|
||||
ecco
|
||||
env
|
||||
Env
|
||||
|
||||
@@ -115,6 +115,11 @@ proxy:
|
||||
headers:
|
||||
Authorization: Basic ${GOCD_AUTH_CREDENTIALS}
|
||||
|
||||
'/dynatrace':
|
||||
target: https://your.dynatrace.instance.com/api/v2
|
||||
headers:
|
||||
Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}'
|
||||
|
||||
organization:
|
||||
name: My Company
|
||||
|
||||
@@ -131,6 +136,9 @@ techdocs:
|
||||
publisher:
|
||||
type: 'local' # Alternatives - 'googleGcs' or 'awsS3' or 'azureBlobStorage' or 'openStackSwift'. Read documentation for using alternatives.
|
||||
|
||||
dynatrace:
|
||||
baseUrl: https://your.dynatrace.instance.com
|
||||
|
||||
sentry:
|
||||
organization: my-company
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: Dynatrace
|
||||
author: TELUS
|
||||
authorUrl: https://github.com/telus
|
||||
category: Monitoring
|
||||
description: View monitoring info from dynatrace for services in your software catalog.
|
||||
documentation: https://github.com/backstage/backstage/tree/master/plugins/dynatrace
|
||||
iconUrl: img/dynatrace.svg
|
||||
npmPackageName: '@backstage/plugin-dynatrace'
|
||||
tags:
|
||||
- dynatrace
|
||||
- monitoring
|
||||
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="370px"
|
||||
height="344px" viewBox="0 0 370 344" enable-background="new 0 0 370 344" xml:space="preserve">
|
||||
<g id="Background">
|
||||
</g>
|
||||
<g id="Vertical">
|
||||
</g>
|
||||
<g id="Horizontal">
|
||||
</g>
|
||||
<g id="Dynatrace_Color">
|
||||
</g>
|
||||
<g id="Variants">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M241.9,282.2h-10.6c-3,0-5.1,0.6-6.3,1.8c-1.3,1.2-1.9,3.3-1.9,6.2l0,36.6h-6.4l0-37.1
|
||||
c0-2.8,0.5-5.9,2-8.2c2.7-4.3,7.9-5.1,11.7-5.1h11.5V282.2z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M201.1,321.2c-3,0-5.1-0.6-6.3-1.8c-1.3-1.2-1.9-3.2-1.9-6.1v-31h13.3v-5.7h-13.3v-15.1h-6.4v52.2
|
||||
c0,2.8,0.5,5.9,2,8.2c2.7,4.3,7.9,5.1,11.7,5.1h11.5v-5.7H201.1z"/>
|
||||
</g>
|
||||
<path fill="#FFFFFF" d="M35.1,261.4v15.1l-13.3,0c-8.1,0-13,2.4-16,5.3c-4.7,4.5-4.7,11-4.7,11.7c0,0.8,0,15.4,0,16.2
|
||||
c0,0.7,0,7.2,4.7,11.7c3,2.9,7.9,5.3,16,5.3h5.9c3.8,0,9-0.8,11.7-5.1c1.5-2.3,2-5.4,2-8.2v-52.2H35.1z M33.2,319.3
|
||||
c-1.3,1.2-3.3,1.8-6.3,1.8h-5.7c-5.2,0-8.5-1.5-10.5-3.5c-2.4-2.3-3.2-5.3-3.2-7.7v-16.6c0-2.4,0.8-5.4,3.2-7.7
|
||||
c2-2,5.3-3.5,10.5-3.5l13.9,0l0,31C35.1,316.1,34.4,318.1,33.2,319.3z"/>
|
||||
<path fill="#FFFFFF" d="M299.3,285.7c2-2,5.3-3.5,10.5-3.5h15.3v-5.7h-14.6c-8.1,0-13,2.4-16,5.3c-4.7,4.5-4.7,11-4.7,11.7
|
||||
c0,0.4,0,15.8,0,16.2c0,0.7,0,7.2,4.7,11.7c3,2.9,7.9,5.3,16,5.3h14.6v-5.7h-15.3c-5.2,0-8.5-1.5-10.5-3.5
|
||||
c-2.4-2.3-3.2-5.3-3.2-7.7v-16.6C296.2,291,297,288,299.3,285.7z"/>
|
||||
<path fill="#FFFFFF" d="M180,293.6c0-0.7,0-7.2-4.7-11.7c-3-2.9-7.9-5.3-16-5.3h-14.1v5.7H160c5.2,0,8.5,1.5,10.5,3.5
|
||||
c2.4,2.3,3.2,5.3,3.2,7.7v4.8h-20.2c-3.8,0-9,0.8-11.7,5.1c-1.5,2.3-2,5.4-2,8.2v2c0,2.8,0.5,5.9,2,8.2c2.7,4.3,7.9,5.1,11.7,5.1
|
||||
h12.8c3.8,0,9-0.8,11.7-5.1c1.5-2.3,2-5.4,2-8.2C180,313.6,180,296.9,180,293.6z M171.7,319.3c-1.3,1.2-3.3,1.8-6.3,1.8h-11.1
|
||||
c-3,0-5.1-0.6-6.3-1.8c-1.3-1.2-1.9-3.2-1.9-6.1v-1.4c0-2.9,0.6-4.9,1.9-6.1c1.3-1.2,3.3-1.8,6.3-1.8h19.4l0,9.3
|
||||
C173.6,316.1,173,318.1,171.7,319.3z"/>
|
||||
<path fill="#FFFFFF" d="M284.8,293.6c0-0.7,0-7.2-4.7-11.7c-3-2.9-7.9-5.3-16-5.3H250v5.7h14.7c5.2,0,8.5,1.5,10.5,3.5
|
||||
c2.4,2.3,3.2,5.3,3.2,7.7v4.8h-20.2c-3.8,0-9,0.8-11.7,5.1c-1.5,2.3-2,5.4-2,8.2v2c0,2.8,0.5,5.9,2,8.2c2.7,4.3,7.9,5.1,11.7,5.1
|
||||
H271c3.8,0,9-0.8,11.7-5.1c1.5-2.3,2-5.4,2-8.2C284.8,313.6,284.8,296.9,284.8,293.6z M276.5,319.3c-1.3,1.2-3.3,1.8-6.3,1.8H259
|
||||
c-3,0-5.1-0.6-6.3-1.8c-1.3-1.2-1.9-3.2-1.9-6.1v-1.4c0-2.9,0.6-4.9,1.9-6.1c1.3-1.2,3.3-1.8,6.3-1.8h19.4l0,9.3
|
||||
C278.4,316.1,277.8,318.1,276.5,319.3z"/>
|
||||
<polygon fill="#FFFFFF" points="91.8,276.5 85.2,276.5 69.1,318.3 53.1,276.5 46.5,276.5 65.8,326.9 60,342 66.6,342 "/>
|
||||
<path fill="#FFFFFF" d="M134.6,293.6c0-0.7,0-7.2-4.6-11.7c-2.9-2.9-7.6-5.2-15.2-5.3h-0.7c-7.6,0.1-12.3,2.5-15.2,5.3
|
||||
c-4.6,4.5-4.6,11-4.6,11.7c0,0.8,0,30.7,0,33.3h6.3l0-33.5c0-2.4,0.8-5.4,3.1-7.7c2-1.9,5.7-3.4,10.7-3.4c5,0.1,8.8,1.5,10.7,3.4
|
||||
c2.3,2.3,3.1,5.3,3.1,7.7l0,33.5h6.3C134.6,324.3,134.6,294.4,134.6,293.6z"/>
|
||||
<path fill="#FFFFFF" d="M364.3,281.9c-2.9-2.9-7.6-5.2-15.2-5.3h-0.7c-7.6,0.1-12.3,2.5-15.2,5.3c-4.6,4.5-4.6,11-4.6,11.7v16.2
|
||||
c0,0.7,0,7.2,4.6,11.7c2.9,2.9,7.6,5.2,15.2,5.3h14.9v-5.7l-14.6,0c-5-0.1-8.8-1.5-10.7-3.4c-2.3-2.3-3.1-5.3-3.1-7.7v-6h34
|
||||
v-10.5C368.9,292.9,368.9,286.4,364.3,281.9z M334.9,298.3v-5c0-2.4,0.8-5.4,3.1-7.7c2-1.9,5.7-3.4,10.7-3.4
|
||||
c5,0.1,8.8,1.5,10.7,3.4c2.3,2.3,3.1,5.3,3.1,7.7l0,5H334.9z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#1496FF" d="M151,19.8c-2.7,14.5-6.2,35.9-8,57.6c-3.2,38.4-1.2,64-1.2,64l-53.9,51.3c0,0-4.2-28.8-6.3-61.2
|
||||
c-1.3-20-1.7-37.7-1.8-48.4c0-0.6,0.3-1.2,0.3-1.8c0-0.7,0.9-7.9,7.9-14.5C95.7,59.5,151.8,15.5,151,19.8z"/>
|
||||
<path fill="#1284EA" d="M151,19.8c-2.7,14.5-6.2,35.9-8,57.6c0,0-59.7-7.1-63.2,7.3c0-0.7,1-9.5,8-16.2
|
||||
C95.5,61.1,151.8,15.5,151,19.8z"/>
|
||||
<path fill="#B4DC00" d="M79.8,81.3c0,1,0,2.1,0,3.3c0.6-2.6,1.6-4.5,3.8-7.2c4.4-5.6,11.6-7.1,14.5-7.5
|
||||
c14.6-1.9,36.2-4.3,57.9-4.9c38.5-1.2,63.9,2,63.9,2l53.9-51.3c0,0-28.3-5.4-60.6-9.2c-21.1-2.5-39.7-3.8-50.1-4.4
|
||||
c-0.7,0-8.2-1-15.2,5.7c-7.7,7.3-46.3,43.9-61.8,58.7C79.3,73.1,79.8,80.6,79.8,81.3z"/>
|
||||
<path fill="#6F2DA8" d="M271.9,146.8c-14.6,2-36.1,4.4-57.9,5.1c-38.5,1.3-64-1.9-64-1.9L96,201.3c0,0,28.6,5.6,60.8,9.3
|
||||
c19.7,2.3,37.3,3.5,47.9,4.1c0.7,0,2-0.6,2.7-0.6c0.7,0,8.2-1.3,15.2-8C230.4,198.8,276.2,146.3,271.9,146.8z"/>
|
||||
<path fill="#591F91" d="M271.9,146.8c-14.6,2-36.1,4.4-57.9,5.1c0,0,4.2,60-10.4,62.7c0.7,0,10.6-0.5,17.6-7.1
|
||||
C228.9,200.2,276.2,146.3,271.9,146.8z"/>
|
||||
<path fill="#73BE28" d="M206.9,214.9c-1-0.1-2.1-0.1-3.3-0.2c2.7-0.5,4.5-1.4,7.4-3.4c5.8-4.2,7.7-11.2,8.2-14.1
|
||||
c2.6-14.5,6-35.9,7.8-57.6c3.1-38.4,1.1-63.9,1.1-63.9l53.9-51.3c0,0,4,28.5,6.2,60.9c1.4,21.2,1.8,39.8,1.9,50.2
|
||||
c0,0.7,0.6,8.2-6.4,14.9c-7.7,7.3-46.2,44.1-61.7,58.9C215.1,215.8,207.6,214.9,206.9,214.9z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
@@ -29,6 +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.2",
|
||||
"@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",
|
||||
|
||||
@@ -73,6 +73,10 @@ import {
|
||||
isCloudbuildAvailable,
|
||||
} from '@backstage/plugin-cloudbuild';
|
||||
import { EntityCodeCoverageContent } from '@backstage/plugin-code-coverage';
|
||||
import {
|
||||
DynatraceTab,
|
||||
isDynatraceAvailable,
|
||||
} from '@backstage/plugin-dynatrace';
|
||||
import {
|
||||
EntityGithubActionsContent,
|
||||
EntityRecentGithubActionsRunsCard,
|
||||
@@ -447,6 +451,14 @@ const serviceEntityPage = (
|
||||
<EntityLayout.Route path="/todos" title="TODOs">
|
||||
<EntityTodoContent />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route
|
||||
path="/dynatrace"
|
||||
title="Dynatrace"
|
||||
if={isDynatraceAvailable}
|
||||
>
|
||||
<DynatraceTab />
|
||||
</EntityLayout.Route>
|
||||
</EntityLayoutWrapper>
|
||||
);
|
||||
|
||||
@@ -495,6 +507,14 @@ const websiteEntityPage = (
|
||||
<EntityKubernetesContent />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route
|
||||
path="/dynatrace"
|
||||
title="Dynatrace"
|
||||
if={isDynatraceAvailable}
|
||||
>
|
||||
<DynatraceTab />
|
||||
</EntityLayout.Route>
|
||||
|
||||
<EntityLayout.Route
|
||||
if={isAzureDevOpsAvailable}
|
||||
path="/git-tags"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
|
||||
@@ -0,0 +1,56 @@
|
||||
# Dynatrace
|
||||
|
||||
Welcome to the Dynatrace plugin!
|
||||
|
||||
## Getting started
|
||||
|
||||
This plugin uses the Backstage proxy to communicate with Dynatrace's REST APIs.
|
||||
|
||||
### Setup
|
||||
|
||||
#### Dynatrace API Key
|
||||
|
||||
The Dynatrace plugin will require the following information, to be used in the configuration options detailed below:
|
||||
|
||||
- Dynatrace API URL, e.g. `https://my-dynatrace-instance.dynatrace.com/api/v2`
|
||||
- Dynatrace API access token (see [documentation](https://www.dynatrace.com/support/help/dynatrace-api/basics/dynatrace-api-authentication)), with the following permissions:
|
||||
- `entities.read`
|
||||
- `problems.read`
|
||||
|
||||
#### Plugin Configuration
|
||||
|
||||
This plugin requires a proxy endpoint for Dynatrace configured in `app-config.yaml` like so:
|
||||
|
||||
```yaml
|
||||
proxy:
|
||||
'/dynatrace':
|
||||
target: 'https://example.dynatrace.com/api/v2'
|
||||
headers:
|
||||
Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}'
|
||||
```
|
||||
|
||||
It also requires a baseUrl for rendering links to problems in the table like so:
|
||||
|
||||
```yaml
|
||||
dynatrace:
|
||||
baseUrl: 'https://example.dynatrace.com'
|
||||
```
|
||||
|
||||
#### Catalog Configuration
|
||||
|
||||
To show information from Dynatrace for a catalog entity, add the following annotation to `catalog-info.yaml`:
|
||||
|
||||
```yaml
|
||||
# catalog-info.yaml
|
||||
# [...]
|
||||
metadata:
|
||||
annotations:
|
||||
dynatrace.com/dynatrace-entity-id: DYNATRACE_ENTITY_ID
|
||||
# [...]
|
||||
```
|
||||
|
||||
The `DYNATRACE_ENTITY_ID` can be found in Dynatrace by browsing to the entity (a service, synthetic, frontend, workload, etc.). It will be located in the browser address bar in the `id` parameter and has the format `ENTITY_TYPE-ENTITY_ID`, where `ENTITY_TYPE` will be one of `SERVICE`, `SYNTHETIC_TEST`, or other, and `ENTITY_ID` will be a string of characters containing uppercase letters and numbers.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This plugin is not officially supported by Dynatrace.
|
||||
@@ -0,0 +1,23 @@
|
||||
## API Report File for "@backstage/plugin-dynatrace"
|
||||
|
||||
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
|
||||
|
||||
```ts
|
||||
/// <reference types="react" />
|
||||
|
||||
import { BackstagePlugin } from '@backstage/core-plugin-api';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
// @public
|
||||
export const dynatracePlugin: BackstagePlugin<{}, {}>;
|
||||
|
||||
// @public
|
||||
export const DynatraceTab: () => JSX.Element;
|
||||
|
||||
// Warning: (tsdoc-param-tag-with-invalid-type) The @param block should not include a JSDoc-style '{type}'
|
||||
//
|
||||
// @public
|
||||
export const isDynatraceAvailable: (entity: Entity) => boolean;
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
```
|
||||
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export interface Config {
|
||||
/**
|
||||
* dynatrace config
|
||||
* @visibility frontend
|
||||
*/
|
||||
dynatrace?: {
|
||||
/**
|
||||
* base url for links
|
||||
* @visibility frontend
|
||||
*/
|
||||
baseUrl: string;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { createDevApp } from '@backstage/dev-utils';
|
||||
import { dynatracePlugin, DynatraceTab } from '../src/plugin';
|
||||
|
||||
createDevApp()
|
||||
.registerPlugin(dynatracePlugin)
|
||||
.addPage({
|
||||
element: <DynatraceTab />,
|
||||
title: 'Root Page',
|
||||
path: '/dynatrace',
|
||||
})
|
||||
.render();
|
||||
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "@backstage/plugin-dynatrace",
|
||||
"version": "0.0.0",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"license": "Apache-2.0",
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"main": "dist/index.esm.js",
|
||||
"types": "dist/index.d.ts"
|
||||
},
|
||||
"backstage": {
|
||||
"role": "frontend-plugin"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "backstage-cli package start",
|
||||
"build": "backstage-cli package build",
|
||||
"lint": "backstage-cli package lint",
|
||||
"test": "backstage-cli package test",
|
||||
"clean": "backstage-cli package clean",
|
||||
"prepack": "backstage-cli package prepack",
|
||||
"postpack": "backstage-cli package postpack"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "^1.0.3-next.0",
|
||||
"@backstage/core-components": "^0.9.5-next.1",
|
||||
"@backstage/core-plugin-api": "^1.0.3-next.0",
|
||||
"@backstage/theme": "^0.2.15",
|
||||
"@material-ui/core": "^4.9.13",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.57",
|
||||
"cross-fetch": "^3.1.5",
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@backstage/plugin-catalog-react": "^1.1.1-next.1",
|
||||
"react": "^16.13.1 || ^17.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "^0.17.2-next.1",
|
||||
"@backstage/core-app-api": "^1.0.3-next.0",
|
||||
"@backstage/dev-utils": "^1.0.3-next.1",
|
||||
"@backstage/test-utils": "^1.1.1-next.0",
|
||||
"@testing-library/jest-dom": "^5.10.1",
|
||||
"@testing-library/react": "^12.1.3",
|
||||
"@testing-library/user-event": "^14.0.0",
|
||||
"@types/jest": "*",
|
||||
"@types/node": "*",
|
||||
"cross-fetch": "^3.1.5",
|
||||
"express": "^4.18.1",
|
||||
"msw": "^0.42.0"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"config.d.ts"
|
||||
],
|
||||
"configSchema": "config.d.ts"
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { createApiRef } from '@backstage/core-plugin-api';
|
||||
|
||||
export type DynatraceEntity = {
|
||||
entityId: {
|
||||
id: string;
|
||||
type: string;
|
||||
};
|
||||
name: string;
|
||||
};
|
||||
|
||||
export type DynatraceProblem = {
|
||||
problemId: string;
|
||||
impactLevel: string;
|
||||
status: string;
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
title: string;
|
||||
severityLevel: string;
|
||||
rootCauseEntity: DynatraceEntity;
|
||||
affectedEntities: Array<DynatraceEntity>;
|
||||
};
|
||||
|
||||
export interface DynatraceProblems {
|
||||
problems: Array<DynatraceProblem>;
|
||||
}
|
||||
|
||||
export const dynatraceApiRef = createApiRef<DynatraceApi>({
|
||||
id: 'plugin.dynatrace.service',
|
||||
});
|
||||
|
||||
export type DynatraceApi = {
|
||||
getDynatraceProblems(
|
||||
dynatraceEntityId: string,
|
||||
): Promise<DynatraceProblems | undefined>;
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { DynatraceProblems, DynatraceApi } from './DynatraceApi';
|
||||
import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';
|
||||
|
||||
export class DynatraceClient implements DynatraceApi {
|
||||
discoveryApi: DiscoveryApi;
|
||||
fetchApi: FetchApi;
|
||||
|
||||
constructor({
|
||||
discoveryApi,
|
||||
fetchApi,
|
||||
}: {
|
||||
discoveryApi: DiscoveryApi;
|
||||
fetchApi: FetchApi;
|
||||
}) {
|
||||
this.discoveryApi = discoveryApi;
|
||||
this.fetchApi = fetchApi;
|
||||
}
|
||||
|
||||
private async callApi<T>(
|
||||
path: string,
|
||||
query: { [key in string]: any },
|
||||
): Promise<T | undefined> {
|
||||
const apiUrl = `${await this.discoveryApi.getBaseUrl('proxy')}/dynatrace`;
|
||||
const response = await this.fetchApi.fetch(
|
||||
`${apiUrl}/${path}?${new URLSearchParams(query).toString()}`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
);
|
||||
if (response.status === 200) {
|
||||
return (await response.json()) as T;
|
||||
}
|
||||
throw new Error(
|
||||
`Dynatrace API call failed: ${response.status}:${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
async getDynatraceProblems(
|
||||
dynatraceEntityId: string,
|
||||
): Promise<DynatraceProblems | undefined> {
|
||||
if (!dynatraceEntityId) {
|
||||
throw new Error('Dynatrace entity ID is required');
|
||||
}
|
||||
|
||||
return this.callApi('problems', {
|
||||
entitySelector: `entityId(${dynatraceEntityId})`,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export type {
|
||||
DynatraceProblems,
|
||||
DynatraceProblem,
|
||||
DynatraceEntity,
|
||||
} from './DynatraceApi';
|
||||
export { dynatraceApiRef } from './DynatraceApi';
|
||||
export { DynatraceClient } from './DynatraceClient';
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { Grid } from '@material-ui/core';
|
||||
import {
|
||||
Page,
|
||||
Content,
|
||||
ContentHeader,
|
||||
SupportButton,
|
||||
MissingAnnotationEmptyState,
|
||||
} from '@backstage/core-components';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import { ProblemsList } from '../Problems/ProblemsList';
|
||||
import { isDynatraceAvailable } from '../../plugin';
|
||||
import { DYNATRACE_ID_ANNOTATION } from '../../constants';
|
||||
|
||||
export const DynatraceTab = () => {
|
||||
const { entity } = useEntity();
|
||||
|
||||
if (!isDynatraceAvailable(entity)) {
|
||||
return <MissingAnnotationEmptyState annotation={DYNATRACE_ID_ANNOTATION} />;
|
||||
}
|
||||
|
||||
const dynatraceEntityId: string =
|
||||
entity?.metadata.annotations?.[DYNATRACE_ID_ANNOTATION]!;
|
||||
|
||||
return (
|
||||
<Page themeId="tool">
|
||||
<Content>
|
||||
<ContentHeader title="Dynatrace">
|
||||
<SupportButton>
|
||||
Plugin to show information from Dynatrace
|
||||
</SupportButton>
|
||||
</ContentHeader>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={12} lg={12}>
|
||||
<ProblemsList dynatraceEntityId={dynatraceEntityId} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export { DynatraceTab } from './DynatraceTab';
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { ProblemStatus } from './ProblemStatus';
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
|
||||
describe('ProblemStatus', () => {
|
||||
it('renders StatusOK for a closed issue', async () => {
|
||||
const rendered = await renderInTestApp(<ProblemStatus status="closed" />);
|
||||
expect(await rendered.findByText('Closed')).toBeInTheDocument();
|
||||
});
|
||||
it('renders StatusError for an open issue', async () => {
|
||||
const rendered = await renderInTestApp(<ProblemStatus status="open" />);
|
||||
expect(await rendered.findByText('Open')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { DynatraceProblem } from '../../../api/DynatraceApi';
|
||||
import { StatusError, StatusOK } from '@backstage/core-components';
|
||||
|
||||
export const ProblemStatus = ({ status }: Partial<DynatraceProblem>) => {
|
||||
switch (status?.toLocaleLowerCase()) {
|
||||
case 'open':
|
||||
return (
|
||||
<>
|
||||
<StatusError />
|
||||
Open
|
||||
</>
|
||||
);
|
||||
case 'closed':
|
||||
return (
|
||||
<>
|
||||
<StatusOK />
|
||||
Closed
|
||||
</>
|
||||
);
|
||||
default:
|
||||
return <></>;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export { ProblemStatus } from './ProblemStatus';
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { ProblemsList } from './ProblemsList';
|
||||
import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils';
|
||||
import { dynatraceApiRef } from '../../../api';
|
||||
import { problems } from '../../../mocks/problems.json';
|
||||
import { ApiProvider, ConfigReader } from '@backstage/core-app-api';
|
||||
import { configApiRef } from '@backstage/core-plugin-api';
|
||||
|
||||
const mockDynatraceApi = {
|
||||
getDynatraceProblems: jest.fn(),
|
||||
};
|
||||
const apis = TestApiRegistry.from(
|
||||
[dynatraceApiRef, mockDynatraceApi],
|
||||
[configApiRef, new ConfigReader({ dynatrace: { baseUrl: '__dynatrace__' } })],
|
||||
);
|
||||
|
||||
describe('ProblemStatus', () => {
|
||||
it('renders a table with problem data', async () => {
|
||||
mockDynatraceApi.getDynatraceProblems = jest
|
||||
.fn()
|
||||
.mockResolvedValue({ problems });
|
||||
const rendered = await renderInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<ProblemsList dynatraceEntityId="example-service-3" />
|
||||
</ApiProvider>,
|
||||
);
|
||||
expect(await rendered.findByText('example-service')).toBeInTheDocument();
|
||||
});
|
||||
it('renders "nothing to report :)" if no problems are found', async () => {
|
||||
mockDynatraceApi.getDynatraceProblems = jest.fn().mockResolvedValue({});
|
||||
const rendered = await renderInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<ProblemsList dynatraceEntityId="example-service-3" />
|
||||
</ApiProvider>,
|
||||
);
|
||||
expect(
|
||||
await rendered.findByText('Nothing to report :)'),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import { Progress } from '@backstage/core-components';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import { ProblemsTable } from '../ProblemsTable';
|
||||
import { dynatraceApiRef } from '../../../api';
|
||||
|
||||
type ProblemsListProps = {
|
||||
dynatraceEntityId: string;
|
||||
};
|
||||
|
||||
export const ProblemsList = (props: ProblemsListProps) => {
|
||||
const { dynatraceEntityId } = props;
|
||||
const dynatraceApi = useApi(dynatraceApiRef);
|
||||
const { value, loading, error } = useAsync(async () => {
|
||||
return dynatraceApi.getDynatraceProblems(dynatraceEntityId);
|
||||
}, [dynatraceApi, dynatraceEntityId]);
|
||||
const problems = value?.problems;
|
||||
|
||||
if (loading) {
|
||||
return <Progress />;
|
||||
} else if (error) {
|
||||
return <Alert severity="error">{error.message}</Alert>;
|
||||
}
|
||||
if (!problems) return <div>Nothing to report :)</div>;
|
||||
return <ProblemsTable problems={problems} />;
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export { ProblemsList } from './ProblemsList';
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { ProblemsTable } from './ProblemsTable';
|
||||
import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils';
|
||||
import { problems } from '../../../mocks/problems.json';
|
||||
import { ApiProvider, ConfigReader } from '@backstage/core-app-api';
|
||||
import { configApiRef } from '@backstage/core-plugin-api';
|
||||
|
||||
describe('ProblemsTable', () => {
|
||||
const apis = TestApiRegistry.from([
|
||||
configApiRef,
|
||||
new ConfigReader({ dynatrace: { baseUrl: '__dynatrace__' } }),
|
||||
]);
|
||||
it('renders the table with some problem data', async () => {
|
||||
const rendered = await renderInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<ProblemsTable problems={problems} />,
|
||||
</ApiProvider>,
|
||||
);
|
||||
expect(await rendered.findByText('example-service')).toBeInTheDocument();
|
||||
});
|
||||
it('renders an empty table when no data is provided', async () => {
|
||||
const rendered = await renderInTestApp(
|
||||
<ApiProvider apis={apis}>
|
||||
<ProblemsTable problems={[]} />
|
||||
</ApiProvider>,
|
||||
);
|
||||
expect(await rendered.findByText('Problems')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { Table, TableColumn } from '@backstage/core-components';
|
||||
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: DynatraceProblem[];
|
||||
};
|
||||
|
||||
export const ProblemsTable = ({ problems }: ProblemsTableProps) => {
|
||||
const configApi = useApi(configApiRef);
|
||||
const dynatraceBaseUrl = configApi.getString('dynatrace.baseUrl');
|
||||
const columns: TableColumn[] = [
|
||||
{
|
||||
title: 'Title',
|
||||
field: 'title',
|
||||
render: (row: Partial<DynatraceProblem>) => (
|
||||
<Link
|
||||
href={`${dynatraceBaseUrl}/#problems/problemdetails;pid=${row.problemId}`}
|
||||
>
|
||||
{row.title}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Status',
|
||||
field: 'status',
|
||||
render: (row: Partial<DynatraceProblem>) => (
|
||||
<ProblemStatus status={row.status} />
|
||||
),
|
||||
},
|
||||
{ title: 'Severity', field: 'severityLevel' },
|
||||
{
|
||||
title: 'Root Cause',
|
||||
field: 'rootCauseEntity',
|
||||
render: (row: Partial<DynatraceProblem>) => row.rootCauseEntity?.name,
|
||||
},
|
||||
{
|
||||
title: 'Affected',
|
||||
field: 'affectedEntities',
|
||||
render: (row: Partial<DynatraceProblem>) =>
|
||||
row.affectedEntities?.map(e => e.name),
|
||||
},
|
||||
{
|
||||
title: 'Start Time',
|
||||
field: 'startTime',
|
||||
render: (row: Partial<DynatraceProblem>) =>
|
||||
new Date(row.startTime || 0).toString(),
|
||||
},
|
||||
{
|
||||
title: 'End Time',
|
||||
field: 'endTime',
|
||||
render: (row: Partial<DynatraceProblem>) =>
|
||||
row.endTime === -1 ? 'ongoing' : new Date(row.endTime || 0).toString(),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Table
|
||||
title="Problems"
|
||||
options={{ search: true, paging: true }}
|
||||
columns={columns}
|
||||
data={problems.map(p => {
|
||||
return { ...p, id: p.problemId };
|
||||
})}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export { ProblemsTable } from './ProblemsTable';
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export const DYNATRACE_ID_ANNOTATION = 'dynatrace.com/dynatrace-entity-id';
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
export { dynatracePlugin, DynatraceTab, isDynatraceAvailable } from './plugin';
|
||||
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"totalCount": 0,
|
||||
"pageSize": 0,
|
||||
"nextPageKey": "AQAAABQBAAAABQ==",
|
||||
"problems": [
|
||||
{
|
||||
"managementZones": [
|
||||
{
|
||||
"name": "string",
|
||||
"id": "string"
|
||||
}
|
||||
],
|
||||
"severityLevel": "AVAILABILITY",
|
||||
"entityTags": [
|
||||
{
|
||||
"stringRepresentation": "string",
|
||||
"value": "string",
|
||||
"key": "string",
|
||||
"context": "string"
|
||||
}
|
||||
],
|
||||
"problemId": "string",
|
||||
"displayId": "string",
|
||||
"affectedEntities": [
|
||||
{
|
||||
"entityId": {
|
||||
"id": "string",
|
||||
"type": "string"
|
||||
},
|
||||
"name": "my-service"
|
||||
},
|
||||
{
|
||||
"entityId": {
|
||||
"id": "string",
|
||||
"type": "string"
|
||||
},
|
||||
"name": "example-service-3"
|
||||
}
|
||||
],
|
||||
"rootCauseEntity": {
|
||||
"entityId": {
|
||||
"id": "string",
|
||||
"type": "string"
|
||||
},
|
||||
"name": "example-service"
|
||||
},
|
||||
"impactedEntities": [
|
||||
{
|
||||
"entityId": {
|
||||
"id": "string",
|
||||
"type": "string"
|
||||
},
|
||||
"name": "HELP ME"
|
||||
},
|
||||
{
|
||||
"entityId": {
|
||||
"id": "string",
|
||||
"type": "string"
|
||||
},
|
||||
"name": "HELP ME 2"
|
||||
}
|
||||
],
|
||||
"linkedProblemInfo": {
|
||||
"problemId": "string",
|
||||
"displayId": "string"
|
||||
},
|
||||
"problemFilters": [
|
||||
{
|
||||
"name": "string",
|
||||
"id": "string"
|
||||
}
|
||||
],
|
||||
"evidenceDetails": {
|
||||
"totalCount": 0,
|
||||
"details": [
|
||||
{
|
||||
"evidenceType": "AVAILABILITY_EVIDENCE",
|
||||
"displayName": "string",
|
||||
"entity": {
|
||||
"entityId": {
|
||||
"id": "string",
|
||||
"type": "string"
|
||||
},
|
||||
"name": "string"
|
||||
},
|
||||
"groupingEntity": {
|
||||
"entityId": {
|
||||
"id": "string",
|
||||
"type": "string"
|
||||
},
|
||||
"name": "string"
|
||||
},
|
||||
"rootCauseRelevant": true,
|
||||
"startTime": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"recentComments": {
|
||||
"comments": [
|
||||
{
|
||||
"createdAtTimestamp": 0,
|
||||
"authorName": "string",
|
||||
"context": "string",
|
||||
"id": "string",
|
||||
"content": "string"
|
||||
}
|
||||
],
|
||||
"totalCount": 0,
|
||||
"pageSize": 0,
|
||||
"nextPageKey": "AQAAABQBAAAABQ=="
|
||||
},
|
||||
"impactAnalysis": {
|
||||
"impacts": [
|
||||
{
|
||||
"impactType": "APPLICATION",
|
||||
"impactedEntity": {
|
||||
"entityId": {
|
||||
"id": "string",
|
||||
"type": "string"
|
||||
},
|
||||
"name": "string"
|
||||
},
|
||||
"estimatedAffectedUsers": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"impactLevel": "APPLICATION",
|
||||
"status": "OPEN",
|
||||
"startTime": 0,
|
||||
"endTime": 0,
|
||||
"title": "this IS a big problem"
|
||||
}
|
||||
],
|
||||
"warnings": ["string"]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { dynatracePlugin } from './plugin';
|
||||
|
||||
describe('dynatrace', () => {
|
||||
it('should export plugin', () => {
|
||||
expect(dynatracePlugin).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { dynatraceApiRef, DynatraceClient } from './api';
|
||||
import {
|
||||
createApiFactory,
|
||||
createPlugin,
|
||||
discoveryApiRef,
|
||||
fetchApiRef,
|
||||
createRoutableExtension,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { DYNATRACE_ID_ANNOTATION } from './constants';
|
||||
|
||||
import { rootRouteRef } from './routes';
|
||||
|
||||
/**
|
||||
* Create the Dynatrace plugin.
|
||||
* @public
|
||||
*/
|
||||
export const dynatracePlugin = createPlugin({
|
||||
id: 'dynatrace',
|
||||
apis: [
|
||||
createApiFactory({
|
||||
api: dynatraceApiRef,
|
||||
deps: {
|
||||
discoveryApi: discoveryApiRef,
|
||||
fetchApi: fetchApiRef,
|
||||
},
|
||||
factory: ({ discoveryApi, fetchApi }) =>
|
||||
new DynatraceClient({
|
||||
discoveryApi,
|
||||
fetchApi,
|
||||
}),
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
/**
|
||||
* Checks if the entity has a dynatrace id annotation.
|
||||
* @public
|
||||
* @param entity {Entity} - The entity to check for the dynatrace id annotation.
|
||||
*/
|
||||
export const isDynatraceAvailable = (entity: Entity) =>
|
||||
Boolean(entity.metadata.annotations?.[DYNATRACE_ID_ANNOTATION]);
|
||||
|
||||
/**
|
||||
* Creates a routable extension for the dynatrace plugin tab.
|
||||
* @public
|
||||
*/
|
||||
export const DynatraceTab = dynatracePlugin.provide(
|
||||
createRoutableExtension({
|
||||
name: 'DynatraceTab',
|
||||
component: () =>
|
||||
import('./components/DynatraceTab').then(m => m.DynatraceTab),
|
||||
mountPoint: rootRouteRef,
|
||||
}),
|
||||
);
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { createRouteRef } from '@backstage/core-plugin-api';
|
||||
|
||||
export const rootRouteRef = createRouteRef({
|
||||
id: 'dynatrace',
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import '@testing-library/jest-dom';
|
||||
import 'cross-fetch/polyfill';
|
||||
@@ -12407,6 +12407,7 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
|
||||
"@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.2"
|
||||
"@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"
|
||||
@@ -12618,7 +12619,7 @@ express-xml-bodyparser@^0.3.0:
|
||||
dependencies:
|
||||
xml2js "^0.4.11"
|
||||
|
||||
express@^4.17.1, express@^4.17.3:
|
||||
express@^4.17.1, express@^4.17.3, express@^4.18.1:
|
||||
version "4.18.1"
|
||||
resolved "https://registry.npmjs.org/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf"
|
||||
integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==
|
||||
|
||||
Reference in New Issue
Block a user