@oneuptime/common 12.0.11 → 12.0.13
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/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +32 -5
- package/Models/DatabaseModels/NetworkDevice.ts +64 -0
- package/Models/DatabaseModels/StatusPage.ts +59 -0
- package/Models/DatabaseModels/StatusPageOidc.ts +2 -0
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +19 -2
- package/Server/API/AIChatAPI.ts +55 -56
- package/Server/API/CommonAPI.ts +89 -0
- package/Server/API/MicrosoftTeamsAPI.ts +20 -9
- package/Server/API/SlackAPI.ts +13 -10
- package/Server/API/StatusPageAPI.ts +2197 -2128
- package/Server/API/TelemetryAPI.ts +72 -3
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787500000000-AddEnableSearchEngineIndexingToStatusPage.ts +30 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787600000000-AddNetworkDeviceReachabilityColumns.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Middleware/UserAuthorization.ts +11 -2
- package/Server/Services/ApiKeyPermissionService.ts +116 -2
- package/Server/Services/DatabaseService.ts +17 -6
- package/Server/Services/LogAggregationService.ts +34 -0
- package/Server/Services/LogService.ts +21 -0
- package/Server/Services/NetworkSiteService.ts +12 -0
- package/Server/Services/SpanService.ts +21 -0
- package/Server/Services/TraceAggregationService.ts +15 -0
- package/Server/Services/WorkspaceNotificationRuleService.ts +172 -220
- package/Server/Types/AnalyticsDatabase/ModelPermission.ts +9 -0
- package/Server/Types/Database/Permissions/AccessControlPermission.ts +47 -16
- package/Server/Types/Workflow/Components/Conditions/IfElse.ts +9 -0
- package/Server/Types/Workflow/Components/JavaScript.ts +9 -0
- package/Server/Utils/APIKey/AccessPermission.ts +16 -40
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +144 -0
- package/Server/Utils/LogRedaction.ts +576 -0
- package/Server/Utils/Logger.ts +123 -46
- package/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.ts +94 -23
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +12 -0
- package/Server/Utils/Monitor/MonitorResource.ts +29 -9
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +28 -7
- package/Server/Utils/SessionReplay/SessionReplayGateCacheStore.ts +56 -10
- package/Server/Utils/StartServer.ts +30 -9
- package/Server/Utils/StatusPageSearchEngineIndexing.ts +33 -0
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +441 -0
- package/Server/Utils/VM/VMRunner.ts +693 -874
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +488 -46
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +300 -0
- package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +130 -0
- package/Tests/Models/DatabaseModels/DatabaseBaseModelToJSONObjectCache.test.ts +180 -0
- package/Tests/Models/StatusPageEnableSearchEngineIndexing.test.ts +157 -0
- package/Tests/Server/API/AIChatCancelAndFeedback.test.ts +23 -1
- package/Tests/Server/API/AIChatRouteAuthorization.test.ts +785 -0
- package/Tests/Server/API/BaseAPIApiKeyAuth.test.ts +21 -8
- package/Tests/Server/API/CommonAPIAuthGuard.test.ts +290 -0
- package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +7 -1
- package/Tests/Server/API/StatusPageOverviewCache.test.ts +474 -0
- package/Tests/Server/API/StatusPageSeoSearchEngineIndexing.test.ts +189 -0
- package/Tests/Server/Infrastructure/InMemoryTTLCache.test.ts +158 -0
- package/Tests/Server/Infrastructure/Postgres/DeviceRoleAndDeclaredLinkParentMigration.test.ts +9 -60
- package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +24 -15
- package/Tests/Server/Middleware/UserAuthorization.test.ts +79 -0
- package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +332 -0
- package/Tests/Server/Services/ApiKeyPermissionService.test.ts +347 -0
- package/Tests/Server/Services/DatabaseServiceUpdateDebugLogging.test.ts +282 -0
- package/Tests/Server/Services/NetworkSiteService.test.ts +56 -2
- package/Tests/Server/Services/TelemetryResourceFacetFilters.test.ts +267 -0
- package/Tests/Server/Services/WorkspaceNotificationRuleTestRuleChannels.test.ts +702 -0
- package/Tests/Server/Types/Database/Permissions/AccessControlPermission.test.ts +165 -0
- package/Tests/Server/Types/Workflow/Components/CustomCodeScriptError.test.ts +121 -0
- package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +48 -36
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +213 -0
- package/Tests/Server/Utils/LogRedaction.test.ts +415 -0
- package/Tests/Server/Utils/LoggerCredentialLeak.test.ts +245 -0
- package/Tests/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.test.ts +374 -4
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorJavascriptExpression.test.ts +92 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceIngestedStepSelection.test.ts +455 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceReachabilityRoundTrip.test.ts +369 -0
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +86 -8
- package/Tests/Server/Utils/PrivacyFilterUtil.test.ts +64 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayGateCacheStore.test.ts +207 -0
- package/Tests/Server/Utils/StartServerBodyVerify.test.ts +335 -0
- package/Tests/Server/Utils/StatusPageSearchEngineIndexing.test.ts +60 -0
- package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +435 -0
- package/Tests/Server/Utils/VM/VMRunnerIsolation.test.ts +385 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +3 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +607 -62
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsInstalledTeamIdSpace.test.ts +778 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +44 -10
- package/Tests/Types/API/HostnameFromAuthority.test.ts +164 -0
- package/Tests/Types/Database/AccessControl/ColumnAccessControlCache.test.ts +344 -0
- package/Tests/Types/Database/DatabasePropertyFindOperator.test.ts +518 -0
- package/Tests/Types/Database/TableColumnMetadataCache.test.ts +286 -0
- package/Tests/Types/Monitor/MonitorStep.test.ts +100 -0
- package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +360 -0
- package/Tests/Types/StatusPage/SearchEngineIndexing.test.ts +86 -0
- package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +254 -0
- package/Tests/UI/Components/CardSelect.test.tsx +1021 -0
- package/Tests/UI/Components/MasterPage.test.tsx +36 -1
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +66 -1
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +115 -6
- package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +610 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +114 -45
- package/Types/API/Hostname.ts +79 -0
- package/Types/Database/AccessControl/ColumnAccessControl.ts +33 -11
- package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +33 -11
- package/Types/Database/DatabaseProperty.ts +38 -0
- package/Types/Database/TableColumn.ts +34 -7
- package/Types/Events/Recurring.ts +16 -1
- package/Types/Monitor/CustomCodeMonitor/CustomCodeMonitorResponse.ts +14 -2
- package/Types/Monitor/MonitorStep.ts +13 -1
- package/Types/Monitor/MonitorType.ts +345 -40
- package/Types/Monitor/SSLMonitor/SslMonitorResponse.ts +43 -0
- package/Types/StatusPage/SearchEngineIndexing.ts +61 -0
- package/Types/Telemetry/ResourceEntityFacet.ts +211 -0
- package/UI/Components/CardSelect/CardSelect.tsx +714 -105
- package/UI/Components/EmptyState/EmptyState.tsx +8 -1
- package/UI/Components/Footer/Footer.tsx +32 -6
- package/UI/Components/Forms/Fields/FormField.tsx +3 -0
- package/UI/Components/Forms/Types/Field.ts +8 -0
- package/UI/Components/Loader/PageLoader.tsx +29 -8
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +26 -4
- package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +17 -1
- package/UI/Components/MasterPage/MasterPage.tsx +24 -11
- package/Utils/Monitor/MonitorMetricType.ts +16 -1
- package/Utils/Monitor/NetworkTopologyUtil.ts +60 -8
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +262 -0
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +41 -24
- package/Utils/Telemetry/CrossSignalScope.ts +75 -4
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +20 -4
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +66 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +60 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js +2 -0
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +48 -35
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/CommonAPI.js +59 -0
- package/build/dist/Server/API/CommonAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +20 -6
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/SlackAPI.js +13 -10
- package/build/dist/Server/API/SlackAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +745 -673
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +34 -3
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787500000000-AddEnableSearchEngineIndexingToStatusPage.js +23 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787500000000-AddEnableSearchEngineIndexingToStatusPage.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787600000000-AddNetworkDeviceReachabilityColumns.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787600000000-AddNetworkDeviceReachabilityColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +6 -2
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/ApiKeyPermissionService.js +90 -1
- package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +15 -6
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +2 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/LogService.js +16 -0
- package/build/dist/Server/Services/LogService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +12 -0
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/SpanService.js +16 -0
- package/build/dist/Server/Services/SpanService.js.map +1 -1
- package/build/dist/Server/Services/TraceAggregationService.js +2 -0
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +137 -164
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +9 -0
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/AccessControlPermission.js +21 -13
- package/build/dist/Server/Types/Database/Permissions/AccessControlPermission.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js +8 -0
- package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js +8 -0
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
- package/build/dist/Server/Utils/APIKey/AccessPermission.js +9 -32
- package/build/dist/Server/Utils/APIKey/AccessPermission.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +87 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/LogRedaction.js +449 -0
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -0
- package/build/dist/Server/Utils/Logger.js +98 -45
- package/build/dist/Server/Utils/Logger.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js +65 -13
- package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +12 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +20 -3
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +27 -7
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCacheStore.js +29 -10
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCacheStore.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +10 -7
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageSearchEngineIndexing.js +24 -0
- package/build/dist/Server/Utils/StatusPageSearchEngineIndexing.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +311 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -0
- package/build/dist/Server/Utils/VM/VMRunner.js +402 -525
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +366 -37
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/API/Hostname.js +63 -0
- package/build/dist/Types/API/Hostname.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +20 -6
- package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +20 -6
- package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
- package/build/dist/Types/Database/DatabaseProperty.js +38 -0
- package/build/dist/Types/Database/DatabaseProperty.js.map +1 -1
- package/build/dist/Types/Database/TableColumn.js +24 -6
- package/build/dist/Types/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/Events/Recurring.js +13 -1
- package/build/dist/Types/Events/Recurring.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +9 -1
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +330 -31
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/StatusPage/SearchEngineIndexing.js +55 -0
- package/build/dist/Types/StatusPage/SearchEngineIndexing.js.map +1 -0
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js +156 -0
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js.map +1 -0
- package/build/dist/UI/Components/CardSelect/CardSelect.js +360 -40
- package/build/dist/UI/Components/CardSelect/CardSelect.js.map +1 -1
- package/build/dist/UI/Components/EmptyState/EmptyState.js +1 -1
- package/build/dist/UI/Components/EmptyState/EmptyState.js.map +1 -1
- package/build/dist/UI/Components/Footer/Footer.js +7 -4
- package/build/dist/UI/Components/Footer/Footer.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Loader/PageLoader.js +15 -5
- package/build/dist/UI/Components/Loader/PageLoader.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +16 -3
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js +13 -1
- package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/MasterPage/MasterPage.js +10 -2
- package/build/dist/UI/Components/MasterPage/MasterPage.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +13 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +34 -7
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +177 -0
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +23 -27
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
- package/build/dist/Utils/Telemetry/CrossSignalScope.js +44 -4
- package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Search engine indexing for status pages.
|
|
3
|
+
*
|
|
4
|
+
* A status page is indexable unless its owner turned indexing off
|
|
5
|
+
* (StatusPage.enableSearchEngineIndexing, which defaults to true). The
|
|
6
|
+
* opt-out is carried to crawlers two ways:
|
|
7
|
+
*
|
|
8
|
+
* - <meta name="robots" content="noindex, nofollow"> in the server-rendered
|
|
9
|
+
* index.ejs, which is in the HTML before the JS bundle loads
|
|
10
|
+
* - an X-Robots-Tag response header, which crawlers also honour on
|
|
11
|
+
* responses that are not HTML (the RSS feed, llms.txt)
|
|
12
|
+
*
|
|
13
|
+
* Both live here rather than in each renderer because the status page is
|
|
14
|
+
* rendered by two servers - the standalone status-page container
|
|
15
|
+
* (App/FeatureSet/StatusPage/Serve.ts) and the combined App container
|
|
16
|
+
* (App/FeatureSet/Frontend/Index.ts) - and the two must not drift.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
* nofollow rides along with noindex: a page that is meant to stay out of
|
|
21
|
+
* search results should not be passing crawl signals to the pages it links to
|
|
22
|
+
* either. This is the same directive Atlassian Statuspage and Status.io emit
|
|
23
|
+
* for their equivalent setting.
|
|
24
|
+
*/
|
|
25
|
+
export const NOINDEX_ROBOTS_DIRECTIVE: string = "noindex, nofollow";
|
|
26
|
+
|
|
27
|
+
export const X_ROBOTS_TAG_HEADER_NAME: string = "X-Robots-Tag";
|
|
28
|
+
|
|
29
|
+
/*
|
|
30
|
+
* Name of the flag on the status page /seo API response, and of the variable
|
|
31
|
+
* handed to index.ejs. Kept as a constant so the API, the two renderers and
|
|
32
|
+
* the template cannot disagree about the spelling.
|
|
33
|
+
*/
|
|
34
|
+
export const SEARCH_ENGINE_INDEXING_FLAG_NAME: string =
|
|
35
|
+
"enableSearchEngineIndexing";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Reads the indexing flag off an untyped value - a JSON field from the /seo
|
|
39
|
+
* API, or a column that predates the migration.
|
|
40
|
+
*
|
|
41
|
+
* Everything that is not an explicit "off" means indexable. Failing this open
|
|
42
|
+
* is deliberate: the flag reaches the renderers over an internal HTTP call,
|
|
43
|
+
* and a blip on that call must not de-index a page whose owner never asked for
|
|
44
|
+
* that. The opposite failure (one render of a noindex page missing its meta
|
|
45
|
+
* tag) costs nothing permanent, because crawlers re-fetch.
|
|
46
|
+
*/
|
|
47
|
+
export function isSearchEngineIndexingEnabled(value: unknown): boolean {
|
|
48
|
+
if (value === false) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/*
|
|
53
|
+
* JSON round-trips and query strings can turn the boolean into a string.
|
|
54
|
+
* "false" is the only spelling either produces for false.
|
|
55
|
+
*/
|
|
56
|
+
if (value === "false") {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The resource facets of the telemetry explorers (Logs / Traces), split by
|
|
3
|
+
* how a selection has to be turned into a predicate.
|
|
4
|
+
*
|
|
5
|
+
* A signal row names exactly one *primary* entity (`primaryEntityId` +
|
|
6
|
+
* `primaryEntityType`) and, since the entity model shipped, the full
|
|
7
|
+
* membership set it belongs to (`entityKeys`). Which of the two a facet
|
|
8
|
+
* selection has to be matched against depends on the ingestion path:
|
|
9
|
+
*
|
|
10
|
+
* - Agent-ingested resource telemetry (Infrastructure / Docker / Podman /
|
|
11
|
+
* Kubernetes agents) has no `service.name`, so the resource IS the
|
|
12
|
+
* primary entity and `primaryEntityId` holds its Postgres id.
|
|
13
|
+
* - OTLP telemetry that carries a `service.name` is primary-keyed on its
|
|
14
|
+
* Service (`OtelIngestBaseService.selectPrimaryEntity`); the host /
|
|
15
|
+
* cluster it runs on is recorded only in `entityKeys`.
|
|
16
|
+
*
|
|
17
|
+
* The second case is why coalescing every resource facet into one
|
|
18
|
+
* `primaryEntityId IN (...)` list returned nothing for a Kubernetes cluster
|
|
19
|
+
* ingested through an OpenTelemetry Collector: the cluster id was compared
|
|
20
|
+
* against a column that only ever held the Service id. Selections on these
|
|
21
|
+
* facets therefore compile to a per-facet OR of both memberships, and the
|
|
22
|
+
* per-facet groups AND with each other so "cluster X" + "service Y"
|
|
23
|
+
* intersects instead of unioning.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Facets whose values are Service ids — the ids that legitimately live in
|
|
28
|
+
* `primaryEntityId` for OTLP telemetry. `serviceId` is the pre-rename alias
|
|
29
|
+
* kept for stale clients (see ResourceFacetResolver).
|
|
30
|
+
*/
|
|
31
|
+
export const SERVICE_FACET_KEYS: ReadonlyArray<string> = [
|
|
32
|
+
"primaryEntityId",
|
|
33
|
+
"serviceId",
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Facets whose values are ids of a NON-Service resource row. These are the
|
|
38
|
+
* ones that need the entity-key treatment; the value is a Postgres id
|
|
39
|
+
* (Host / DockerHost / PodmanHost / KubernetesCluster) which the server
|
|
40
|
+
* resolves to the resource's identifying value and then to its entity key.
|
|
41
|
+
*/
|
|
42
|
+
export const RESOURCE_ENTITY_FACET_KEYS: ReadonlyArray<string> = [
|
|
43
|
+
"hostId",
|
|
44
|
+
"dockerHostId",
|
|
45
|
+
"podmanHostId",
|
|
46
|
+
"kubernetesClusterId",
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
const RESOURCE_ENTITY_FACET_KEY_SET: ReadonlySet<string> = new Set<string>(
|
|
50
|
+
RESOURCE_ENTITY_FACET_KEYS,
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const SERVICE_FACET_KEY_SET: ReadonlySet<string> = new Set<string>(
|
|
54
|
+
SERVICE_FACET_KEYS,
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Every facet key that names a resource, in either group. Kept so call
|
|
59
|
+
* sites that only need "is this a resource chip?" (chip rendering, scope
|
|
60
|
+
* hand-off) do not have to consult both sets.
|
|
61
|
+
*/
|
|
62
|
+
export const ALL_RESOURCE_FACET_KEYS: ReadonlyArray<string> = [
|
|
63
|
+
...SERVICE_FACET_KEYS,
|
|
64
|
+
...RESOURCE_ENTITY_FACET_KEYS,
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
export function isServiceFacetKey(facetKey: string): boolean {
|
|
68
|
+
return SERVICE_FACET_KEY_SET.has(facetKey);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function isResourceEntityFacetKey(facetKey: string): boolean {
|
|
72
|
+
return RESOURCE_ENTITY_FACET_KEY_SET.has(facetKey);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function isResourceFacetKey(facetKey: string): boolean {
|
|
76
|
+
return isServiceFacetKey(facetKey) || isResourceEntityFacetKey(facetKey);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Selected ids per non-Service resource facet, e.g.
|
|
81
|
+
* `{ kubernetesClusterId: ["<id>"] }`. This is the wire shape sent to the
|
|
82
|
+
* aggregation endpoints (`resourceFilters` in the POST body) and carried on
|
|
83
|
+
* the analytics list query under the same key.
|
|
84
|
+
*/
|
|
85
|
+
export type ResourceEntityFacetSelections = Record<string, Array<string>>;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Collect the non-Service resource selections out of applied facet filters.
|
|
89
|
+
* Accepts anything entry-iterable so the Logs explorer can pass a
|
|
90
|
+
* `Map<string, Set<string>>` and the Traces explorer a plain record via
|
|
91
|
+
* `Object.entries`.
|
|
92
|
+
*
|
|
93
|
+
* Values are de-duplicated and empty facets are dropped, so an emptied chip
|
|
94
|
+
* group never becomes a `[]` that a reader might read as "match nothing".
|
|
95
|
+
*/
|
|
96
|
+
export function collectResourceEntityFacetSelections(
|
|
97
|
+
entries: Iterable<[string, Iterable<string>]>,
|
|
98
|
+
): ResourceEntityFacetSelections {
|
|
99
|
+
const selections: ResourceEntityFacetSelections = {};
|
|
100
|
+
|
|
101
|
+
for (const [facetKey, values] of entries) {
|
|
102
|
+
if (!isResourceEntityFacetKey(facetKey)) {
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const unique: Set<string> = new Set<string>(selections[facetKey] || []);
|
|
107
|
+
|
|
108
|
+
for (const value of values) {
|
|
109
|
+
if (typeof value === "string" && value.length > 0) {
|
|
110
|
+
unique.add(value);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (unique.size > 0) {
|
|
115
|
+
selections[facetKey] = Array.from(unique);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return selections;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** Collect the Service-facet selections, same rules as the helper above. */
|
|
123
|
+
export function collectServiceFacetSelections(
|
|
124
|
+
entries: Iterable<[string, Iterable<string>]>,
|
|
125
|
+
): Array<string> {
|
|
126
|
+
const unique: Set<string> = new Set<string>();
|
|
127
|
+
|
|
128
|
+
for (const [facetKey, values] of entries) {
|
|
129
|
+
if (!isServiceFacetKey(facetKey)) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
for (const value of values) {
|
|
134
|
+
if (typeof value === "string" && value.length > 0) {
|
|
135
|
+
unique.add(value);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return Array.from(unique);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/*
|
|
144
|
+
* Ids are ObjectID (UUID) strings. Validating the shape here means a
|
|
145
|
+
* malformed filter is dropped at the edge instead of reaching a lookup or a
|
|
146
|
+
* SQL parameter.
|
|
147
|
+
*/
|
|
148
|
+
const UUID_PATTERN: RegExp =
|
|
149
|
+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
150
|
+
|
|
151
|
+
/** Upper bound on ids per facet, so a crafted request cannot send an unbounded list. */
|
|
152
|
+
export const MAX_RESOURCE_IDS_PER_FACET: number = 200;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Parse an untrusted `resourceFilters` value (request body field or a
|
|
156
|
+
* persisted saved-view query) into the canonical selection shape.
|
|
157
|
+
*
|
|
158
|
+
* Deliberately lenient: anything that is not `{ <known facet key>:
|
|
159
|
+
* <uuid>[] }` is dropped rather than turned into a predicate, because a
|
|
160
|
+
* malformed filter must mean "no constraint" — never "match nothing", which
|
|
161
|
+
* would show an empty explorer with no explanation.
|
|
162
|
+
*/
|
|
163
|
+
export function parseResourceEntityFacetSelections(
|
|
164
|
+
source: unknown,
|
|
165
|
+
): ResourceEntityFacetSelections {
|
|
166
|
+
const selections: ResourceEntityFacetSelections = {};
|
|
167
|
+
|
|
168
|
+
if (!source || typeof source !== "object" || Array.isArray(source)) {
|
|
169
|
+
return selections;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const record: Record<string, unknown> = source as Record<string, unknown>;
|
|
173
|
+
|
|
174
|
+
for (const facetKey of Object.keys(record)) {
|
|
175
|
+
if (!isResourceEntityFacetKey(facetKey)) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const raw: unknown = record[facetKey];
|
|
180
|
+
|
|
181
|
+
if (!Array.isArray(raw)) {
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const ids: Array<string> = Array.from(
|
|
186
|
+
new Set(
|
|
187
|
+
(raw as Array<unknown>).filter((value: unknown): value is string => {
|
|
188
|
+
return typeof value === "string" && UUID_PATTERN.test(value);
|
|
189
|
+
}),
|
|
190
|
+
),
|
|
191
|
+
).slice(0, MAX_RESOURCE_IDS_PER_FACET);
|
|
192
|
+
|
|
193
|
+
if (ids.length > 0) {
|
|
194
|
+
selections[facetKey] = ids;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return selections;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function hasResourceEntityFacetSelections(
|
|
202
|
+
selections: ResourceEntityFacetSelections | undefined,
|
|
203
|
+
): boolean {
|
|
204
|
+
if (!selections) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return Object.keys(selections).some((key: string): boolean => {
|
|
209
|
+
return (selections[key] || []).length > 0;
|
|
210
|
+
});
|
|
211
|
+
}
|