@anyshift/backstage-plugin-anyshift 0.1.0-beta.20 → 0.1.0-beta.21
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/LICENSE +1 -0
- package/README.md +3 -11
- package/dist/api/AnyshiftApi.esm.js +5 -56
- package/dist/api/AnyshiftApi.esm.js.map +1 -1
- package/dist/components/cloud/CloudResourceContent.esm.js +45 -444
- package/dist/components/cloud/CloudResourceContent.esm.js.map +1 -1
- package/dist/components/entity/AnyshiftEntityContent.esm.js +23 -128
- package/dist/components/entity/AnyshiftEntityContent.esm.js.map +1 -1
- package/dist/components/entity/BriefSections.esm.js +4 -24
- package/dist/components/entity/BriefSections.esm.js.map +1 -1
- package/dist/components/entity/DatadogLiveSignal.esm.js +23 -85
- package/dist/components/entity/DatadogLiveSignal.esm.js.map +1 -1
- package/dist/components/entity/MermaidArchitecture.esm.js +43 -202
- package/dist/components/entity/MermaidArchitecture.esm.js.map +1 -1
- package/dist/components/entity/SectionPresenters.esm.js +82 -145
- package/dist/components/entity/SectionPresenters.esm.js.map +1 -1
- package/dist/components/entity/architectureDiagram.esm.js +15 -48
- package/dist/components/entity/architectureDiagram.esm.js.map +1 -1
- package/dist/components/explorer/AnyshiftExplorerPage.esm.js +19 -154
- package/dist/components/explorer/AnyshiftExplorerPage.esm.js.map +1 -1
- package/dist/components/explorer/DatadogOperationsRadar.esm.js +31 -92
- package/dist/components/explorer/DatadogOperationsRadar.esm.js.map +1 -1
- package/dist/index.d.ts +4 -18
- package/dist/index.esm.js +1 -1
- package/dist/package.json.esm.js +13 -13
- package/dist/plugin.esm.js +2 -6
- package/dist/plugin.esm.js.map +1 -1
- package/package.json +15 -15
- package/CHANGELOG.md +0 -87
- package/dist/components/ask/AskAnyshiftCard.esm.js +0 -348
- package/dist/components/ask/AskAnyshiftCard.esm.js.map +0 -1
- package/dist/components/ask/askPresenters.esm.js +0 -1203
- package/dist/components/ask/askPresenters.esm.js.map +0 -1
- package/dist/components/ask/askScope.esm.js +0 -27
- package/dist/components/ask/askScope.esm.js.map +0 -1
- package/dist/components/ask/askSuggestions.esm.js +0 -41
- package/dist/components/ask/askSuggestions.esm.js.map +0 -1
- package/dist/components/cloud/CloudImpactSection.esm.js +0 -54
- package/dist/components/cloud/CloudImpactSection.esm.js.map +0 -1
- package/dist/components/cloud/CloudRelationshipSections.esm.js +0 -43
- package/dist/components/cloud/CloudRelationshipSections.esm.js.map +0 -1
- package/dist/components/entity/ArchitectureOperationDetails.esm.js +0 -107
- package/dist/components/entity/ArchitectureOperationDetails.esm.js.map +0 -1
- package/dist/components/entity/architectureGraph.esm.js +0 -145
- package/dist/components/entity/architectureGraph.esm.js.map +0 -1
- package/dist/components/entity/entityIdentity.esm.js +0 -40
- package/dist/components/entity/entityIdentity.esm.js.map +0 -1
- package/dist/components/entity/relatedCatalogEntities.esm.js +0 -60
- package/dist/components/entity/relatedCatalogEntities.esm.js.map +0 -1
|
@@ -1,39 +1,21 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import { useState, useRef, useCallback, useEffect
|
|
2
|
+
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
3
3
|
import { Typography, Box, Chip, Button, CircularProgress, Grid } from '@material-ui/core';
|
|
4
4
|
import { Progress } from '@backstage/core-components';
|
|
5
|
-
import { useApi
|
|
6
|
-
import { ANYSHIFT_KIND_ANNOTATION,
|
|
7
|
-
import { useEntity
|
|
5
|
+
import { useApi } from '@backstage/frontend-plugin-api';
|
|
6
|
+
import { ANYSHIFT_KIND_ANNOTATION, ANYSHIFT_TARGET_ANNOTATION, GITHUB_PROJECT_SLUG_ANNOTATION } from '@anyshift/backstage-plugin-anyshift-common';
|
|
7
|
+
import { useEntity } from '@backstage/plugin-catalog-react';
|
|
8
8
|
import { anyshiftApiRef } from '../../api/AnyshiftApi.esm.js';
|
|
9
|
-
import {
|
|
10
|
-
import { askScopeForEntity } from '../ask/askScope.esm.js';
|
|
11
|
-
import { CloudAnyshiftEntityContent } from '../cloud/CloudResourceContent.esm.js';
|
|
12
|
-
import { isCloudResourceEntity, entityTarget } from './entityIdentity.esm.js';
|
|
13
|
-
import { resolveRelatedCatalogEntities } from './relatedCatalogEntities.esm.js';
|
|
14
|
-
import { OverviewSection, WhyNowSection, DatadogSignalSection, ArchitectureSection, DependencySection, BriefRail, TimelineSection } from './BriefSections.esm.js';
|
|
9
|
+
import { OverviewSection, DatadogSignalSection, ArchitectureSection, DependencySection, BriefRail, TimelineSection } from './BriefSections.esm.js';
|
|
15
10
|
|
|
16
11
|
const AnyshiftEntityContent = () => {
|
|
17
|
-
const { entity } = useEntity();
|
|
18
|
-
return isCloudResourceEntity(entity) ? /* @__PURE__ */ jsx(CloudAnyshiftEntityContent, {}) : /* @__PURE__ */ jsx(ServiceAnyshiftEntityContent, {});
|
|
19
|
-
};
|
|
20
|
-
const ServiceAnyshiftEntityContent = () => {
|
|
21
12
|
const { entity } = useEntity();
|
|
22
13
|
const api = useApi(anyshiftApiRef);
|
|
23
|
-
const catalogApi = useApiHolder().get(catalogApiRef);
|
|
24
14
|
const annotations = entity.metadata.annotations ?? {};
|
|
25
15
|
const target = entityTarget(entity);
|
|
26
16
|
const kind = annotations[ANYSHIFT_KIND_ANNOTATION] || "workload";
|
|
27
17
|
const namespace = entity.metadata.namespace;
|
|
28
|
-
const configurationEndpoints = annotations[ANYSHIFT_CONFIGURATION_ENDPOINTS_ANNOTATION];
|
|
29
|
-
const configurationDependencies = annotations[ANYSHIFT_CONFIGURATION_DEPENDENCIES_ANNOTATION];
|
|
30
|
-
const configurationTarget = annotations[ANYSHIFT_RUNTIME_RESOURCE_ID_ANNOTATION] ?? annotations[ANYSHIFT_RESOURCE_ID_ANNOTATION];
|
|
31
18
|
const [brief, setBrief] = useState();
|
|
32
|
-
const [catalogEntities, setCatalogEntities] = useState([]);
|
|
33
|
-
const [capabilities, setCapabilities] = useState({
|
|
34
|
-
askEnabled: false,
|
|
35
|
-
queryEnabled: false
|
|
36
|
-
});
|
|
37
19
|
const [error, setError] = useState();
|
|
38
20
|
const [refreshingAll, setRefreshingAll] = useState(false);
|
|
39
21
|
const [refreshing, setRefreshing] = useState(
|
|
@@ -45,13 +27,7 @@ const ServiceAnyshiftEntityContent = () => {
|
|
|
45
27
|
setError(void 0);
|
|
46
28
|
if (refresh) setRefreshingAll(true);
|
|
47
29
|
try {
|
|
48
|
-
const next = await api.brief(kind, target, {
|
|
49
|
-
namespace,
|
|
50
|
-
refresh,
|
|
51
|
-
configurationEndpoints,
|
|
52
|
-
configurationDependencies,
|
|
53
|
-
configurationTarget
|
|
54
|
-
});
|
|
30
|
+
const next = await api.brief(kind, target, { namespace, refresh });
|
|
55
31
|
if (active.current) setBrief(next);
|
|
56
32
|
} catch (cause) {
|
|
57
33
|
if (active.current)
|
|
@@ -60,15 +36,7 @@ const ServiceAnyshiftEntityContent = () => {
|
|
|
60
36
|
if (active.current) setRefreshingAll(false);
|
|
61
37
|
}
|
|
62
38
|
},
|
|
63
|
-
[
|
|
64
|
-
api,
|
|
65
|
-
configurationDependencies,
|
|
66
|
-
configurationEndpoints,
|
|
67
|
-
configurationTarget,
|
|
68
|
-
kind,
|
|
69
|
-
namespace,
|
|
70
|
-
target
|
|
71
|
-
]
|
|
39
|
+
[api, kind, namespace, target]
|
|
72
40
|
);
|
|
73
41
|
const retrySection = useCallback(
|
|
74
42
|
async (section) => {
|
|
@@ -76,10 +44,7 @@ const ServiceAnyshiftEntityContent = () => {
|
|
|
76
44
|
try {
|
|
77
45
|
const response = await api.briefSection(kind, target, section, {
|
|
78
46
|
namespace,
|
|
79
|
-
refresh: true
|
|
80
|
-
configurationEndpoints,
|
|
81
|
-
configurationDependencies,
|
|
82
|
-
configurationTarget
|
|
47
|
+
refresh: true
|
|
83
48
|
});
|
|
84
49
|
if (active.current) {
|
|
85
50
|
setBrief(
|
|
@@ -101,15 +66,7 @@ const ServiceAnyshiftEntityContent = () => {
|
|
|
101
66
|
}
|
|
102
67
|
}
|
|
103
68
|
},
|
|
104
|
-
[
|
|
105
|
-
api,
|
|
106
|
-
configurationDependencies,
|
|
107
|
-
configurationEndpoints,
|
|
108
|
-
configurationTarget,
|
|
109
|
-
kind,
|
|
110
|
-
namespace,
|
|
111
|
-
target
|
|
112
|
-
]
|
|
69
|
+
[api, kind, namespace, target]
|
|
113
70
|
);
|
|
114
71
|
useEffect(() => {
|
|
115
72
|
active.current = true;
|
|
@@ -118,71 +75,28 @@ const ServiceAnyshiftEntityContent = () => {
|
|
|
118
75
|
active.current = false;
|
|
119
76
|
};
|
|
120
77
|
}, [load]);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (!catalogApi) {
|
|
124
|
-
setCatalogEntities([]);
|
|
125
|
-
return () => {
|
|
126
|
-
cancelled = true;
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
catalogApi.getEntities({
|
|
130
|
-
filter: [{ kind: "Component" }, { kind: "Resource" }],
|
|
131
|
-
fields: ["kind", "metadata.name", "metadata.namespace"]
|
|
132
|
-
}).then((response) => {
|
|
133
|
-
if (!cancelled) setCatalogEntities(response.items);
|
|
134
|
-
}).catch(() => {
|
|
135
|
-
if (!cancelled) setCatalogEntities([]);
|
|
136
|
-
});
|
|
137
|
-
return () => {
|
|
138
|
-
cancelled = true;
|
|
139
|
-
};
|
|
140
|
-
}, [catalogApi]);
|
|
141
|
-
useEffect(() => {
|
|
142
|
-
api.capabilities().then((next) => {
|
|
143
|
-
if (active.current) setCapabilities(next);
|
|
144
|
-
}).catch(() => {
|
|
145
|
-
if (active.current) {
|
|
146
|
-
setCapabilities({ askEnabled: false, queryEnabled: false });
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
}, [api]);
|
|
150
|
-
const resolvedBrief = useMemo(() => {
|
|
151
|
-
if (!brief || brief.impact.state !== "data" || !brief.impact.data)
|
|
152
|
-
return brief;
|
|
153
|
-
const impactData = brief.impact.data;
|
|
154
|
-
return {
|
|
155
|
-
...brief,
|
|
156
|
-
impact: {
|
|
157
|
-
...brief.impact,
|
|
158
|
-
data: {
|
|
159
|
-
...impactData,
|
|
160
|
-
relatedEntities: resolveRelatedCatalogEntities(
|
|
161
|
-
impactData.relatedEntities,
|
|
162
|
-
catalogEntities
|
|
163
|
-
)
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
}, [brief, catalogEntities]);
|
|
168
|
-
if (error && !resolvedBrief)
|
|
169
|
-
return /* @__PURE__ */ jsx(Typography, { color: "error", children: error });
|
|
170
|
-
if (!resolvedBrief) return /* @__PURE__ */ jsx(Progress, {});
|
|
78
|
+
if (error && !brief) return /* @__PURE__ */ jsx(Typography, { color: "error", children: error });
|
|
79
|
+
if (!brief) return /* @__PURE__ */ jsx(Progress, {});
|
|
171
80
|
return /* @__PURE__ */ jsx(
|
|
172
81
|
ServiceBriefView,
|
|
173
82
|
{
|
|
174
|
-
brief
|
|
83
|
+
brief,
|
|
175
84
|
onRetry: retrySection,
|
|
176
85
|
refreshing,
|
|
177
86
|
onRefresh: () => void load(true),
|
|
178
87
|
refreshingAll,
|
|
179
|
-
refreshError: error
|
|
180
|
-
askEnabled: capabilities.askEnabled,
|
|
181
|
-
askScope: askScopeForEntity(entity),
|
|
182
|
-
askScopeLabel: target
|
|
88
|
+
refreshError: error
|
|
183
89
|
}
|
|
184
90
|
);
|
|
185
91
|
};
|
|
92
|
+
function entityTarget(entity) {
|
|
93
|
+
const annotations = entity.metadata.annotations ?? {};
|
|
94
|
+
const explicit = annotations[ANYSHIFT_TARGET_ANNOTATION]?.trim();
|
|
95
|
+
if (explicit) return explicit;
|
|
96
|
+
const slug = annotations[GITHUB_PROJECT_SLUG_ANNOTATION]?.trim();
|
|
97
|
+
const repository = slug?.split("/").filter(Boolean).at(-1);
|
|
98
|
+
return repository || entity.metadata.name;
|
|
99
|
+
}
|
|
186
100
|
const ServiceBriefView = ({
|
|
187
101
|
brief,
|
|
188
102
|
onRetry,
|
|
@@ -190,10 +104,7 @@ const ServiceBriefView = ({
|
|
|
190
104
|
onRefresh = () => {
|
|
191
105
|
},
|
|
192
106
|
refreshingAll = false,
|
|
193
|
-
refreshError
|
|
194
|
-
askEnabled = false,
|
|
195
|
-
askScope,
|
|
196
|
-
askScopeLabel
|
|
107
|
+
refreshError
|
|
197
108
|
}) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
198
109
|
/* @__PURE__ */ jsxs(
|
|
199
110
|
Box,
|
|
@@ -258,22 +169,6 @@ const ServiceBriefView = ({
|
|
|
258
169
|
refreshing: refreshing.has("overview")
|
|
259
170
|
}
|
|
260
171
|
) }),
|
|
261
|
-
/* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
|
|
262
|
-
WhyNowSection,
|
|
263
|
-
{
|
|
264
|
-
section: brief.whyNow,
|
|
265
|
-
onRetry,
|
|
266
|
-
refreshing: refreshing.has("whyNow")
|
|
267
|
-
}
|
|
268
|
-
) }),
|
|
269
|
-
askEnabled && /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
|
|
270
|
-
AskAnyshiftCard,
|
|
271
|
-
{
|
|
272
|
-
context: "entity",
|
|
273
|
-
scope: askScope,
|
|
274
|
-
scopeLabel: askScopeLabel
|
|
275
|
-
}
|
|
276
|
-
) }),
|
|
277
172
|
/* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
|
|
278
173
|
DatadogSignalSection,
|
|
279
174
|
{
|
|
@@ -314,5 +209,5 @@ function formatTimestamp(value) {
|
|
|
314
209
|
return Number.isNaN(parsed) ? value : new Date(parsed).toLocaleString();
|
|
315
210
|
}
|
|
316
211
|
|
|
317
|
-
export { AnyshiftEntityContent,
|
|
212
|
+
export { AnyshiftEntityContent, ServiceBriefView, entityTarget };
|
|
318
213
|
//# sourceMappingURL=AnyshiftEntityContent.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnyshiftEntityContent.esm.js","sources":["../../../src/components/entity/AnyshiftEntityContent.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Box,\n Button,\n Chip,\n CircularProgress,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport { Progress } from '@backstage/core-components';\nimport { useApi, useApiHolder } from '@backstage/frontend-plugin-api';\nimport type { Entity } from '@backstage/catalog-model';\nimport {\n ANYSHIFT_CONFIGURATION_DEPENDENCIES_ANNOTATION,\n ANYSHIFT_CONFIGURATION_ENDPOINTS_ANNOTATION,\n ANYSHIFT_KIND_ANNOTATION,\n ANYSHIFT_RESOURCE_ID_ANNOTATION,\n ANYSHIFT_RUNTIME_RESOURCE_ID_ANNOTATION,\n} from '@anyshift/backstage-plugin-anyshift-common';\nimport { catalogApiRef, useEntity } from '@backstage/plugin-catalog-react';\nimport { anyshiftApiRef } from '../../api/AnyshiftApi';\nimport type {\n AnyshiftCapabilities,\n AskScope,\n BriefSectionName,\n ServiceBrief,\n} from '../../api/types';\nimport { AskAnyshiftCard } from '../ask/AskAnyshiftCard';\nimport { askScopeForEntity } from '../ask/askScope';\nimport { CloudAnyshiftEntityContent } from '../cloud/CloudResourceContent';\nimport { entityTarget, isCloudResourceEntity } from './entityIdentity';\nimport { resolveRelatedCatalogEntities } from './relatedCatalogEntities';\nimport {\n ArchitectureSection,\n BriefRail,\n DatadogSignalSection,\n DependencySection,\n OverviewSection,\n TimelineSection,\n WhyNowSection,\n} from './BriefSections';\n\nexport const AnyshiftEntityContent = () => {\n const { entity } = useEntity();\n return isCloudResourceEntity(entity) ? (\n <CloudAnyshiftEntityContent />\n ) : (\n <ServiceAnyshiftEntityContent />\n );\n};\n\nexport const ServiceAnyshiftEntityContent = () => {\n const { entity } = useEntity();\n const api = useApi(anyshiftApiRef);\n const catalogApi = useApiHolder().get(catalogApiRef);\n const annotations = entity.metadata.annotations ?? {};\n const target = entityTarget(entity);\n const kind = annotations[ANYSHIFT_KIND_ANNOTATION] || 'workload';\n const namespace = entity.metadata.namespace;\n const configurationEndpoints =\n annotations[ANYSHIFT_CONFIGURATION_ENDPOINTS_ANNOTATION];\n const configurationDependencies =\n annotations[ANYSHIFT_CONFIGURATION_DEPENDENCIES_ANNOTATION];\n const configurationTarget =\n annotations[ANYSHIFT_RUNTIME_RESOURCE_ID_ANNOTATION] ??\n annotations[ANYSHIFT_RESOURCE_ID_ANNOTATION];\n const [brief, setBrief] = useState<ServiceBrief>();\n const [catalogEntities, setCatalogEntities] = useState<Entity[]>([]);\n const [capabilities, setCapabilities] = useState<AnyshiftCapabilities>({\n askEnabled: false,\n queryEnabled: false,\n });\n const [error, setError] = useState<string>();\n const [refreshingAll, setRefreshingAll] = useState(false);\n const [refreshing, setRefreshing] = useState<Set<BriefSectionName>>(\n new Set(),\n );\n const active = useRef(true);\n\n const load = useCallback(\n async (refresh = false) => {\n setError(undefined);\n if (refresh) setRefreshingAll(true);\n try {\n const next = await api.brief(kind, target, {\n namespace,\n refresh,\n configurationEndpoints,\n configurationDependencies,\n configurationTarget,\n });\n if (active.current) setBrief(next);\n } catch (cause) {\n if (active.current)\n setError(cause instanceof Error ? cause.message : String(cause));\n } finally {\n if (active.current) setRefreshingAll(false);\n }\n },\n [\n api,\n configurationDependencies,\n configurationEndpoints,\n configurationTarget,\n kind,\n namespace,\n target,\n ],\n );\n\n const retrySection = useCallback(\n async (section: BriefSectionName) => {\n setRefreshing(current => new Set(current).add(section));\n try {\n const response = await api.briefSection(kind, target, section, {\n namespace,\n refresh: true,\n configurationEndpoints,\n configurationDependencies,\n configurationTarget,\n });\n if (active.current) {\n setBrief(current =>\n current\n ? {\n ...current,\n [section]: response.value,\n refreshedAt: response.refreshedAt,\n ...(response.observedService\n ? { observedService: response.observedService }\n : {}),\n }\n : current,\n );\n }\n } finally {\n if (active.current) {\n setRefreshing(current => {\n const next = new Set(current);\n next.delete(section);\n return next;\n });\n }\n }\n },\n [\n api,\n configurationDependencies,\n configurationEndpoints,\n configurationTarget,\n kind,\n namespace,\n target,\n ],\n );\n\n useEffect(() => {\n active.current = true;\n void load();\n return () => {\n active.current = false;\n };\n }, [load]);\n\n useEffect(() => {\n let cancelled = false;\n if (!catalogApi) {\n setCatalogEntities([]);\n return () => {\n cancelled = true;\n };\n }\n catalogApi\n .getEntities({\n filter: [{ kind: 'Component' }, { kind: 'Resource' }],\n fields: ['kind', 'metadata.name', 'metadata.namespace'],\n })\n .then(response => {\n if (!cancelled) setCatalogEntities(response.items);\n })\n .catch(() => {\n if (!cancelled) setCatalogEntities([]);\n });\n return () => {\n cancelled = true;\n };\n }, [catalogApi]);\n\n useEffect(() => {\n api\n .capabilities()\n .then(next => {\n if (active.current) setCapabilities(next);\n })\n .catch(() => {\n if (active.current) {\n setCapabilities({ askEnabled: false, queryEnabled: false });\n }\n });\n }, [api]);\n\n const resolvedBrief = useMemo<ServiceBrief | undefined>(() => {\n if (!brief || brief.impact.state !== 'data' || !brief.impact.data)\n return brief;\n const impactData = brief.impact.data;\n return {\n ...brief,\n impact: {\n ...brief.impact,\n data: {\n ...impactData,\n relatedEntities: resolveRelatedCatalogEntities(\n impactData.relatedEntities,\n catalogEntities,\n ),\n },\n },\n };\n }, [brief, catalogEntities]);\n\n if (error && !resolvedBrief)\n return <Typography color=\"error\">{error}</Typography>;\n if (!resolvedBrief) return <Progress />;\n return (\n <ServiceBriefView\n brief={resolvedBrief}\n onRetry={retrySection}\n refreshing={refreshing}\n onRefresh={() => void load(true)}\n refreshingAll={refreshingAll}\n refreshError={error}\n askEnabled={capabilities.askEnabled}\n askScope={askScopeForEntity(entity)}\n askScopeLabel={target}\n />\n );\n};\n\nexport const ServiceBriefView = ({\n brief,\n onRetry,\n refreshing = new Set(),\n onRefresh = () => {},\n refreshingAll = false,\n refreshError,\n askEnabled = false,\n askScope,\n askScopeLabel,\n}: {\n brief: ServiceBrief;\n onRetry: (section: BriefSectionName) => void;\n refreshing?: ReadonlySet<BriefSectionName>;\n onRefresh?: () => void;\n refreshingAll?: boolean;\n refreshError?: string;\n askEnabled?: boolean;\n askScope?: AskScope;\n askScopeLabel?: string;\n}) => (\n <>\n <Box\n mb={3}\n px={2.5}\n py={2}\n borderLeft={4}\n borderColor=\"primary.main\"\n bgcolor=\"background.paper\"\n >\n <Box display=\"flex\" justifyContent=\"space-between\" gridGap={16}>\n <Box>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Anyshift evidence trace\n </Typography>\n <Box display=\"flex\" flexWrap=\"wrap\" alignItems=\"center\" gridGap={8}>\n <Chip size=\"small\" label={`Workload · ${brief.target}`} />\n <Typography aria-hidden=\"true\" color=\"primary\">\n →\n </Typography>\n <Chip\n size=\"small\"\n color=\"primary\"\n label={`Observed service · ${\n brief.observedService || 'Not resolved'\n }`}\n />\n </Box>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Runtime namespace: {brief.namespace || 'Not set'} · Refreshed{' '}\n {formatTimestamp(brief.refreshedAt)}\n </Typography>\n </Box>\n <Button\n type=\"button\"\n variant=\"outlined\"\n size=\"small\"\n onClick={onRefresh}\n disabled={refreshingAll}\n startIcon={refreshingAll ? <CircularProgress size={14} /> : undefined}\n >\n {refreshingAll ? 'Refreshing…' : 'Refresh brief'}\n </Button>\n </Box>\n {refreshError && (\n <Typography color=\"error\" variant=\"caption\">\n Refresh failed: {refreshError}. Existing evidence is still shown.\n </Typography>\n )}\n </Box>\n\n <Grid container spacing={3} alignItems=\"stretch\">\n <Grid item xs={12}>\n <OverviewSection\n section={brief.overview}\n onRetry={onRetry}\n refreshing={refreshing.has('overview')}\n />\n </Grid>\n <Grid item xs={12}>\n <WhyNowSection\n section={brief.whyNow}\n onRetry={onRetry}\n refreshing={refreshing.has('whyNow')}\n />\n </Grid>\n {askEnabled && (\n <Grid item xs={12}>\n <AskAnyshiftCard\n context=\"entity\"\n scope={askScope}\n scopeLabel={askScopeLabel}\n />\n </Grid>\n )}\n <Grid item xs={12}>\n <DatadogSignalSection\n section={brief.observability}\n onRetry={onRetry}\n refreshing={refreshing.has('observability')}\n />\n </Grid>\n <Grid item xs={12}>\n <ArchitectureSection\n section={brief.architecture}\n onRetry={onRetry}\n refreshing={refreshing.has('architecture')}\n />\n </Grid>\n <Grid item xs={12} md={8}>\n <DependencySection\n section={brief.topology}\n onRetry={onRetry}\n refreshing={refreshing.has('topology')}\n />\n </Grid>\n <Grid item xs={12} md={4}>\n <BriefRail brief={brief} onRetry={onRetry} refreshing={refreshing} />\n </Grid>\n <Grid item xs={12}>\n <TimelineSection\n section={brief.timeline}\n onRetry={onRetry}\n refreshing={refreshing.has('timeline')}\n />\n </Grid>\n </Grid>\n </>\n);\n\nfunction formatTimestamp(value: string): string {\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? value : new Date(parsed).toLocaleString();\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AnyshiftEntityContent.esm.js","sources":["../../../src/components/entity/AnyshiftEntityContent.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n Box,\n Button,\n Chip,\n CircularProgress,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport { Progress } from '@backstage/core-components';\nimport { useApi } from '@backstage/frontend-plugin-api';\nimport {\n ANYSHIFT_KIND_ANNOTATION,\n ANYSHIFT_TARGET_ANNOTATION,\n GITHUB_PROJECT_SLUG_ANNOTATION,\n} from '@anyshift/backstage-plugin-anyshift-common';\nimport type { Entity } from '@backstage/catalog-model';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { anyshiftApiRef } from '../../api/AnyshiftApi';\nimport type { BriefSectionName, ServiceBrief } from '../../api/types';\nimport {\n ArchitectureSection,\n BriefRail,\n DatadogSignalSection,\n DependencySection,\n OverviewSection,\n TimelineSection,\n} from './BriefSections';\n\nexport const AnyshiftEntityContent = () => {\n const { entity } = useEntity();\n const api = useApi(anyshiftApiRef);\n const annotations = entity.metadata.annotations ?? {};\n const target = entityTarget(entity);\n const kind = annotations[ANYSHIFT_KIND_ANNOTATION] || 'workload';\n const namespace = entity.metadata.namespace;\n const [brief, setBrief] = useState<ServiceBrief>();\n const [error, setError] = useState<string>();\n const [refreshingAll, setRefreshingAll] = useState(false);\n const [refreshing, setRefreshing] = useState<Set<BriefSectionName>>(\n new Set(),\n );\n const active = useRef(true);\n\n const load = useCallback(\n async (refresh = false) => {\n setError(undefined);\n if (refresh) setRefreshingAll(true);\n try {\n const next = await api.brief(kind, target, { namespace, refresh });\n if (active.current) setBrief(next);\n } catch (cause) {\n if (active.current)\n setError(cause instanceof Error ? cause.message : String(cause));\n } finally {\n if (active.current) setRefreshingAll(false);\n }\n },\n [api, kind, namespace, target],\n );\n\n const retrySection = useCallback(\n async (section: BriefSectionName) => {\n setRefreshing(current => new Set(current).add(section));\n try {\n const response = await api.briefSection(kind, target, section, {\n namespace,\n refresh: true,\n });\n if (active.current) {\n setBrief(current =>\n current\n ? {\n ...current,\n [section]: response.value,\n refreshedAt: response.refreshedAt,\n ...(response.observedService\n ? { observedService: response.observedService }\n : {}),\n }\n : current,\n );\n }\n } finally {\n if (active.current) {\n setRefreshing(current => {\n const next = new Set(current);\n next.delete(section);\n return next;\n });\n }\n }\n },\n [api, kind, namespace, target],\n );\n\n useEffect(() => {\n active.current = true;\n void load();\n return () => {\n active.current = false;\n };\n }, [load]);\n\n if (error && !brief) return <Typography color=\"error\">{error}</Typography>;\n if (!brief) return <Progress />;\n return (\n <ServiceBriefView\n brief={brief}\n onRetry={retrySection}\n refreshing={refreshing}\n onRefresh={() => void load(true)}\n refreshingAll={refreshingAll}\n refreshError={error}\n />\n );\n};\n\nexport function entityTarget(entity: Entity): string {\n const annotations = entity.metadata.annotations ?? {};\n const explicit = annotations[ANYSHIFT_TARGET_ANNOTATION]?.trim();\n if (explicit) return explicit;\n\n const slug = annotations[GITHUB_PROJECT_SLUG_ANNOTATION]?.trim();\n const repository = slug?.split('/').filter(Boolean).at(-1);\n return repository || entity.metadata.name;\n}\n\nexport const ServiceBriefView = ({\n brief,\n onRetry,\n refreshing = new Set(),\n onRefresh = () => {},\n refreshingAll = false,\n refreshError,\n}: {\n brief: ServiceBrief;\n onRetry: (section: BriefSectionName) => void;\n refreshing?: ReadonlySet<BriefSectionName>;\n onRefresh?: () => void;\n refreshingAll?: boolean;\n refreshError?: string;\n}) => (\n <>\n <Box\n mb={3}\n px={2.5}\n py={2}\n borderLeft={4}\n borderColor=\"primary.main\"\n bgcolor=\"background.paper\"\n >\n <Box display=\"flex\" justifyContent=\"space-between\" gridGap={16}>\n <Box>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Anyshift evidence trace\n </Typography>\n <Box display=\"flex\" flexWrap=\"wrap\" alignItems=\"center\" gridGap={8}>\n <Chip size=\"small\" label={`Workload · ${brief.target}`} />\n <Typography aria-hidden=\"true\" color=\"primary\">\n →\n </Typography>\n <Chip\n size=\"small\"\n color=\"primary\"\n label={`Observed service · ${\n brief.observedService || 'Not resolved'\n }`}\n />\n </Box>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Runtime namespace: {brief.namespace || 'Not set'} · Refreshed{' '}\n {formatTimestamp(brief.refreshedAt)}\n </Typography>\n </Box>\n <Button\n type=\"button\"\n variant=\"outlined\"\n size=\"small\"\n onClick={onRefresh}\n disabled={refreshingAll}\n startIcon={refreshingAll ? <CircularProgress size={14} /> : undefined}\n >\n {refreshingAll ? 'Refreshing…' : 'Refresh brief'}\n </Button>\n </Box>\n {refreshError && (\n <Typography color=\"error\" variant=\"caption\">\n Refresh failed: {refreshError}. Existing evidence is still shown.\n </Typography>\n )}\n </Box>\n\n <Grid container spacing={3} alignItems=\"stretch\">\n <Grid item xs={12}>\n <OverviewSection\n section={brief.overview}\n onRetry={onRetry}\n refreshing={refreshing.has('overview')}\n />\n </Grid>\n <Grid item xs={12}>\n <DatadogSignalSection\n section={brief.observability}\n onRetry={onRetry}\n refreshing={refreshing.has('observability')}\n />\n </Grid>\n <Grid item xs={12}>\n <ArchitectureSection\n section={brief.architecture}\n onRetry={onRetry}\n refreshing={refreshing.has('architecture')}\n />\n </Grid>\n <Grid item xs={12} md={8}>\n <DependencySection\n section={brief.topology}\n onRetry={onRetry}\n refreshing={refreshing.has('topology')}\n />\n </Grid>\n <Grid item xs={12} md={4}>\n <BriefRail brief={brief} onRetry={onRetry} refreshing={refreshing} />\n </Grid>\n <Grid item xs={12}>\n <TimelineSection\n section={brief.timeline}\n onRetry={onRetry}\n refreshing={refreshing.has('timeline')}\n />\n </Grid>\n </Grid>\n </>\n);\n\nfunction formatTimestamp(value: string): string {\n const parsed = Date.parse(value);\n return Number.isNaN(parsed) ? value : new Date(parsed).toLocaleString();\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { Box, Grid, Typography, Button, CircularProgress } from '@material-ui/core';
|
|
3
3
|
import { InfoCard } from '@backstage/core-components';
|
|
4
|
-
import { OverviewPresenter,
|
|
4
|
+
import { OverviewPresenter, ArchitecturePresenter, DependencyFootprintPresenter, OperationalPosturePresenter, LatestChangePresenter, SafeguardsPresenter, TimelinePresenter } from './SectionPresenters.esm.js';
|
|
5
5
|
import { DatadogSignalStripPresenter } from './DatadogLiveSignal.esm.js';
|
|
6
6
|
|
|
7
7
|
const OverviewSection = ({
|
|
@@ -58,26 +58,6 @@ const DatadogSignalSection = ({
|
|
|
58
58
|
renderData: (data) => /* @__PURE__ */ jsx(DatadogSignalStripPresenter, { data })
|
|
59
59
|
}
|
|
60
60
|
) }) });
|
|
61
|
-
const WhyNowSection = ({
|
|
62
|
-
section,
|
|
63
|
-
onRetry,
|
|
64
|
-
refreshing
|
|
65
|
-
}) => /* @__PURE__ */ jsx(
|
|
66
|
-
SectionCard,
|
|
67
|
-
{
|
|
68
|
-
title: "Why now?",
|
|
69
|
-
subheader: "Current symptoms and evidence-backed suspects",
|
|
70
|
-
children: /* @__PURE__ */ jsx(
|
|
71
|
-
DataSection,
|
|
72
|
-
{
|
|
73
|
-
section,
|
|
74
|
-
onRetry: () => onRetry("whyNow"),
|
|
75
|
-
refreshing,
|
|
76
|
-
renderData: (data) => /* @__PURE__ */ jsx(WhyNowPresenter, { data })
|
|
77
|
-
}
|
|
78
|
-
)
|
|
79
|
-
}
|
|
80
|
-
);
|
|
81
61
|
const BriefRail = ({
|
|
82
62
|
brief,
|
|
83
63
|
onRetry,
|
|
@@ -86,11 +66,11 @@ const BriefRail = ({
|
|
|
86
66
|
/* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
|
|
87
67
|
CompactSection,
|
|
88
68
|
{
|
|
89
|
-
title: "
|
|
69
|
+
title: "Operational posture",
|
|
90
70
|
section: brief.impact,
|
|
91
71
|
onRetry: () => onRetry("impact"),
|
|
92
72
|
refreshing: refreshing.has("impact"),
|
|
93
|
-
renderData: (data) => /* @__PURE__ */ jsx(
|
|
73
|
+
renderData: (data) => /* @__PURE__ */ jsx(OperationalPosturePresenter, { data })
|
|
94
74
|
}
|
|
95
75
|
) }),
|
|
96
76
|
/* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsx(
|
|
@@ -234,5 +214,5 @@ const RetryControl = ({
|
|
|
234
214
|
}
|
|
235
215
|
);
|
|
236
216
|
|
|
237
|
-
export { ArchitectureSection, BriefRail, DatadogSignalSection, DependencySection, OverviewSection, TimelineSection
|
|
217
|
+
export { ArchitectureSection, BriefRail, DatadogSignalSection, DependencySection, OverviewSection, TimelineSection };
|
|
238
218
|
//# sourceMappingURL=BriefSections.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BriefSections.esm.js","sources":["../../../src/components/entity/BriefSections.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport {\n Box,\n Button,\n CircularProgress,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport { InfoCard } from '@backstage/core-components';\nimport type {\n BriefSection,\n BriefSectionName,\n EntityImpact,\n SafeguardResult,\n ServiceBrief,\n ServiceOverview,\n WhyNowAssessment,\n} from '../../api/types';\nimport {\n AffectedFootprintPresenter,\n ArchitecturePresenter,\n DependencyFootprintPresenter,\n LatestChangePresenter,\n OverviewPresenter,\n SafeguardsPresenter,\n TimelinePresenter,\n WhyNowPresenter,\n} from './SectionPresenters';\nimport { DatadogSignalStripPresenter } from './DatadogLiveSignal';\n\nexport type RetrySection = (section: BriefSectionName) => void;\n\nexport const OverviewSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection<ServiceOverview>;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <InfoCard noPadding>\n <Box px={2} py={2}>\n <DataSection\n section={section}\n onRetry={() => onRetry('overview')}\n refreshing={refreshing}\n renderData={data => <OverviewPresenter data={data} />}\n />\n </Box>\n </InfoCard>\n);\n\nexport const DependencySection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard\n title=\"Dependency footprint\"\n subheader=\"Direct traffic and transitive reach\"\n >\n <DataSection\n section={section}\n onRetry={() => onRetry('topology')}\n refreshing={refreshing}\n renderData={data => <DependencyFootprintPresenter data={data} />}\n />\n </SectionCard>\n);\n\nexport const DatadogSignalSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <InfoCard noPadding>\n {section.state === 'data' && section.data !== undefined ? (\n <DataSection\n section={section}\n onRetry={() => onRetry('observability')}\n refreshing={refreshing}\n renderData={data => <DatadogSignalStripPresenter data={data} />}\n />\n ) : (\n <Box px={2} py={1.5}>\n <DataSection\n section={section}\n onRetry={() => onRetry('observability')}\n refreshing={refreshing}\n renderData={data => <DatadogSignalStripPresenter data={data} />}\n />\n </Box>\n )}\n </InfoCard>\n);\n\nexport const WhyNowSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection<WhyNowAssessment>;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard\n title=\"Why now?\"\n subheader=\"Current symptoms and evidence-backed suspects\"\n >\n <DataSection\n section={section}\n onRetry={() => onRetry('whyNow')}\n refreshing={refreshing}\n renderData={data => <WhyNowPresenter data={data} />}\n />\n </SectionCard>\n);\n\nexport const BriefRail = ({\n brief,\n onRetry,\n refreshing = new Set(),\n}: {\n brief: ServiceBrief;\n onRetry: RetrySection;\n refreshing?: ReadonlySet<BriefSectionName>;\n}) => (\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <CompactSection\n title=\"Affected footprint\"\n section={brief.impact}\n onRetry={() => onRetry('impact')}\n refreshing={refreshing.has('impact')}\n renderData={(data: EntityImpact) => (\n <AffectedFootprintPresenter data={data} />\n )}\n />\n </Grid>\n <Grid item xs={12}>\n <CompactSection\n title=\"Latest change\"\n section={brief.latestChange}\n onRetry={() => onRetry('latestChange')}\n refreshing={refreshing.has('latestChange')}\n renderData={data => <LatestChangePresenter data={data} />}\n />\n </Grid>\n <Grid item xs={12}>\n <CompactSection<SafeguardResult[]>\n title=\"Runtime safeguards\"\n section={brief.safeguards}\n onRetry={() => onRetry('safeguards')}\n refreshing={refreshing.has('safeguards')}\n renderData={data => <SafeguardsPresenter data={data} />}\n />\n </Grid>\n </Grid>\n);\n\nexport const TimelineSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard\n title=\"Change intelligence\"\n subheader=\"Runtime changes in the last 24 hours\"\n >\n <DataSection\n section={section}\n onRetry={() => onRetry('timeline')}\n refreshing={refreshing}\n renderData={data => <TimelinePresenter data={data} />}\n />\n </SectionCard>\n);\n\nexport const ArchitectureSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard title=\"Service map\" subheader=\"Cross-layer C4 graph evidence\">\n <DataSection\n section={section}\n onRetry={() => onRetry('architecture')}\n refreshing={refreshing}\n renderData={data => <ArchitecturePresenter data={data} />}\n />\n </SectionCard>\n);\n\nconst SectionCard = ({\n title,\n subheader,\n children,\n}: {\n title: string;\n subheader?: string;\n children: ReactNode;\n}) => (\n <InfoCard\n title={\n <Typography component=\"h2\" variant=\"h5\">\n {title}\n </Typography>\n }\n subheader={subheader}\n >\n {children}\n </InfoCard>\n);\n\nconst CompactSection = <T,>({\n title,\n section,\n onRetry,\n refreshing,\n renderData,\n}: {\n title: string;\n section: BriefSection<T>;\n onRetry: () => void;\n refreshing?: boolean;\n renderData: (data: T) => ReactNode;\n}) => (\n <InfoCard\n title={\n <Typography component=\"h2\" variant=\"h5\">\n {title}\n </Typography>\n }\n noPadding\n >\n <Box p={2}>\n <DataSection\n section={section}\n onRetry={onRetry}\n refreshing={refreshing}\n renderData={renderData}\n />\n </Box>\n </InfoCard>\n);\n\nconst DataSection = <T,>({\n section,\n onRetry,\n refreshing,\n renderData,\n}: {\n section: BriefSection<T>;\n onRetry: () => void;\n refreshing?: boolean;\n renderData: (data: T) => ReactNode;\n}) => {\n if (section.state === 'data' && section.data !== undefined) {\n return (\n <>\n {renderData(section.data)}\n {section.retryable && (\n <RetryControl onRetry={onRetry} refreshing={refreshing} />\n )}\n </>\n );\n }\n return (\n <SectionStateContent\n section={section}\n onRetry={onRetry}\n refreshing={refreshing}\n />\n );\n};\n\nconst SectionStateContent = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: () => void;\n refreshing?: boolean;\n}) => (\n <>\n <Typography\n color={section.state === 'error' ? 'error' : 'textSecondary'}\n variant=\"body2\"\n >\n {section.message || 'No graph evidence is available.'}\n </Typography>\n {section.retryable && (\n <RetryControl onRetry={onRetry} refreshing={refreshing} />\n )}\n </>\n);\n\nconst RetryControl = ({\n onRetry,\n refreshing,\n}: {\n onRetry: () => void;\n refreshing?: boolean;\n}) => (\n <Button\n type=\"button\"\n variant=\"outlined\"\n size=\"small\"\n onClick={onRetry}\n disabled={refreshing}\n startIcon={refreshing ? <CircularProgress size={14} /> : undefined}\n style={{ marginTop: 8 }}\n >\n {refreshing ? 'Retrying…' : 'Retry'}\n </Button>\n);\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BriefSections.esm.js","sources":["../../../src/components/entity/BriefSections.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport {\n Box,\n Button,\n CircularProgress,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport { InfoCard } from '@backstage/core-components';\nimport type {\n BriefSection,\n BriefSectionName,\n SafeguardResult,\n ServiceBrief,\n ServiceOverview,\n} from '../../api/types';\nimport {\n ArchitecturePresenter,\n DependencyFootprintPresenter,\n LatestChangePresenter,\n OperationalPosturePresenter,\n OverviewPresenter,\n SafeguardsPresenter,\n TimelinePresenter,\n} from './SectionPresenters';\nimport { DatadogSignalStripPresenter } from './DatadogLiveSignal';\n\nexport type RetrySection = (section: BriefSectionName) => void;\n\nexport const OverviewSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection<ServiceOverview>;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <InfoCard noPadding>\n <Box px={2} py={2}>\n <DataSection\n section={section}\n onRetry={() => onRetry('overview')}\n refreshing={refreshing}\n renderData={data => <OverviewPresenter data={data} />}\n />\n </Box>\n </InfoCard>\n);\n\nexport const DependencySection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard\n title=\"Dependency footprint\"\n subheader=\"Direct traffic and transitive reach\"\n >\n <DataSection\n section={section}\n onRetry={() => onRetry('topology')}\n refreshing={refreshing}\n renderData={data => <DependencyFootprintPresenter data={data} />}\n />\n </SectionCard>\n);\n\nexport const DatadogSignalSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <InfoCard noPadding>\n {section.state === 'data' && section.data !== undefined ? (\n <DataSection\n section={section}\n onRetry={() => onRetry('observability')}\n refreshing={refreshing}\n renderData={data => <DatadogSignalStripPresenter data={data} />}\n />\n ) : (\n <Box px={2} py={1.5}>\n <DataSection\n section={section}\n onRetry={() => onRetry('observability')}\n refreshing={refreshing}\n renderData={data => <DatadogSignalStripPresenter data={data} />}\n />\n </Box>\n )}\n </InfoCard>\n);\n\nexport const BriefRail = ({\n brief,\n onRetry,\n refreshing = new Set(),\n}: {\n brief: ServiceBrief;\n onRetry: RetrySection;\n refreshing?: ReadonlySet<BriefSectionName>;\n}) => (\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <CompactSection\n title=\"Operational posture\"\n section={brief.impact}\n onRetry={() => onRetry('impact')}\n refreshing={refreshing.has('impact')}\n renderData={data => <OperationalPosturePresenter data={data} />}\n />\n </Grid>\n <Grid item xs={12}>\n <CompactSection\n title=\"Latest change\"\n section={brief.latestChange}\n onRetry={() => onRetry('latestChange')}\n refreshing={refreshing.has('latestChange')}\n renderData={data => <LatestChangePresenter data={data} />}\n />\n </Grid>\n <Grid item xs={12}>\n <CompactSection<SafeguardResult[]>\n title=\"Runtime safeguards\"\n section={brief.safeguards}\n onRetry={() => onRetry('safeguards')}\n refreshing={refreshing.has('safeguards')}\n renderData={data => <SafeguardsPresenter data={data} />}\n />\n </Grid>\n </Grid>\n);\n\nexport const TimelineSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard\n title=\"Change intelligence\"\n subheader=\"Runtime changes in the last 24 hours\"\n >\n <DataSection\n section={section}\n onRetry={() => onRetry('timeline')}\n refreshing={refreshing}\n renderData={data => <TimelinePresenter data={data} />}\n />\n </SectionCard>\n);\n\nexport const ArchitectureSection = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: RetrySection;\n refreshing?: boolean;\n}) => (\n <SectionCard title=\"Service map\" subheader=\"Cross-layer C4 graph evidence\">\n <DataSection\n section={section}\n onRetry={() => onRetry('architecture')}\n refreshing={refreshing}\n renderData={data => <ArchitecturePresenter data={data} />}\n />\n </SectionCard>\n);\n\nconst SectionCard = ({\n title,\n subheader,\n children,\n}: {\n title: string;\n subheader?: string;\n children: ReactNode;\n}) => (\n <InfoCard\n title={\n <Typography component=\"h2\" variant=\"h5\">\n {title}\n </Typography>\n }\n subheader={subheader}\n >\n {children}\n </InfoCard>\n);\n\nconst CompactSection = <T,>({\n title,\n section,\n onRetry,\n refreshing,\n renderData,\n}: {\n title: string;\n section: BriefSection<T>;\n onRetry: () => void;\n refreshing?: boolean;\n renderData: (data: T) => ReactNode;\n}) => (\n <InfoCard\n title={\n <Typography component=\"h2\" variant=\"h5\">\n {title}\n </Typography>\n }\n noPadding\n >\n <Box p={2}>\n <DataSection\n section={section}\n onRetry={onRetry}\n refreshing={refreshing}\n renderData={renderData}\n />\n </Box>\n </InfoCard>\n);\n\nconst DataSection = <T,>({\n section,\n onRetry,\n refreshing,\n renderData,\n}: {\n section: BriefSection<T>;\n onRetry: () => void;\n refreshing?: boolean;\n renderData: (data: T) => ReactNode;\n}) => {\n if (section.state === 'data' && section.data !== undefined) {\n return (\n <>\n {renderData(section.data)}\n {section.retryable && (\n <RetryControl onRetry={onRetry} refreshing={refreshing} />\n )}\n </>\n );\n }\n return (\n <SectionStateContent\n section={section}\n onRetry={onRetry}\n refreshing={refreshing}\n />\n );\n};\n\nconst SectionStateContent = ({\n section,\n onRetry,\n refreshing,\n}: {\n section: BriefSection;\n onRetry: () => void;\n refreshing?: boolean;\n}) => (\n <>\n <Typography\n color={section.state === 'error' ? 'error' : 'textSecondary'}\n variant=\"body2\"\n >\n {section.message || 'No graph evidence is available.'}\n </Typography>\n {section.retryable && (\n <RetryControl onRetry={onRetry} refreshing={refreshing} />\n )}\n </>\n);\n\nconst RetryControl = ({\n onRetry,\n refreshing,\n}: {\n onRetry: () => void;\n refreshing?: boolean;\n}) => (\n <Button\n type=\"button\"\n variant=\"outlined\"\n size=\"small\"\n onClick={onRetry}\n disabled={refreshing}\n startIcon={refreshing ? <CircularProgress size={14} /> : undefined}\n style={{ marginTop: 8 }}\n >\n {refreshing ? 'Retrying…' : 'Retry'}\n </Button>\n);\n"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { jsxs, jsx
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { Box, Typography, makeStyles } from '@material-ui/core';
|
|
3
3
|
import { EvidenceDisclosure } from './EvidenceDisclosure.esm.js';
|
|
4
4
|
|
|
5
5
|
const STATE_COPY = {
|
|
6
6
|
firing: {
|
|
7
7
|
headline: "Service on fire",
|
|
8
|
-
detail: (signal) => `${signal.
|
|
8
|
+
detail: (signal) => `${signal.active} ${signal.active === 1 ? "monitor" : "monitors"} firing now`
|
|
9
9
|
},
|
|
10
10
|
noisy: {
|
|
11
11
|
headline: "Quiet now \xB7 noisy lately",
|
|
12
|
-
detail: () => "No
|
|
12
|
+
detail: () => "No monitor is firing now."
|
|
13
13
|
},
|
|
14
14
|
quiet: {
|
|
15
15
|
headline: "Quiet",
|
|
@@ -17,7 +17,7 @@ const STATE_COPY = {
|
|
|
17
17
|
},
|
|
18
18
|
unavailable: {
|
|
19
19
|
headline: "Signal unavailable",
|
|
20
|
-
detail: (
|
|
20
|
+
detail: () => "No Datadog signal evidence was returned."
|
|
21
21
|
}
|
|
22
22
|
};
|
|
23
23
|
const STATE_COLORS = {
|
|
@@ -87,66 +87,22 @@ const DatadogSignalStripPresenter = ({ data }) => {
|
|
|
87
87
|
/* @__PURE__ */ jsx(Typography, { variant: "h6", className: classes.headline, children: copy.headline }),
|
|
88
88
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children: compactSummary(signal) })
|
|
89
89
|
] }),
|
|
90
|
-
signal.partial && /* @__PURE__ */
|
|
91
|
-
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", component: "p", children: signal.activeHasMore ? "Additional alert rows are available; the loaded count is a lower bound." : "Some operational alert evidence is temporarily unavailable." }),
|
|
92
|
-
/* @__PURE__ */ jsx(AlertCoverage, { signal })
|
|
93
|
-
] }),
|
|
90
|
+
signal.partial && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", component: "p", children: "Some Datadog evidence is temporarily unavailable." }),
|
|
94
91
|
/* @__PURE__ */ jsx(EvidenceDisclosure, { data })
|
|
95
92
|
] });
|
|
96
93
|
};
|
|
97
|
-
const AlertCoverage = ({ signal }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
98
|
-
signal.providers.filter((provider) => provider.status !== "available").map((provider) => /* @__PURE__ */ jsxs(
|
|
99
|
-
Typography,
|
|
100
|
-
{
|
|
101
|
-
variant: "caption",
|
|
102
|
-
color: "textSecondary",
|
|
103
|
-
component: "p",
|
|
104
|
-
children: [
|
|
105
|
-
"Alert coverage: ",
|
|
106
|
-
readableProvider(provider.provider),
|
|
107
|
-
" ",
|
|
108
|
-
provider.status,
|
|
109
|
-
"."
|
|
110
|
-
]
|
|
111
|
-
},
|
|
112
|
-
provider.provider
|
|
113
|
-
)),
|
|
114
|
-
signal.warnings.map((warning) => /* @__PURE__ */ jsxs(
|
|
115
|
-
Typography,
|
|
116
|
-
{
|
|
117
|
-
variant: "caption",
|
|
118
|
-
color: "textSecondary",
|
|
119
|
-
component: "p",
|
|
120
|
-
children: [
|
|
121
|
-
"Alert warning: ",
|
|
122
|
-
warning.message,
|
|
123
|
-
warning.message.endsWith(".") ? "" : "."
|
|
124
|
-
]
|
|
125
|
-
},
|
|
126
|
-
`${warning.provider ?? "alert"}:${warning.message}`
|
|
127
|
-
))
|
|
128
|
-
] });
|
|
129
94
|
function datadogSignalFrom(data) {
|
|
130
95
|
const root = recordFrom(data);
|
|
131
96
|
const alerts = recordFrom(root.alerts);
|
|
132
97
|
const alertNoise = recordFrom(root.alertNoise);
|
|
133
98
|
const counts = recordFrom(alertNoise.counts);
|
|
134
99
|
const alertCause = recordFrom(root.alertCause);
|
|
135
|
-
const
|
|
136
|
-
const warnings = warningsFrom(alerts.warnings);
|
|
137
|
-
const activeHasMore = recordFrom(alerts.page).hasMore === true;
|
|
138
|
-
const alertEvidenceIncomplete = alerts.partial === true || activeHasMore || providers.some((provider) => provider.status !== "available") || warnings.length > 0;
|
|
139
|
-
const firingMonitors = uniqueMonitors(
|
|
140
|
-
recordsFrom(alerts.items).filter(
|
|
141
|
-
(record) => textFrom(record, "status") === "firing"
|
|
142
|
-
),
|
|
143
|
-
"alert"
|
|
144
|
-
);
|
|
100
|
+
const firingMonitors = uniqueMonitors(recordsFrom(alerts.firing), "firing");
|
|
145
101
|
const noisyMonitors = uniqueMonitors(
|
|
146
102
|
recordsFrom(alertNoise.monitors),
|
|
147
103
|
"noise"
|
|
148
104
|
);
|
|
149
|
-
const active = firingMonitors.length;
|
|
105
|
+
const active = numberFrom(alerts.total) ?? firingMonitors.length;
|
|
150
106
|
const fires = numberFrom(counts.totalFires) ?? noisyMonitors.reduce((total, monitor) => total + (monitor.fires ?? 0), 0);
|
|
151
107
|
const recovers = noisyMonitors.reduce(
|
|
152
108
|
(total, monitor) => total + (monitor.recovers ?? 0),
|
|
@@ -157,9 +113,8 @@ function datadogSignalFrom(data) {
|
|
|
157
113
|
const hasEvidence = isRecord(root.alerts) || isRecord(root.alertNoise);
|
|
158
114
|
const changes = Array.isArray(alertCause.changes) ? alertCause.changes.length : void 0;
|
|
159
115
|
return {
|
|
160
|
-
state: !hasEvidence ? "unavailable" : active > 0 ? "firing" :
|
|
116
|
+
state: !hasEvidence ? "unavailable" : active > 0 ? "firing" : fires > 0 || flapping > 0 || stuck > 0 ? "noisy" : "quiet",
|
|
161
117
|
active,
|
|
162
|
-
activeHasMore,
|
|
163
118
|
fires,
|
|
164
119
|
recovers,
|
|
165
120
|
flapping,
|
|
@@ -167,44 +122,27 @@ function datadogSignalFrom(data) {
|
|
|
167
122
|
firingMonitors,
|
|
168
123
|
noisyMonitors,
|
|
169
124
|
...changes !== void 0 ? { correlatedChanges: changes } : {},
|
|
170
|
-
partial: Array.isArray(root.errors) && root.errors.length > 0
|
|
171
|
-
providers,
|
|
172
|
-
warnings
|
|
125
|
+
partial: Array.isArray(root.errors) && root.errors.length > 0
|
|
173
126
|
};
|
|
174
127
|
}
|
|
175
|
-
function providerCoverageFrom(value) {
|
|
176
|
-
return recordsFrom(value).flatMap((provider) => {
|
|
177
|
-
const name = textFrom(provider, "provider");
|
|
178
|
-
const status = textFrom(provider, "status");
|
|
179
|
-
return name && status ? [{ provider: name, status }] : [];
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
function warningsFrom(value) {
|
|
183
|
-
return recordsFrom(value).flatMap((warning) => {
|
|
184
|
-
const message = textFrom(warning, "message");
|
|
185
|
-
const provider = textFrom(warning, "provider");
|
|
186
|
-
return message ? [{ message, ...provider ? { provider } : {} }] : [];
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
function readableProvider(provider) {
|
|
190
|
-
return provider.charAt(0).toUpperCase() + provider.slice(1);
|
|
191
|
-
}
|
|
192
128
|
function uniqueMonitors(records, source) {
|
|
193
129
|
const unique = /* @__PURE__ */ new Map();
|
|
194
130
|
records.forEach((record) => {
|
|
195
|
-
const name = textFrom(record, source === "
|
|
131
|
+
const name = textFrom(record, source === "firing" ? "monitor" : "name");
|
|
196
132
|
if (!name) return;
|
|
197
|
-
const service = recordFrom(record.service);
|
|
198
133
|
const monitor = {
|
|
199
|
-
key:
|
|
134
|
+
key: [
|
|
135
|
+
name,
|
|
136
|
+
textFrom(record, "state"),
|
|
137
|
+
textFrom(record, "service"),
|
|
138
|
+
textFrom(record, "workload"),
|
|
139
|
+
textFrom(record, "namespace")
|
|
140
|
+
].filter(Boolean).join("|").toLowerCase(),
|
|
200
141
|
name,
|
|
201
|
-
state:
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
service: source === "alert" ? textFrom(service, "name") : textFrom(record, "service"),
|
|
206
|
-
workload: source === "alert" ? textFrom(service, "name") : textFrom(record, "workload"),
|
|
207
|
-
namespace: source === "alert" ? textFrom(service, "namespace") : textFrom(record, "namespace"),
|
|
142
|
+
state: textFrom(record, "state"),
|
|
143
|
+
service: textFrom(record, "service"),
|
|
144
|
+
workload: textFrom(record, "workload"),
|
|
145
|
+
namespace: textFrom(record, "namespace"),
|
|
208
146
|
fires: numberFrom(record.fires),
|
|
209
147
|
recovers: numberFrom(record.recovers),
|
|
210
148
|
noiseKind: textFrom(record, "noiseKind")
|
|
@@ -216,7 +154,7 @@ function uniqueMonitors(records, source) {
|
|
|
216
154
|
function compactSummary(signal) {
|
|
217
155
|
if (signal.state === "firing") {
|
|
218
156
|
const summary = [
|
|
219
|
-
`${signal.
|
|
157
|
+
`${signal.active} ${signal.active === 1 ? "monitor" : "monitors"}`
|
|
220
158
|
];
|
|
221
159
|
if (signal.correlatedChanges) {
|
|
222
160
|
summary.push(
|
|
@@ -229,7 +167,7 @@ function compactSummary(signal) {
|
|
|
229
167
|
return `${signal.fires} fire \xB7 ${signal.flapping} flapping`;
|
|
230
168
|
}
|
|
231
169
|
if (signal.state === "quiet") return "No recent paging noise";
|
|
232
|
-
return
|
|
170
|
+
return "No Datadog signal evidence returned";
|
|
233
171
|
}
|
|
234
172
|
function recordFrom(value) {
|
|
235
173
|
return isRecord(value) ? value : {};
|