@backstage-community/plugin-newrelic 0.3.50 → 0.3.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/api/index.esm.js +57 -0
- package/dist/api/index.esm.js.map +1 -0
- package/dist/components/NewRelicComponent/NewRelicComponent.esm.js +10 -0
- package/dist/components/NewRelicComponent/NewRelicComponent.esm.js.map +1 -0
- package/dist/components/NewRelicComponent/index.esm.js +2 -0
- package/dist/components/NewRelicComponent/index.esm.js.map +1 -0
- package/dist/{esm/index-C0wl3iLB.esm.js → components/NewRelicFetchComponent/NewRelicFetchComponent.esm.js} +4 -9
- package/dist/components/NewRelicFetchComponent/NewRelicFetchComponent.esm.js.map +1 -0
- package/dist/index.esm.js +1 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +32 -0
- package/dist/plugin.esm.js.map +1 -0
- package/package.json +11 -7
- package/dist/esm/index-C0wl3iLB.esm.js.map +0 -1
- package/dist/esm/index-DhuyBTi3.esm.js +0 -92
- package/dist/esm/index-DhuyBTi3.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @backstage-community/plugin-newrelic
|
|
2
2
|
|
|
3
|
+
## 0.3.52
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 80b4088: Backstage version bump to v1.30.2
|
|
8
|
+
|
|
9
|
+
## 0.3.51
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- bed3488: Backstage version bump to v1.29.2
|
|
14
|
+
|
|
3
15
|
## 0.3.50
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createApiRef } from '@backstage/core-plugin-api';
|
|
2
|
+
import parseLinkHeader from 'parse-link-header';
|
|
3
|
+
|
|
4
|
+
const newRelicApiRef = createApiRef({
|
|
5
|
+
id: "plugin.newrelic.service"
|
|
6
|
+
});
|
|
7
|
+
const DEFAULT_PROXY_PATH_BASE = "/newrelic";
|
|
8
|
+
class NewRelicClient {
|
|
9
|
+
discoveryApi;
|
|
10
|
+
fetchApi;
|
|
11
|
+
proxyPathBase;
|
|
12
|
+
baseUrl;
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.discoveryApi = options.discoveryApi;
|
|
15
|
+
this.fetchApi = options.fetchApi;
|
|
16
|
+
this.proxyPathBase = options.proxyPathBase ?? DEFAULT_PROXY_PATH_BASE;
|
|
17
|
+
this.baseUrl = "";
|
|
18
|
+
}
|
|
19
|
+
async getApplications() {
|
|
20
|
+
if (!this.baseUrl) {
|
|
21
|
+
const proxyUrl = await this.discoveryApi.getBaseUrl("proxy");
|
|
22
|
+
this.baseUrl = `${proxyUrl}${this.proxyPathBase}/apm/api/applications.json`;
|
|
23
|
+
}
|
|
24
|
+
const applications = [];
|
|
25
|
+
let targetUrl = this.baseUrl;
|
|
26
|
+
do {
|
|
27
|
+
const { nextPageUrl, applicationsFromReadPage } = await this.fetchNewRelic(targetUrl);
|
|
28
|
+
targetUrl = nextPageUrl ?? "";
|
|
29
|
+
applications.push(...applicationsFromReadPage);
|
|
30
|
+
} while (!!targetUrl);
|
|
31
|
+
return { applications };
|
|
32
|
+
}
|
|
33
|
+
async fetchNewRelic(targetUrl) {
|
|
34
|
+
const response = await this.fetchApi.fetch(targetUrl);
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
let specificErrorTitle = void 0;
|
|
37
|
+
try {
|
|
38
|
+
specificErrorTitle = (await response.json())?.error?.title;
|
|
39
|
+
} catch (e) {
|
|
40
|
+
}
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Error communicating with New Relic: ${specificErrorTitle || response.statusText}`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
const readResponse = await response.json();
|
|
46
|
+
const linkHeader = response.headers.get("link");
|
|
47
|
+
const parseResult = parseLinkHeader(linkHeader);
|
|
48
|
+
const nextPageNumber = parseResult?.next?.page;
|
|
49
|
+
return {
|
|
50
|
+
nextPageUrl: nextPageNumber && `${this.baseUrl}?page=${nextPageNumber}`,
|
|
51
|
+
applicationsFromReadPage: readResponse.applications
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export { NewRelicClient, newRelicApiRef };
|
|
57
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../../src/api/index.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createApiRef,\n DiscoveryApi,\n FetchApi,\n} from '@backstage/core-plugin-api';\n\nimport parseLinkHeader from 'parse-link-header';\n\nexport type NewRelicApplication = {\n id: number;\n application_summary: NewRelicApplicationSummary;\n name: string;\n language: string;\n health_status: string;\n reporting: boolean;\n settings: NewRelicApplicationSettings;\n links?: NewRelicApplicationLinks;\n};\n\nexport type NewRelicApplicationSummary = {\n apdex_score: number;\n error_rate: number;\n host_count: number;\n instance_count: number;\n response_time: number;\n throughput: number;\n};\n\nexport type NewRelicApplicationSettings = {\n app_apdex_threshold: number;\n end_user_apdex_threshold: number;\n enable_real_user_monitoring: boolean;\n use_server_side_config: boolean;\n};\n\nexport type NewRelicApplicationLinks = {\n application_instances: Array<any>;\n servers: Array<any>;\n application_hosts: Array<any>;\n};\n\nexport type NewRelicApplications = {\n applications: NewRelicApplication[];\n};\n\nexport const newRelicApiRef = createApiRef<NewRelicApi>({\n id: 'plugin.newrelic.service',\n});\n\nconst DEFAULT_PROXY_PATH_BASE = '/newrelic';\n\ntype Options = {\n discoveryApi: DiscoveryApi;\n fetchApi: FetchApi;\n /**\n * Path to use for requests via the proxy, defaults to /newrelic\n */\n proxyPathBase?: string;\n};\n\nexport interface NewRelicApi {\n getApplications(): Promise<NewRelicApplications>;\n}\n\ninterface NewRelicPageReadResult {\n nextPageUrl: string | undefined;\n applicationsFromReadPage: NewRelicApplication[];\n}\n\nexport class NewRelicClient implements NewRelicApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n private readonly proxyPathBase: string;\n private baseUrl: string;\n\n constructor(options: Options) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi;\n this.proxyPathBase = options.proxyPathBase ?? DEFAULT_PROXY_PATH_BASE;\n this.baseUrl = '';\n }\n\n async getApplications(): Promise<NewRelicApplications> {\n if (!this.baseUrl) {\n const proxyUrl = await this.discoveryApi.getBaseUrl('proxy');\n this.baseUrl = `${proxyUrl}${this.proxyPathBase}/apm/api/applications.json`;\n }\n\n const applications: NewRelicApplication[] = [];\n let targetUrl = this.baseUrl;\n\n do {\n const { nextPageUrl, applicationsFromReadPage } =\n await this.fetchNewRelic(targetUrl);\n\n targetUrl = nextPageUrl ?? '';\n applications.push(...applicationsFromReadPage);\n } while (!!targetUrl);\n\n return { applications };\n }\n\n private async fetchNewRelic(\n targetUrl: string,\n ): Promise<NewRelicPageReadResult> {\n const response = await this.fetchApi.fetch(targetUrl);\n\n if (!response.ok) {\n let specificErrorTitle = undefined;\n try {\n specificErrorTitle = (await response.json())?.error?.title;\n } catch (e) {\n /* empty */\n }\n\n throw new Error(\n `Error communicating with New Relic: ${\n specificErrorTitle || response.statusText\n }`,\n );\n }\n\n const readResponse = (await response.json()) as NewRelicApplications;\n const linkHeader = response.headers.get('link');\n const parseResult = parseLinkHeader(linkHeader);\n const nextPageNumber = parseResult?.next?.page;\n\n return {\n nextPageUrl: nextPageNumber && `${this.baseUrl}?page=${nextPageNumber}`,\n applicationsFromReadPage: readResponse.applications,\n };\n }\n}\n"],"names":[],"mappings":";;;AA6DO,MAAM,iBAAiB,YAA0B,CAAA;AAAA,EACtD,EAAI,EAAA,yBAAA;AACN,CAAC,EAAA;AAED,MAAM,uBAA0B,GAAA,WAAA,CAAA;AAoBzB,MAAM,cAAsC,CAAA;AAAA,EAChC,YAAA,CAAA;AAAA,EACA,QAAA,CAAA;AAAA,EACA,aAAA,CAAA;AAAA,EACT,OAAA,CAAA;AAAA,EAER,YAAY,OAAkB,EAAA;AAC5B,IAAA,IAAA,CAAK,eAAe,OAAQ,CAAA,YAAA,CAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,OAAQ,CAAA,QAAA,CAAA;AACxB,IAAK,IAAA,CAAA,aAAA,GAAgB,QAAQ,aAAiB,IAAA,uBAAA,CAAA;AAC9C,IAAA,IAAA,CAAK,OAAU,GAAA,EAAA,CAAA;AAAA,GACjB;AAAA,EAEA,MAAM,eAAiD,GAAA;AACrD,IAAI,IAAA,CAAC,KAAK,OAAS,EAAA;AACjB,MAAA,MAAM,QAAW,GAAA,MAAM,IAAK,CAAA,YAAA,CAAa,WAAW,OAAO,CAAA,CAAA;AAC3D,MAAA,IAAA,CAAK,OAAU,GAAA,CAAA,EAAG,QAAQ,CAAA,EAAG,KAAK,aAAa,CAAA,0BAAA,CAAA,CAAA;AAAA,KACjD;AAEA,IAAA,MAAM,eAAsC,EAAC,CAAA;AAC7C,IAAA,IAAI,YAAY,IAAK,CAAA,OAAA,CAAA;AAErB,IAAG,GAAA;AACD,MAAA,MAAM,EAAE,WAAa,EAAA,wBAAA,KACnB,MAAM,IAAA,CAAK,cAAc,SAAS,CAAA,CAAA;AAEpC,MAAA,SAAA,GAAY,WAAe,IAAA,EAAA,CAAA;AAC3B,MAAa,YAAA,CAAA,IAAA,CAAK,GAAG,wBAAwB,CAAA,CAAA;AAAA,KAC/C,QAAS,CAAC,CAAC,SAAA,EAAA;AAEX,IAAA,OAAO,EAAE,YAAa,EAAA,CAAA;AAAA,GACxB;AAAA,EAEA,MAAc,cACZ,SACiC,EAAA;AACjC,IAAA,MAAM,QAAW,GAAA,MAAM,IAAK,CAAA,QAAA,CAAS,MAAM,SAAS,CAAA,CAAA;AAEpD,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAA,IAAI,kBAAqB,GAAA,KAAA,CAAA,CAAA;AACzB,MAAI,IAAA;AACF,QAAA,kBAAA,GAAA,CAAsB,MAAM,QAAA,CAAS,IAAK,EAAA,GAAI,KAAO,EAAA,KAAA,CAAA;AAAA,eAC9C,CAAG,EAAA;AAAA,OAEZ;AAEA,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,oCAAA,EACE,kBAAsB,IAAA,QAAA,CAAS,UACjC,CAAA,CAAA;AAAA,OACF,CAAA;AAAA,KACF;AAEA,IAAM,MAAA,YAAA,GAAgB,MAAM,QAAA,CAAS,IAAK,EAAA,CAAA;AAC1C,IAAA,MAAM,UAAa,GAAA,QAAA,CAAS,OAAQ,CAAA,GAAA,CAAI,MAAM,CAAA,CAAA;AAC9C,IAAM,MAAA,WAAA,GAAc,gBAAgB,UAAU,CAAA,CAAA;AAC9C,IAAM,MAAA,cAAA,GAAiB,aAAa,IAAM,EAAA,IAAA,CAAA;AAE1C,IAAO,OAAA;AAAA,MACL,aAAa,cAAkB,IAAA,CAAA,EAAG,IAAK,CAAA,OAAO,SAAS,cAAc,CAAA,CAAA;AAAA,MACrE,0BAA0B,YAAa,CAAA,YAAA;AAAA,KACzC,CAAA;AAAA,GACF;AACF;;;;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Grid from '@material-ui/core/Grid';
|
|
3
|
+
import NewRelicFetchComponent from '../NewRelicFetchComponent/NewRelicFetchComponent.esm.js';
|
|
4
|
+
import { Page, Header, HeaderLabel, Content, ContentHeader, SupportButton } from '@backstage/core-components';
|
|
5
|
+
|
|
6
|
+
const NewRelicComponent = () => /* @__PURE__ */ React.createElement(Page, { themeId: "tool" }, /* @__PURE__ */ React.createElement(Header, { title: "New Relic" }, /* @__PURE__ */ React.createElement(HeaderLabel, { label: "Owner", value: "Engineering" })), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(ContentHeader, { title: "New Relic" }, /* @__PURE__ */ React.createElement(SupportButton, null, "New Relic Application Performance Monitoring")), /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(NewRelicFetchComponent, null)))));
|
|
7
|
+
var NewRelicComponent$1 = NewRelicComponent;
|
|
8
|
+
|
|
9
|
+
export { NewRelicComponent$1 as default };
|
|
10
|
+
//# sourceMappingURL=NewRelicComponent.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NewRelicComponent.esm.js","sources":["../../../src/components/NewRelicComponent/NewRelicComponent.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport Grid from '@material-ui/core/Grid';\nimport NewRelicFetchComponent from '../NewRelicFetchComponent';\nimport {\n Header,\n Page,\n Content,\n ContentHeader,\n HeaderLabel,\n SupportButton,\n} from '@backstage/core-components';\n\nconst NewRelicComponent = () => (\n <Page themeId=\"tool\">\n <Header title=\"New Relic\">\n <HeaderLabel label=\"Owner\" value=\"Engineering\" />\n </Header>\n <Content>\n <ContentHeader title=\"New Relic\">\n <SupportButton>\n New Relic Application Performance Monitoring\n </SupportButton>\n </ContentHeader>\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <NewRelicFetchComponent />\n </Grid>\n </Grid>\n </Content>\n </Page>\n);\n\nexport default NewRelicComponent;\n"],"names":[],"mappings":";;;;;AA4BA,MAAM,iBAAA,GAAoB,sBACvB,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,SAAQ,MACZ,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAO,KAAM,EAAA,WAAA,EAAA,sCACX,WAAY,EAAA,EAAA,KAAA,EAAM,SAAQ,KAAM,EAAA,aAAA,EAAc,CACjD,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,OACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,aAAc,EAAA,EAAA,KAAA,EAAM,+BAClB,KAAA,CAAA,aAAA,CAAA,aAAA,EAAA,IAAA,EAAc,8CAEf,CACF,CAAA,sCACC,IAAK,EAAA,EAAA,SAAA,EAAS,MAAC,OAAS,EAAA,CAAA,EAAG,WAAU,QACpC,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAK,IAAI,EAAA,IAAA,EAAA,sCACP,sBAAuB,EAAA,IAAA,CAC1B,CACF,CACF,CACF,CAAA,CAAA;AAGF,0BAAe,iBAAA;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import Grid from '@material-ui/core/Grid';
|
|
3
2
|
import Alert from '@material-ui/lab/Alert';
|
|
4
3
|
import useAsync from 'react-use/esm/useAsync';
|
|
5
|
-
import {
|
|
6
|
-
import { Progress, Table
|
|
4
|
+
import { newRelicApiRef } from '../../api/index.esm.js';
|
|
5
|
+
import { Progress, Table } from '@backstage/core-components';
|
|
7
6
|
import { useApi } from '@backstage/core-plugin-api';
|
|
8
|
-
import 'parse-link-header';
|
|
9
7
|
|
|
10
8
|
const sortNumeric = (field) => (a, b) => {
|
|
11
9
|
return a[field] - b[field];
|
|
@@ -88,8 +86,5 @@ const NewRelicFetchComponent = () => {
|
|
|
88
86
|
return /* @__PURE__ */ React.createElement(NewRelicAPMTable, { applications: value || [] });
|
|
89
87
|
};
|
|
90
88
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
export { NewRelicComponent$1 as default };
|
|
95
|
-
//# sourceMappingURL=index-C0wl3iLB.esm.js.map
|
|
89
|
+
export { NewRelicAPMTable, NewRelicFetchComponent as default };
|
|
90
|
+
//# sourceMappingURL=NewRelicFetchComponent.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NewRelicFetchComponent.esm.js","sources":["../../../src/components/NewRelicFetchComponent/NewRelicFetchComponent.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport useAsync from 'react-use/esm/useAsync';\nimport { newRelicApiRef, NewRelicApplications } from '../../api';\n\nimport { Progress, Table, TableColumn } from '@backstage/core-components';\nimport { useApi } from '@backstage/core-plugin-api';\n\nconst sortNumeric =\n <F extends string>(field: F) =>\n (a: { [key in F]: number }, b: { [key in F]: number }) => {\n return a[field] - b[field];\n };\n\ntype NewRelicTableData = {\n name: string;\n responseTime: number;\n throughput: number;\n errorRate: number;\n instanceCount: number;\n apdexScore: number;\n};\n\nexport const NewRelicAPMTable = ({ applications }: NewRelicApplications) => {\n const columns: TableColumn<NewRelicTableData>[] = [\n { title: 'Application', field: 'name', searchable: true },\n {\n title: 'Response Time (ms)',\n field: 'responseTime',\n customSort: sortNumeric('responseTime'),\n searchable: false,\n },\n {\n title: 'Throughput (rpm)',\n field: 'throughput',\n customSort: sortNumeric('throughput'),\n searchable: false,\n },\n {\n title: 'Error Rate (%)',\n field: 'errorRate',\n customSort: sortNumeric('errorRate'),\n searchable: false,\n },\n {\n title: 'Instance Count',\n field: 'instanceCount',\n customSort: sortNumeric('instanceCount'),\n searchable: false,\n },\n {\n title: 'Apdex',\n field: 'apdexScore',\n customSort: sortNumeric('apdexScore'),\n searchable: false,\n },\n ];\n const data: Array<NewRelicTableData> = applications.map(app => {\n const { name, application_summary: applicationSummary } = app;\n const {\n response_time: responseTime,\n throughput,\n error_rate: errorRate,\n instance_count: instanceCount,\n apdex_score: apdexScore,\n } = applicationSummary;\n\n return {\n name,\n responseTime,\n throughput,\n errorRate,\n instanceCount,\n apdexScore,\n };\n });\n\n return (\n <Table\n title=\"Application Performance Monitoring\"\n options={{ search: true, paging: true }}\n columns={columns}\n data={data}\n />\n );\n};\n\nconst NewRelicFetchComponent = () => {\n const api = useApi(newRelicApiRef);\n\n const { value, loading, error } = useAsync(async () => {\n const data = await api.getApplications();\n return data.applications.filter(application => {\n return application.hasOwnProperty('application_summary');\n });\n }, []);\n\n if (loading) {\n return <Progress />;\n } else if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n return <NewRelicAPMTable applications={value || []} />;\n};\n\nexport default NewRelicFetchComponent;\n"],"names":[],"mappings":"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"}
|
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export {
|
|
2
|
-
import '@backstage/core-plugin-api';
|
|
3
|
-
import 'parse-link-header';
|
|
1
|
+
export { NewRelicPage, newRelicPlugin, newRelicPlugin as plugin } from './plugin.esm.js';
|
|
4
2
|
//# sourceMappingURL=index.esm.js.map
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { newRelicApiRef, NewRelicClient } from './api/index.esm.js';
|
|
2
|
+
import { createRouteRef, createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, createRoutableExtension } from '@backstage/core-plugin-api';
|
|
3
|
+
|
|
4
|
+
const rootRouteRef = createRouteRef({
|
|
5
|
+
id: "newrelic"
|
|
6
|
+
});
|
|
7
|
+
const newRelicPlugin = createPlugin({
|
|
8
|
+
id: "newrelic",
|
|
9
|
+
apis: [
|
|
10
|
+
createApiFactory({
|
|
11
|
+
api: newRelicApiRef,
|
|
12
|
+
deps: {
|
|
13
|
+
discoveryApi: discoveryApiRef,
|
|
14
|
+
fetchApi: fetchApiRef
|
|
15
|
+
},
|
|
16
|
+
factory: ({ discoveryApi, fetchApi }) => new NewRelicClient({ discoveryApi, fetchApi })
|
|
17
|
+
})
|
|
18
|
+
],
|
|
19
|
+
routes: {
|
|
20
|
+
root: rootRouteRef
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
const NewRelicPage = newRelicPlugin.provide(
|
|
24
|
+
createRoutableExtension({
|
|
25
|
+
name: "NewRelicPage",
|
|
26
|
+
component: () => import('./components/NewRelicComponent/index.esm.js').then((m) => m.default),
|
|
27
|
+
mountPoint: rootRouteRef
|
|
28
|
+
})
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
export { NewRelicPage, newRelicPlugin, rootRouteRef };
|
|
32
|
+
//# sourceMappingURL=plugin.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { NewRelicClient, newRelicApiRef } from './api';\nimport {\n createApiFactory,\n createPlugin,\n createRouteRef,\n discoveryApiRef,\n fetchApiRef,\n createRoutableExtension,\n} from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n id: 'newrelic',\n});\n\n/** @public */\nexport const newRelicPlugin = createPlugin({\n id: 'newrelic',\n apis: [\n createApiFactory({\n api: newRelicApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ discoveryApi, fetchApi }) =>\n new NewRelicClient({ discoveryApi, fetchApi }),\n }),\n ],\n routes: {\n root: rootRouteRef,\n },\n});\n\n/** @public */\nexport const NewRelicPage = newRelicPlugin.provide(\n createRoutableExtension({\n name: 'NewRelicPage',\n component: () =>\n import('./components/NewRelicComponent').then(m => m.default),\n mountPoint: rootRouteRef,\n }),\n);\n"],"names":[],"mappings":";;;AA0BO,MAAM,eAAe,cAAe,CAAA;AAAA,EACzC,EAAI,EAAA,UAAA;AACN,CAAC,EAAA;AAGM,MAAM,iBAAiB,YAAa,CAAA;AAAA,EACzC,EAAI,EAAA,UAAA;AAAA,EACJ,IAAM,EAAA;AAAA,IACJ,gBAAiB,CAAA;AAAA,MACf,GAAK,EAAA,cAAA;AAAA,MACL,IAAM,EAAA;AAAA,QACJ,YAAc,EAAA,eAAA;AAAA,QACd,QAAU,EAAA,WAAA;AAAA,OACZ;AAAA,MACA,OAAA,EAAS,CAAC,EAAE,YAAc,EAAA,QAAA,EACxB,KAAA,IAAI,cAAe,CAAA,EAAE,YAAc,EAAA,QAAA,EAAU,CAAA;AAAA,KAChD,CAAA;AAAA,GACH;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,YAAA;AAAA,GACR;AACF,CAAC,EAAA;AAGM,MAAM,eAAe,cAAe,CAAA,OAAA;AAAA,EACzC,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,cAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,6CAAgC,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,OAAO,CAAA;AAAA,IAC9D,UAAY,EAAA,YAAA;AAAA,GACb,CAAA;AACH;;;;"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage-community/plugin-newrelic",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.52",
|
|
4
4
|
"description": "A Backstage plugin that integrates towards New Relic",
|
|
5
5
|
"backstage": {
|
|
6
|
-
"role": "frontend-plugin"
|
|
6
|
+
"role": "frontend-plugin",
|
|
7
|
+
"pluginId": "newrelic",
|
|
8
|
+
"pluginPackages": [
|
|
9
|
+
"@backstage-community/plugin-newrelic"
|
|
10
|
+
]
|
|
7
11
|
},
|
|
8
12
|
"publishConfig": {
|
|
9
13
|
"access": "public",
|
|
@@ -37,8 +41,8 @@
|
|
|
37
41
|
"test": "backstage-cli package test"
|
|
38
42
|
},
|
|
39
43
|
"dependencies": {
|
|
40
|
-
"@backstage/core-components": "^0.14.
|
|
41
|
-
"@backstage/core-plugin-api": "^1.9.
|
|
44
|
+
"@backstage/core-components": "^0.14.10",
|
|
45
|
+
"@backstage/core-plugin-api": "^1.9.3",
|
|
42
46
|
"@material-ui/core": "^4.12.2",
|
|
43
47
|
"@material-ui/lab": "4.0.0-alpha.61",
|
|
44
48
|
"@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0",
|
|
@@ -46,9 +50,9 @@
|
|
|
46
50
|
"react-use": "^17.2.4"
|
|
47
51
|
},
|
|
48
52
|
"devDependencies": {
|
|
49
|
-
"@backstage/cli": "^0.
|
|
50
|
-
"@backstage/dev-utils": "^1.0.
|
|
51
|
-
"@backstage/test-utils": "^1.5.
|
|
53
|
+
"@backstage/cli": "^0.27.0",
|
|
54
|
+
"@backstage/dev-utils": "^1.0.37",
|
|
55
|
+
"@backstage/test-utils": "^1.5.10",
|
|
52
56
|
"@testing-library/dom": "^10.0.0",
|
|
53
57
|
"@testing-library/jest-dom": "^6.0.0",
|
|
54
58
|
"@testing-library/react": "^15.0.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-C0wl3iLB.esm.js","sources":["../../src/components/NewRelicFetchComponent/NewRelicFetchComponent.tsx","../../src/components/NewRelicComponent/NewRelicComponent.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport Alert from '@material-ui/lab/Alert';\nimport useAsync from 'react-use/esm/useAsync';\nimport { newRelicApiRef, NewRelicApplications } from '../../api';\n\nimport { Progress, Table, TableColumn } from '@backstage/core-components';\nimport { useApi } from '@backstage/core-plugin-api';\n\nconst sortNumeric =\n <F extends string>(field: F) =>\n (a: { [key in F]: number }, b: { [key in F]: number }) => {\n return a[field] - b[field];\n };\n\ntype NewRelicTableData = {\n name: string;\n responseTime: number;\n throughput: number;\n errorRate: number;\n instanceCount: number;\n apdexScore: number;\n};\n\nexport const NewRelicAPMTable = ({ applications }: NewRelicApplications) => {\n const columns: TableColumn<NewRelicTableData>[] = [\n { title: 'Application', field: 'name', searchable: true },\n {\n title: 'Response Time (ms)',\n field: 'responseTime',\n customSort: sortNumeric('responseTime'),\n searchable: false,\n },\n {\n title: 'Throughput (rpm)',\n field: 'throughput',\n customSort: sortNumeric('throughput'),\n searchable: false,\n },\n {\n title: 'Error Rate (%)',\n field: 'errorRate',\n customSort: sortNumeric('errorRate'),\n searchable: false,\n },\n {\n title: 'Instance Count',\n field: 'instanceCount',\n customSort: sortNumeric('instanceCount'),\n searchable: false,\n },\n {\n title: 'Apdex',\n field: 'apdexScore',\n customSort: sortNumeric('apdexScore'),\n searchable: false,\n },\n ];\n const data: Array<NewRelicTableData> = applications.map(app => {\n const { name, application_summary: applicationSummary } = app;\n const {\n response_time: responseTime,\n throughput,\n error_rate: errorRate,\n instance_count: instanceCount,\n apdex_score: apdexScore,\n } = applicationSummary;\n\n return {\n name,\n responseTime,\n throughput,\n errorRate,\n instanceCount,\n apdexScore,\n };\n });\n\n return (\n <Table\n title=\"Application Performance Monitoring\"\n options={{ search: true, paging: true }}\n columns={columns}\n data={data}\n />\n );\n};\n\nconst NewRelicFetchComponent = () => {\n const api = useApi(newRelicApiRef);\n\n const { value, loading, error } = useAsync(async () => {\n const data = await api.getApplications();\n return data.applications.filter(application => {\n return application.hasOwnProperty('application_summary');\n });\n }, []);\n\n if (loading) {\n return <Progress />;\n } else if (error) {\n return <Alert severity=\"error\">{error.message}</Alert>;\n }\n\n return <NewRelicAPMTable applications={value || []} />;\n};\n\nexport default NewRelicFetchComponent;\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport Grid from '@material-ui/core/Grid';\nimport NewRelicFetchComponent from '../NewRelicFetchComponent';\nimport {\n Header,\n Page,\n Content,\n ContentHeader,\n HeaderLabel,\n SupportButton,\n} from '@backstage/core-components';\n\nconst NewRelicComponent = () => (\n <Page themeId=\"tool\">\n <Header title=\"New Relic\">\n <HeaderLabel label=\"Owner\" value=\"Engineering\" />\n </Header>\n <Content>\n <ContentHeader title=\"New Relic\">\n <SupportButton>\n New Relic Application Performance Monitoring\n </SupportButton>\n </ContentHeader>\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <NewRelicFetchComponent />\n </Grid>\n </Grid>\n </Content>\n </Page>\n);\n\nexport default NewRelicComponent;\n"],"names":[],"mappings":"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"}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { createApiRef, createRouteRef, createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, createRoutableExtension } from '@backstage/core-plugin-api';
|
|
2
|
-
import parseLinkHeader from 'parse-link-header';
|
|
3
|
-
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
-
var __publicField = (obj, key, value) => {
|
|
7
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
8
|
-
return value;
|
|
9
|
-
};
|
|
10
|
-
const newRelicApiRef = createApiRef({
|
|
11
|
-
id: "plugin.newrelic.service"
|
|
12
|
-
});
|
|
13
|
-
const DEFAULT_PROXY_PATH_BASE = "/newrelic";
|
|
14
|
-
class NewRelicClient {
|
|
15
|
-
constructor(options) {
|
|
16
|
-
__publicField(this, "discoveryApi");
|
|
17
|
-
__publicField(this, "fetchApi");
|
|
18
|
-
__publicField(this, "proxyPathBase");
|
|
19
|
-
__publicField(this, "baseUrl");
|
|
20
|
-
var _a;
|
|
21
|
-
this.discoveryApi = options.discoveryApi;
|
|
22
|
-
this.fetchApi = options.fetchApi;
|
|
23
|
-
this.proxyPathBase = (_a = options.proxyPathBase) != null ? _a : DEFAULT_PROXY_PATH_BASE;
|
|
24
|
-
this.baseUrl = "";
|
|
25
|
-
}
|
|
26
|
-
async getApplications() {
|
|
27
|
-
if (!this.baseUrl) {
|
|
28
|
-
const proxyUrl = await this.discoveryApi.getBaseUrl("proxy");
|
|
29
|
-
this.baseUrl = `${proxyUrl}${this.proxyPathBase}/apm/api/applications.json`;
|
|
30
|
-
}
|
|
31
|
-
const applications = [];
|
|
32
|
-
let targetUrl = this.baseUrl;
|
|
33
|
-
do {
|
|
34
|
-
const { nextPageUrl, applicationsFromReadPage } = await this.fetchNewRelic(targetUrl);
|
|
35
|
-
targetUrl = nextPageUrl != null ? nextPageUrl : "";
|
|
36
|
-
applications.push(...applicationsFromReadPage);
|
|
37
|
-
} while (!!targetUrl);
|
|
38
|
-
return { applications };
|
|
39
|
-
}
|
|
40
|
-
async fetchNewRelic(targetUrl) {
|
|
41
|
-
var _a, _b, _c;
|
|
42
|
-
const response = await this.fetchApi.fetch(targetUrl);
|
|
43
|
-
if (!response.ok) {
|
|
44
|
-
let specificErrorTitle = void 0;
|
|
45
|
-
try {
|
|
46
|
-
specificErrorTitle = (_b = (_a = await response.json()) == null ? void 0 : _a.error) == null ? void 0 : _b.title;
|
|
47
|
-
} catch (e) {
|
|
48
|
-
}
|
|
49
|
-
throw new Error(
|
|
50
|
-
`Error communicating with New Relic: ${specificErrorTitle || response.statusText}`
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
const readResponse = await response.json();
|
|
54
|
-
const linkHeader = response.headers.get("link");
|
|
55
|
-
const parseResult = parseLinkHeader(linkHeader);
|
|
56
|
-
const nextPageNumber = (_c = parseResult == null ? void 0 : parseResult.next) == null ? void 0 : _c.page;
|
|
57
|
-
return {
|
|
58
|
-
nextPageUrl: nextPageNumber && `${this.baseUrl}?page=${nextPageNumber}`,
|
|
59
|
-
applicationsFromReadPage: readResponse.applications
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const rootRouteRef = createRouteRef({
|
|
65
|
-
id: "newrelic"
|
|
66
|
-
});
|
|
67
|
-
const newRelicPlugin = createPlugin({
|
|
68
|
-
id: "newrelic",
|
|
69
|
-
apis: [
|
|
70
|
-
createApiFactory({
|
|
71
|
-
api: newRelicApiRef,
|
|
72
|
-
deps: {
|
|
73
|
-
discoveryApi: discoveryApiRef,
|
|
74
|
-
fetchApi: fetchApiRef
|
|
75
|
-
},
|
|
76
|
-
factory: ({ discoveryApi, fetchApi }) => new NewRelicClient({ discoveryApi, fetchApi })
|
|
77
|
-
})
|
|
78
|
-
],
|
|
79
|
-
routes: {
|
|
80
|
-
root: rootRouteRef
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
const NewRelicPage = newRelicPlugin.provide(
|
|
84
|
-
createRoutableExtension({
|
|
85
|
-
name: "NewRelicPage",
|
|
86
|
-
component: () => import('./index-C0wl3iLB.esm.js').then((m) => m.default),
|
|
87
|
-
mountPoint: rootRouteRef
|
|
88
|
-
})
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
export { NewRelicPage as N, newRelicPlugin as a, newRelicApiRef as n };
|
|
92
|
-
//# sourceMappingURL=index-DhuyBTi3.esm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-DhuyBTi3.esm.js","sources":["../../src/api/index.ts","../../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createApiRef,\n DiscoveryApi,\n FetchApi,\n} from '@backstage/core-plugin-api';\n\nimport parseLinkHeader from 'parse-link-header';\n\nexport type NewRelicApplication = {\n id: number;\n application_summary: NewRelicApplicationSummary;\n name: string;\n language: string;\n health_status: string;\n reporting: boolean;\n settings: NewRelicApplicationSettings;\n links?: NewRelicApplicationLinks;\n};\n\nexport type NewRelicApplicationSummary = {\n apdex_score: number;\n error_rate: number;\n host_count: number;\n instance_count: number;\n response_time: number;\n throughput: number;\n};\n\nexport type NewRelicApplicationSettings = {\n app_apdex_threshold: number;\n end_user_apdex_threshold: number;\n enable_real_user_monitoring: boolean;\n use_server_side_config: boolean;\n};\n\nexport type NewRelicApplicationLinks = {\n application_instances: Array<any>;\n servers: Array<any>;\n application_hosts: Array<any>;\n};\n\nexport type NewRelicApplications = {\n applications: NewRelicApplication[];\n};\n\nexport const newRelicApiRef = createApiRef<NewRelicApi>({\n id: 'plugin.newrelic.service',\n});\n\nconst DEFAULT_PROXY_PATH_BASE = '/newrelic';\n\ntype Options = {\n discoveryApi: DiscoveryApi;\n fetchApi: FetchApi;\n /**\n * Path to use for requests via the proxy, defaults to /newrelic\n */\n proxyPathBase?: string;\n};\n\nexport interface NewRelicApi {\n getApplications(): Promise<NewRelicApplications>;\n}\n\ninterface NewRelicPageReadResult {\n nextPageUrl: string | undefined;\n applicationsFromReadPage: NewRelicApplication[];\n}\n\nexport class NewRelicClient implements NewRelicApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n private readonly proxyPathBase: string;\n private baseUrl: string;\n\n constructor(options: Options) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi;\n this.proxyPathBase = options.proxyPathBase ?? DEFAULT_PROXY_PATH_BASE;\n this.baseUrl = '';\n }\n\n async getApplications(): Promise<NewRelicApplications> {\n if (!this.baseUrl) {\n const proxyUrl = await this.discoveryApi.getBaseUrl('proxy');\n this.baseUrl = `${proxyUrl}${this.proxyPathBase}/apm/api/applications.json`;\n }\n\n const applications: NewRelicApplication[] = [];\n let targetUrl = this.baseUrl;\n\n do {\n const { nextPageUrl, applicationsFromReadPage } =\n await this.fetchNewRelic(targetUrl);\n\n targetUrl = nextPageUrl ?? '';\n applications.push(...applicationsFromReadPage);\n } while (!!targetUrl);\n\n return { applications };\n }\n\n private async fetchNewRelic(\n targetUrl: string,\n ): Promise<NewRelicPageReadResult> {\n const response = await this.fetchApi.fetch(targetUrl);\n\n if (!response.ok) {\n let specificErrorTitle = undefined;\n try {\n specificErrorTitle = (await response.json())?.error?.title;\n } catch (e) {\n /* empty */\n }\n\n throw new Error(\n `Error communicating with New Relic: ${\n specificErrorTitle || response.statusText\n }`,\n );\n }\n\n const readResponse = (await response.json()) as NewRelicApplications;\n const linkHeader = response.headers.get('link');\n const parseResult = parseLinkHeader(linkHeader);\n const nextPageNumber = parseResult?.next?.page;\n\n return {\n nextPageUrl: nextPageNumber && `${this.baseUrl}?page=${nextPageNumber}`,\n applicationsFromReadPage: readResponse.applications,\n };\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { NewRelicClient, newRelicApiRef } from './api';\nimport {\n createApiFactory,\n createPlugin,\n createRouteRef,\n discoveryApiRef,\n fetchApiRef,\n createRoutableExtension,\n} from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n id: 'newrelic',\n});\n\n/** @public */\nexport const newRelicPlugin = createPlugin({\n id: 'newrelic',\n apis: [\n createApiFactory({\n api: newRelicApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ discoveryApi, fetchApi }) =>\n new NewRelicClient({ discoveryApi, fetchApi }),\n }),\n ],\n routes: {\n root: rootRouteRef,\n },\n});\n\n/** @public */\nexport const NewRelicPage = newRelicPlugin.provide(\n createRoutableExtension({\n name: 'NewRelicPage',\n component: () =>\n import('./components/NewRelicComponent').then(m => m.default),\n mountPoint: rootRouteRef,\n }),\n);\n"],"names":[],"mappings":"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"}
|