@datalayer/core 1.2.17 → 1.2.19
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/lib/cli-login.js +5 -51
- package/lib/components/anonymous/AnonymousKeyExpired.js +1 -15
- package/lib/components/anonymous/AnonymousKeyTimer.js +5 -15
- package/lib/components/auth/SignIn.js +2 -2
- package/lib/components/avatars/UserAvatar.js +3 -27
- package/lib/components/billing/BillingEntitySelect.js +6 -48
- package/lib/components/checkout/StripeCheckout.js +33 -217
- package/lib/components/contents/ContentSourceCard.js +2 -11
- package/lib/components/contents/HomeFolderObjectsBrowser.d.ts +1 -1
- package/lib/components/contents/HomeFolderObjectsBrowser.js +11 -35
- package/lib/components/display/CenteredSpinner.js +1 -6
- package/lib/components/display/DatalayerBox.js +2 -14
- package/lib/components/flashes/FlashClosable.js +2 -17
- package/lib/components/mcp/ClientBadge.js +1 -1
- package/lib/components/mcp/McpErrorBlankslate.js +1 -1
- package/lib/components/mcp/ScopeList.js +1 -1
- package/lib/components/notebooks/JupyterNotebook.js +1 -2
- package/lib/components/principal/Principal.js +2 -10
- package/lib/components/principal/PrincipalAppearance.js +19 -63
- package/lib/components/principal/PrincipalAvatar.js +5 -25
- package/lib/components/principal/PrincipalBadge.js +3 -13
- package/lib/components/principal/PrincipalBanner.js +4 -32
- package/lib/components/principal/PrincipalDetailsOverlay.js +7 -23
- package/lib/components/principal/PrincipalHoverCard.js +15 -18
- package/lib/components/principal/PrincipalSwitcherMenu.js +15 -83
- package/lib/components/progress/ConsumptionBar.js +1 -1
- package/lib/components/sharing/ShareAccessComponent.js +21 -229
- package/lib/components/sharing/SharingEditor.js +1 -1
- package/lib/components/spaces/SpaceDetailsOverlay.js +4 -35
- package/lib/components/spaces/SpaceDisplay.js +1 -8
- package/lib/components/storage/ContentsBrowser.js +3 -26
- package/lib/components/storage/ContentsTable.js +4 -23
- package/lib/components/students/StudentResultCircle.js +7 -29
- package/lib/components/timeline/Timeline.js +4 -36
- package/lib/hooks/layouts/LayoutBackdrop.js +2 -1
- package/lib/hooks/layouts/LayoutScreencapture.js +1 -1
- package/lib/hooks/libraryApp.d.ts +6 -1
- package/lib/hooks/libraryApp.js +10 -1
- package/lib/hooks/useAuthorization.js +6 -1
- package/lib/mocks/components/FlashMock.js +3 -8
- package/lib/mocks/views/DashboardMock.js +6 -72
- package/lib/mocks/views/FormMock.js +3 -2
- package/lib/mocks/views/TableMock.js +3 -2
- package/lib/mocks/views/WipMock.js +2 -1
- package/lib/models/Person.d.ts +9 -0
- package/lib/models/Person.js +23 -0
- package/lib/otel/index.d.ts +4 -0
- package/lib/otel/index.js +3 -0
- package/lib/otel/live/filter.d.ts +15 -0
- package/lib/otel/live/filter.js +16 -0
- package/lib/otel/live/index.d.ts +10 -0
- package/lib/otel/live/index.js +14 -0
- package/lib/otel/live/tracer.d.ts +94 -0
- package/lib/otel/live/tracer.js +223 -0
- package/lib/otel/live/useOtelLiveSpans.d.ts +6 -0
- package/lib/otel/live/useOtelLiveSpans.js +22 -0
- package/lib/otel/types.d.ts +17 -0
- package/lib/otel/views/OtelLive.js +4 -62
- package/lib/otel/views/OtelLiveSpans.d.ts +52 -0
- package/lib/otel/views/OtelLiveSpans.js +114 -0
- package/lib/otel/views/OtelLogsList.js +13 -64
- package/lib/otel/views/OtelMetricsChart.js +4 -19
- package/lib/otel/views/OtelMetricsList.js +8 -77
- package/lib/otel/views/OtelSearchBar.js +3 -12
- package/lib/otel/views/OtelSpanDetail.d.ts +6 -0
- package/lib/otel/views/OtelSpanDetail.js +31 -81
- package/lib/otel/views/OtelSpanTree.js +7 -57
- package/lib/otel/views/OtelSqlView.js +5 -99
- package/lib/otel/views/OtelSystemView.js +4 -34
- package/lib/otel/views/OtelTimeline.js +7 -37
- package/lib/otel/views/OtelTimelineRangeSlider.js +7 -140
- package/lib/otel/views/OtelTracesList.js +39 -87
- package/lib/otel/views/index.d.ts +3 -0
- package/lib/otel/views/index.js +2 -0
- package/lib/portable/index.d.ts +8 -0
- package/lib/portable/index.js +12 -0
- package/lib/state/substates/NavigationState.d.ts +6 -4
- package/lib/state/substates/NavigationState.js +6 -5
- package/lib/views/api-keys/APIKeyEdit.js +2 -11
- package/lib/views/api-keys/APIKeyNew.js +3 -19
- package/lib/views/api-keys/APIKeys.js +6 -11
- package/lib/views/api-keys/APIKeysStandalone.js +1 -1
- package/lib/views/datasources/DatasourceDetail.d.ts +1 -1
- package/lib/views/datasources/DatasourceDetail.js +24 -17
- package/lib/views/datasources/DatasourceNew.js +2 -6
- package/lib/views/datasources/Datasources.js +2 -14
- package/lib/views/iam/SignInSimple.js +8 -64
- package/lib/views/mcp/AdmittedClients.js +3 -16
- package/lib/views/mcp/AlertDestinations.js +2 -10
- package/lib/views/mcp/AlertRules.js +4 -9
- package/lib/views/mcp/ApprovalQueue.js +4 -21
- package/lib/views/mcp/AuditLog.js +7 -44
- package/lib/views/mcp/ConnectedAgents.js +1 -6
- package/lib/views/mcp/EnterpriseConsole.js +10 -23
- package/lib/views/mcp/IdentityProviders.js +7 -31
- package/lib/views/mcp/McpDashboard.js +14 -30
- package/lib/views/mcp/McpHome.js +7 -54
- package/lib/views/mcp/McpObservability.js +13 -85
- package/lib/views/mcp/NotebookRuns.js +5 -12
- package/lib/views/mcp/OrganizationPolicy.js +3 -9
- package/lib/views/mcp/OrganizationUsage.js +4 -11
- package/lib/views/mcp/PersonalPolicy.js +3 -3
- package/lib/views/mcp/Policies.js +5 -46
- package/lib/views/mcp/PolicyForm.js +1 -9
- package/lib/views/mcp/PolicyHistory.js +2 -8
- package/lib/views/mcp/RunDetail.js +3 -25
- package/lib/views/mcp/ScimProvisioning.js +3 -15
- package/lib/views/mcp/ServiceAgents.js +4 -17
- package/lib/views/mcp/TeamPolicies.js +7 -19
- package/lib/views/mcp/ToolAccess.js +15 -22
- package/lib/views/mcp/TraceTimeline.js +8 -23
- package/lib/views/otel/DashboardView.js +2 -2
- package/lib/views/otel/LogsView.js +2 -2
- package/lib/views/otel/MetricsView.js +2 -2
- package/lib/views/otel/OtelHeader.js +6 -40
- package/lib/views/otel/SqlView.js +2 -2
- package/lib/views/otel/SystemView.js +2 -2
- package/lib/views/otel/TracesView.js +2 -2
- package/lib/views/profile/UserBadge.js +6 -98
- package/lib/views/secrets/SecretEdit.js +2 -11
- package/lib/views/secrets/SecretNew.js +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Box
|
|
2
|
+
import { Box } from '@datalayer/primer-addons';
|
|
3
|
+
import { Text } from '@primer/react';
|
|
3
4
|
const statusStyles = {
|
|
4
5
|
done: {
|
|
5
6
|
dotBackground: 'success.emphasis',
|
|
@@ -42,44 +43,11 @@ export const Timeline = ({ items, renderTimestamp }) => {
|
|
|
42
43
|
if (!items.length) {
|
|
43
44
|
return null;
|
|
44
45
|
}
|
|
45
|
-
return (_jsx(Box, {
|
|
46
|
-
overflowX: 'auto',
|
|
47
|
-
pb: 1,
|
|
48
|
-
}, children: _jsx(Box, { sx: {
|
|
49
|
-
display: 'flex',
|
|
50
|
-
alignItems: 'stretch',
|
|
51
|
-
minWidth: 'max-content',
|
|
52
|
-
}, children: items.map((item, index) => {
|
|
46
|
+
return (_jsx(Box, { overflowX: "auto", pb: 1, children: _jsx(Box, { display: "flex", alignItems: "stretch", minWidth: "max-content", children: items.map((item, index) => {
|
|
53
47
|
const status = item.status || 'neutral';
|
|
54
48
|
const style = statusStyles[status];
|
|
55
49
|
const hasNext = index < items.length - 1;
|
|
56
|
-
return (_jsxs(Box, { sx: {
|
|
57
|
-
display: 'flex',
|
|
58
|
-
flexDirection: 'column',
|
|
59
|
-
minWidth: 220,
|
|
60
|
-
flex: hasNext ? '0 0 220px' : '0 0 auto',
|
|
61
|
-
pr: hasNext ? 0 : 1,
|
|
62
|
-
}, children: [_jsxs(Box, { sx: {
|
|
63
|
-
display: 'flex',
|
|
64
|
-
alignItems: 'center',
|
|
65
|
-
minHeight: 28,
|
|
66
|
-
mb: 2,
|
|
67
|
-
}, children: [_jsx(Box, { sx: {
|
|
68
|
-
width: 16,
|
|
69
|
-
height: 16,
|
|
70
|
-
borderRadius: '50%',
|
|
71
|
-
border: '2px solid',
|
|
72
|
-
borderColor: style.dotBorder,
|
|
73
|
-
bg: style.dotBackground,
|
|
74
|
-
boxShadow: 'inset 0 0 0 1px rgba(255,255,255,0.2)',
|
|
75
|
-
} }), hasNext ? (_jsx(Box, { sx: {
|
|
76
|
-
flex: 1,
|
|
77
|
-
height: 4,
|
|
78
|
-
ml: 2,
|
|
79
|
-
mr: 2,
|
|
80
|
-
borderRadius: 999,
|
|
81
|
-
bg: style.lineColor,
|
|
82
|
-
} })) : null] }), _jsx(Text, { as: "p", sx: { fontWeight: 600, color: style.titleColor, mb: 1 }, children: item.title }), _jsx(Text, { as: "p", sx: {
|
|
50
|
+
return (_jsxs(Box, { display: "flex", flexDirection: "column", minWidth: 220, flex: hasNext ? '0 0 220px' : '0 0 auto', pr: hasNext ? 0 : 1, children: [_jsxs(Box, { display: "flex", alignItems: "center", minHeight: 28, mb: 2, children: [_jsx(Box, { width: 16, height: 16, borderRadius: "50%", border: "2px solid", borderColor: style.dotBorder, bg: style.dotBackground, boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.2)" }), hasNext ? (_jsx(Box, { flex: 1, height: 4, ml: 2, mr: 2, borderRadius: 999, bg: style.lineColor })) : null] }), _jsx(Text, { as: "p", sx: { fontWeight: 600, color: style.titleColor, mb: 1 }, children: item.title }), _jsx(Text, { as: "p", sx: {
|
|
83
51
|
fontSize: 0,
|
|
84
52
|
color: 'fg.muted',
|
|
85
53
|
mb: item.subtitle ? 1 : 0,
|
|
@@ -4,7 +4,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
6
|
import { useEffect } from 'react';
|
|
7
|
-
import {
|
|
7
|
+
import { Box } from '@datalayer/primer-addons';
|
|
8
|
+
import { Heading, Spinner } from '@primer/react';
|
|
8
9
|
import { useBackdrop } from '../index.js';
|
|
9
10
|
import { useLayoutStore } from '../../state/index.js';
|
|
10
11
|
const BackdropContent = (props) => {
|
|
@@ -4,7 +4,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
6
|
import { useEffect } from 'react';
|
|
7
|
-
import { Box } from '@primer
|
|
7
|
+
import { Box } from '@datalayer/primer-addons';
|
|
8
8
|
import { useScreencapture, useToast } from '../index.js';
|
|
9
9
|
import { lazyWithPreload, WithSuspense } from '../../utils/index.js';
|
|
10
10
|
import { useLayoutStore } from '../../state/index.js';
|
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
* projection carries them: `face_s` (the JSON of its `id`, `emoji`, `avatar`
|
|
7
7
|
* and `banner`, each only when set), `app_kind_s` and `runs_live_b` — an app
|
|
8
8
|
* that runs live can be tried before it is cloned: not a decision, and naming
|
|
9
|
-
* the agent it runs on.
|
|
9
|
+
* the agent it runs on. One of Datalayer's examples, published from the
|
|
10
|
+
* catalogue, also says which (`catalogue_example_s`), beside `publisher_s:
|
|
11
|
+
* datalayer` — the Library projects both only for an item of the `datalayer`
|
|
12
|
+
* organization's spaces whose metadata says `catalogueExample` (STUDIO E-10).
|
|
10
13
|
*
|
|
11
14
|
* @module hooks/libraryApp
|
|
12
15
|
*/
|
|
@@ -30,6 +33,8 @@ export type LibraryAppFields = {
|
|
|
30
33
|
appKind?: LibraryAppKind;
|
|
31
34
|
/** Whether it can be tried before it is cloned. */
|
|
32
35
|
runsLive: boolean;
|
|
36
|
+
/** The example of the catalogue it is, when it is one of Datalayer's. */
|
|
37
|
+
catalogueExample?: string;
|
|
33
38
|
};
|
|
34
39
|
/** The face `face_s` carries; a value that is not a face's JSON is refused. */
|
|
35
40
|
export declare function libraryAppFaceOf(value: unknown): LibraryAppFace | undefined;
|
package/lib/hooks/libraryApp.js
CHANGED
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
* projection carries them: `face_s` (the JSON of its `id`, `emoji`, `avatar`
|
|
11
11
|
* and `banner`, each only when set), `app_kind_s` and `runs_live_b` — an app
|
|
12
12
|
* that runs live can be tried before it is cloned: not a decision, and naming
|
|
13
|
-
* the agent it runs on.
|
|
13
|
+
* the agent it runs on. One of Datalayer's examples, published from the
|
|
14
|
+
* catalogue, also says which (`catalogue_example_s`), beside `publisher_s:
|
|
15
|
+
* datalayer` — the Library projects both only for an item of the `datalayer`
|
|
16
|
+
* organization's spaces whose metadata says `catalogueExample` (STUDIO E-10).
|
|
14
17
|
*
|
|
15
18
|
* @module hooks/libraryApp
|
|
16
19
|
*/
|
|
@@ -50,10 +53,16 @@ export function libraryAppFieldsOf(raw) {
|
|
|
50
53
|
!LIBRARY_APP_KINDS.includes(kind)) {
|
|
51
54
|
throw new Error(`An app's kind is not one of ${LIBRARY_APP_KINDS}: ${String(kind)}`);
|
|
52
55
|
}
|
|
56
|
+
const example = raw.catalogue_example_s;
|
|
57
|
+
if (example !== undefined &&
|
|
58
|
+
(typeof example !== 'string' || example.trim() === '')) {
|
|
59
|
+
throw new Error(`An app's example is not an example's id: ${String(example)}`);
|
|
60
|
+
}
|
|
53
61
|
const face = libraryAppFaceOf(raw.face_s);
|
|
54
62
|
return {
|
|
55
63
|
...(face ? { face } : {}),
|
|
56
64
|
...(kind ? { appKind: kind } : {}),
|
|
57
65
|
runsLive: raw.runs_live_b === true,
|
|
66
|
+
...(example ? { catalogueExample: example } : {}),
|
|
58
67
|
};
|
|
59
68
|
}
|
|
@@ -35,8 +35,13 @@ export const useAuthorization = () => {
|
|
|
35
35
|
const checkIsPlatformMember = (user) => {
|
|
36
36
|
return user.roles.includes(PlatformRoles.Member.handle);
|
|
37
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* Whether the user sees the features that are not released yet: a Platform
|
|
40
|
+
* Features Previewer, or a Platform Admin — an admin previews everything.
|
|
41
|
+
*/
|
|
38
42
|
const checkIsPlatformFeaturesPreviewer = (user) => {
|
|
39
|
-
return user.roles.includes(PlatformRoles.FeaturesPreviewer.handle)
|
|
43
|
+
return (user.roles.includes(PlatformRoles.FeaturesPreviewer.handle) ||
|
|
44
|
+
checkIsPlatformAdmin(user));
|
|
40
45
|
};
|
|
41
46
|
const checkIsPlatformUsageReviewer = (user) => {
|
|
42
47
|
return user.roles.includes(PlatformRoles.UsageReviewer.handle);
|
|
@@ -4,16 +4,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
6
|
import { AlertIcon } from '@primer/octicons-react';
|
|
7
|
-
import { Box
|
|
7
|
+
import { Box } from '@datalayer/primer-addons';
|
|
8
|
+
import { Button, Flash } from '@primer/react';
|
|
8
9
|
import { useNavigate } from '../../hooks/index.js';
|
|
9
10
|
export const FlashMock = () => {
|
|
10
11
|
const navigate = useNavigate();
|
|
11
|
-
return (_jsx(Flash, { variant: "warning", style: { marginBottom: 10 }, children: _jsxs(Box, {
|
|
12
|
-
display: 'flex',
|
|
13
|
-
alignItems: 'center',
|
|
14
|
-
justifyContent: 'space-between',
|
|
15
|
-
gap: 3,
|
|
16
|
-
width: '100%',
|
|
17
|
-
}, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(AlertIcon, {}), _jsx("span", { children: "This is placeholder content. Contact us to learn more about this feature." })] }), _jsx(Button, { size: "small", onClick: () => navigate('/contact'), children: "Contact Us" })] }) }));
|
|
12
|
+
return (_jsx(Flash, { variant: "warning", style: { marginBottom: 10 }, children: _jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 3, width: "100%", children: [_jsxs(Box, { display: "flex", alignItems: "center", gap: 2, children: [_jsx(AlertIcon, {}), _jsx("span", { children: "This is placeholder content. Contact us to learn more about this feature." })] }), _jsx(Button, { size: "small", onClick: () => navigate('/contact'), children: "Contact Us" })] }) }));
|
|
18
13
|
};
|
|
19
14
|
export default FlashMock;
|
|
@@ -3,36 +3,15 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
|
-
import { Box
|
|
6
|
+
import { Box } from '@datalayer/primer-addons';
|
|
7
|
+
import { Link, Text, LabelGroup, Label, ActionMenu, ActionList, } from '@primer/react';
|
|
7
8
|
import { ArrowRightIcon, CloudIcon, StarIcon, DotFillIcon, RepoForkedIcon, LinkIcon, } from '@primer/octicons-react';
|
|
8
9
|
import { ReactJsIcon } from '@datalayer/icons-react';
|
|
9
10
|
import { lazyWithPreload, WithSuspense } from '../../utils/index.js';
|
|
10
11
|
import { ECHART_MOCK_1, ECHART_MOCK_2, ECHART_MOCK_3, FlashMock, } from '../../mocks/index.js';
|
|
11
12
|
const ReactECharts = WithSuspense(lazyWithPreload(() => import('echarts-for-react')), true);
|
|
12
13
|
export const DashboardMock = () => {
|
|
13
|
-
return (_jsxs(_Fragment, { children: [_jsx(Box, { mb: 3, children: _jsx(FlashMock, {}) }), _jsxs(Box, { sx: {
|
|
14
|
-
display: 'grid',
|
|
15
|
-
gridTemplateColumns: '1fr 1fr 1fr',
|
|
16
|
-
gap: 4,
|
|
17
|
-
}, children: [_jsxs(Box, { sx: {
|
|
18
|
-
gridColumn: '1 / 3',
|
|
19
|
-
minHeight: '200px',
|
|
20
|
-
}, children: [_jsxs(Box, { sx: {
|
|
21
|
-
display: 'flex',
|
|
22
|
-
alignItems: 'center',
|
|
23
|
-
justifyContent: 'space-between',
|
|
24
|
-
paddingRight: 4,
|
|
25
|
-
}, children: [_jsx(Text, { as: "h2", sx: { borderLeft: '4px solid #28b899', paddingLeft: 2 }, children: "My latest work" }), _jsxs(Link, { children: ["View all work", _jsx(ArrowRightIcon, {})] })] }), _jsxs(Box, { sx: {
|
|
26
|
-
display: 'grid',
|
|
27
|
-
gridTemplateColumns: '1fr 1fr',
|
|
28
|
-
gap: 4,
|
|
29
|
-
}, children: [_jsxs(Box, { sx: {
|
|
30
|
-
borderColor: 'border.default',
|
|
31
|
-
borderStyle: 'solid',
|
|
32
|
-
borderWidth: '1',
|
|
33
|
-
borderRadius: '2',
|
|
34
|
-
padding: 4,
|
|
35
|
-
}, children: [_jsxs(Text, { as: "h3", sx: { paddingBottom: 2 }, children: ["clouder ", _jsx(Label, { children: "Public" })] }), _jsxs(Text, { as: "p", sx: { color: 'fg.subtle', fontWeight: 'semibold' }, children: [_jsx(CloudIcon
|
|
14
|
+
return (_jsxs(_Fragment, { children: [_jsx(Box, { mb: 3, children: _jsx(FlashMock, {}) }), _jsxs(Box, { display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 4, children: [_jsxs(Box, { gridColumn: "1 / 3", minHeight: "200px", children: [_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", paddingRight: 4, children: [_jsx(Text, { as: "h2", sx: { borderLeft: '4px solid #28b899', paddingLeft: 2 }, children: "My latest work" }), _jsxs(Link, { children: ["View all work", _jsx(ArrowRightIcon, {})] })] }), _jsxs(Box, { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 4, children: [_jsxs(Box, { borderColor: "border.default", borderStyle: "solid", borderWidth: "1", borderRadius: "2", padding: 4, children: [_jsxs(Text, { as: "h3", sx: { paddingBottom: 2 }, children: ["clouder ", _jsx(Label, { children: "Public" })] }), _jsxs(Text, { as: "p", sx: { color: 'fg.subtle', fontWeight: 'semibold' }, children: [_jsx(CloudIcon
|
|
36
15
|
// sx={{ margin: "0 4px" }}
|
|
37
16
|
, {}), "Create, manage and share Kubernetes clusters."] }), _jsxs(LabelGroup, { sx: { paddingTop: 2, paddingBottom: 2 }, children: [_jsx(Label, { variant: "accent", children: "Kubernetes" }), _jsx(Label, { variant: "accent", children: "cloud" }), _jsx(Label, { variant: "accent", children: "kubernets-cluster" }), _jsx(Label, { variant: "accent", children: "datalayer" })] }), _jsxs(Text, { as: "p", sx: {
|
|
38
17
|
color: 'fg.subtle',
|
|
@@ -47,13 +26,7 @@ export const DashboardMock = () => {
|
|
|
47
26
|
// sx={{ marginRight: 1, marginBottom: "3px" }}
|
|
48
27
|
, {}), "3"] }), _jsxs(Text, { children: [_jsx(StarIcon
|
|
49
28
|
// sx={{ marginRight: 1, marginBottom: "3px" }}
|
|
50
|
-
, {}), "11"] })] })] }), _jsxs(Box, { sx: {
|
|
51
|
-
borderColor: 'border.default',
|
|
52
|
-
borderStyle: 'solid',
|
|
53
|
-
borderWidth: '1',
|
|
54
|
-
borderRadius: '2',
|
|
55
|
-
padding: 4,
|
|
56
|
-
}, children: [_jsxs(Text, { as: "h3", sx: { paddingBottom: 2 }, children: ["jupyter-ui ", _jsx(Label, { children: "Public" })] }), _jsxs(Text, { as: "p", children: [_jsx(ReactJsIcon, { style: { margin: '0 4px' } }), "React.js components 100% compatible with Jupyter.", ' ', _jsx(Link, { href: "https://jupyter-ui-storybook.datalayer.tech", children: "https://jupyter-ui-storybook.datalayer.tech" })] }), _jsxs(LabelGroup, { sx: { paddingTop: 2, paddingBottom: 2 }, children: [_jsx(Label, { variant: "accent", children: "data-science" }), _jsx(Label, { variant: "accent", children: "data" }), _jsx(Label, { variant: "accent", children: "ui" }), _jsx(Label, { variant: "accent", children: "jupyter" }), _jsx(Label, { children: "+4" })] }), _jsxs(Text, { as: "p", sx: {
|
|
29
|
+
, {}), "11"] })] })] }), _jsxs(Box, { borderColor: "border.default", borderStyle: "solid", borderWidth: "1", borderRadius: "2", padding: 4, children: [_jsxs(Text, { as: "h3", sx: { paddingBottom: 2 }, children: ["jupyter-ui ", _jsx(Label, { children: "Public" })] }), _jsxs(Text, { as: "p", children: [_jsx(ReactJsIcon, { style: { margin: '0 4px' } }), "React.js components 100% compatible with Jupyter.", ' ', _jsx(Link, { href: "https://jupyter-ui-storybook.datalayer.tech", children: "https://jupyter-ui-storybook.datalayer.tech" })] }), _jsxs(LabelGroup, { sx: { paddingTop: 2, paddingBottom: 2 }, children: [_jsx(Label, { variant: "accent", children: "data-science" }), _jsx(Label, { variant: "accent", children: "data" }), _jsx(Label, { variant: "accent", children: "ui" }), _jsx(Label, { variant: "accent", children: "jupyter" }), _jsx(Label, { children: "+4" })] }), _jsxs(Text, { as: "p", sx: {
|
|
57
30
|
color: 'fg.subtle',
|
|
58
31
|
'> *': { paddingLeft: 1, paddingRight: 1 },
|
|
59
32
|
}, children: [_jsxs(Text, { children: [_jsx(DotFillIcon
|
|
@@ -68,51 +41,12 @@ export const DashboardMock = () => {
|
|
|
68
41
|
// sx={{ marginRight: 1, marginBottom: "3px" }}
|
|
69
42
|
, {}), "3"] }), _jsxs(Text, { children: [_jsx(StarIcon
|
|
70
43
|
// sx={{ marginRight: 1, marginBottom: "3px" }}
|
|
71
|
-
, {}), "11"] })] })] })] })] }), _jsxs(Box, { sx: {
|
|
72
|
-
gridColumn: '3 / 4',
|
|
73
|
-
gridRow: '1 / 3',
|
|
74
|
-
minHeight: '200px',
|
|
75
|
-
}, children: [_jsxs(Box, { sx: {
|
|
76
|
-
display: 'flex',
|
|
77
|
-
alignItems: 'center',
|
|
78
|
-
justifyContent: 'space-between',
|
|
79
|
-
paddingRight: 4,
|
|
80
|
-
}, children: [_jsx(Text, { as: "h2", sx: { borderLeft: '4px solid #28b899', paddingLeft: 2 }, children: "Usage" }), _jsxs(Link, { children: ["More Usage", _jsx(ArrowRightIcon, {})] })] }), _jsxs(Box, { sx: {
|
|
81
|
-
borderColor: 'border.default',
|
|
82
|
-
borderStyle: 'solid',
|
|
83
|
-
borderWidth: '1',
|
|
84
|
-
borderRadius: '2',
|
|
85
|
-
padding: 4,
|
|
86
|
-
}, children: [_jsxs(Box, { sx: {
|
|
87
|
-
display: 'inline-flex',
|
|
88
|
-
flexDirection: 'row',
|
|
89
|
-
alignItems: 'center',
|
|
90
|
-
}, children: [_jsx(Text, { as: "h3", sx: { marginRight: '20px' }, children: "Kernels Activity" }), _jsxs(ActionMenu, { children: [_jsxs(ActionMenu.Button, { children: [_jsx(Box, { sx: { color: 'fg.muted', display: 'inline-block' }, children: "View:" }), ' ', 'All kernels'] }), _jsx(ActionMenu.Overlay, { width: "auto", children: _jsx(ActionList, { selectionVariant: "single", children: _jsx(ActionList.Item, { selected: true, children: "All kernels" }) }) })] })] }), _jsx(Text, { as: "h3", children: "Credits usage" }), _jsx(Text, { as: "p", sx: { color: 'fg.subtle' }, children: "Amount today" }), _jsx(Text, { as: "p", sx: { color: 'fg.subtle' }, children: "Balance yesterday" }), _jsx(Text, { as: "h3", children: "Last invoice" }), _jsx(Text, { as: "p", sx: { color: 'fg.subtle', fontSize: '3', fontWeight: 'bold' }, children: "$216" })] })] }), _jsxs(Box, { sx: {
|
|
91
|
-
gridColumn: '1 / 3',
|
|
92
|
-
minHeight: '200px',
|
|
93
|
-
}, children: [_jsxs(Box, { sx: {
|
|
94
|
-
display: 'flex',
|
|
95
|
-
alignItems: 'center',
|
|
96
|
-
justifyContent: 'space-between',
|
|
97
|
-
paddingRight: 4,
|
|
98
|
-
}, children: [_jsx(Text, { as: "h2", sx: { borderLeft: '4px solid #28b899', paddingLeft: 2 }, children: "Trending Notebooks" }), _jsxs(Link, { children: ["All Notebooks", _jsx(ArrowRightIcon, {})] })] }), _jsxs(Box, { sx: {
|
|
99
|
-
borderColor: 'border.default',
|
|
100
|
-
borderStyle: 'solid',
|
|
101
|
-
borderWidth: '1',
|
|
102
|
-
borderRadius: '2',
|
|
103
|
-
display: 'grid',
|
|
104
|
-
gridTemplateColumns: '1fr 1fr',
|
|
44
|
+
, {}), "11"] })] })] })] })] }), _jsxs(Box, { gridColumn: "3 / 4", gridRow: "1 / 3", minHeight: "200px", children: [_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", paddingRight: 4, children: [_jsx(Text, { as: "h2", sx: { borderLeft: '4px solid #28b899', paddingLeft: 2 }, children: "Usage" }), _jsxs(Link, { children: ["More Usage", _jsx(ArrowRightIcon, {})] })] }), _jsxs(Box, { borderColor: "border.default", borderStyle: "solid", borderWidth: "1", borderRadius: "2", padding: 4, children: [_jsxs(Box, { display: "inline-flex", flexDirection: "row", alignItems: "center", children: [_jsx(Text, { as: "h3", sx: { marginRight: '20px' }, children: "Kernels Activity" }), _jsxs(ActionMenu, { children: [_jsxs(ActionMenu.Button, { children: [_jsx(Box, { color: "fg.muted", display: "inline-block", children: "View:" }), ' ', 'All kernels'] }), _jsx(ActionMenu.Overlay, { width: "auto", children: _jsx(ActionList, { selectionVariant: "single", children: _jsx(ActionList.Item, { selected: true, children: "All kernels" }) }) })] })] }), _jsx(Text, { as: "h3", children: "Credits usage" }), _jsx(Text, { as: "p", sx: { color: 'fg.subtle' }, children: "Amount today" }), _jsx(Text, { as: "p", sx: { color: 'fg.subtle' }, children: "Balance yesterday" }), _jsx(Text, { as: "h3", children: "Last invoice" }), _jsx(Text, { as: "p", sx: { color: 'fg.subtle', fontSize: '3', fontWeight: 'bold' }, children: "$216" })] })] }), _jsxs(Box, { gridColumn: "1 / 3", minHeight: "200px", children: [_jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "space-between", paddingRight: 4, children: [_jsx(Text, { as: "h2", sx: { borderLeft: '4px solid #28b899', paddingLeft: 2 }, children: "Trending Notebooks" }), _jsxs(Link, { children: ["All Notebooks", _jsx(ArrowRightIcon, {})] })] }), _jsxs(Box, { borderColor: "border.default", borderStyle: "solid", borderWidth: "1", borderRadius: "2", display: "grid", gridTemplateColumns: "1fr 1fr", sx: {
|
|
105
45
|
'> :not(:last-child)': {
|
|
106
46
|
borderRightColor: 'border.default',
|
|
107
47
|
borderRightStyle: 'solid',
|
|
108
48
|
borderRightWidth: '1',
|
|
109
49
|
},
|
|
110
|
-
}, children: [_jsxs(Box, { sx: {
|
|
111
|
-
padding: 4,
|
|
112
|
-
}, children: [_jsx(Text, { as: "h3", children: "Notebook name abc" }), _jsx(Text, { sx: { color: 'fg.subtle' }, children: "Subtitle comes here" }), _jsxs(Box, { sx: { height: '300px', maxWidth: '380px' }, children: [_jsx(ReactECharts, { option: ECHART_MOCK_1 }), ";"] }), _jsxs(Text, { as: "p", sx: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx(Link, { children: "Link to somewhere" }), _jsxs(Link, { children: ["Second link", _jsx(LinkIcon, {})] })] })] }), _jsxs(Box, { sx: {
|
|
113
|
-
padding: 4,
|
|
114
|
-
}, children: [_jsx(Text, { as: "h3", children: "Notebook name abc" }), _jsx(Text, { sx: { color: 'fg.subtle' }, children: "Subtitle comes here" }), _jsxs(Box, { sx: { height: '300px', maxWidth: '380px' }, children: [_jsx(ReactECharts, { option: ECHART_MOCK_3 }), ";"] }), _jsxs(Text, { as: "p", sx: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx(Link, { children: "Link to somewhere" }), _jsxs(Link, { children: ["Second link", _jsx(LinkIcon, {})] })] })] }), _jsxs(Box, { sx: {
|
|
115
|
-
padding: 4,
|
|
116
|
-
}, children: [_jsx(Text, { as: "h3", children: "Notebook name abc" }), _jsx(Text, { sx: { color: 'fg.subtle' }, children: "Subtitle comes here" }), _jsxs(Box, { sx: { height: '300px', maxWidth: '380px' }, children: [_jsx(ReactECharts, { option: ECHART_MOCK_2 }), ";"] }), _jsxs(Text, { as: "p", sx: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx(Link, { children: "Link to somewhere" }), _jsxs(Link, { children: ["Second link", _jsx(LinkIcon, {})] })] })] })] })] })] })] }));
|
|
50
|
+
}, children: [_jsxs(Box, { padding: 4, children: [_jsx(Text, { as: "h3", children: "Notebook name abc" }), _jsx(Text, { sx: { color: 'fg.subtle' }, children: "Subtitle comes here" }), _jsxs(Box, { height: "300px", maxWidth: "380px", children: [_jsx(ReactECharts, { option: ECHART_MOCK_1 }), ";"] }), _jsxs(Text, { as: "p", sx: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx(Link, { children: "Link to somewhere" }), _jsxs(Link, { children: ["Second link", _jsx(LinkIcon, {})] })] })] }), _jsxs(Box, { padding: 4, children: [_jsx(Text, { as: "h3", children: "Notebook name abc" }), _jsx(Text, { sx: { color: 'fg.subtle' }, children: "Subtitle comes here" }), _jsxs(Box, { height: "300px", maxWidth: "380px", children: [_jsx(ReactECharts, { option: ECHART_MOCK_3 }), ";"] }), _jsxs(Text, { as: "p", sx: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx(Link, { children: "Link to somewhere" }), _jsxs(Link, { children: ["Second link", _jsx(LinkIcon, {})] })] })] }), _jsxs(Box, { padding: 4, children: [_jsx(Text, { as: "h3", children: "Notebook name abc" }), _jsx(Text, { sx: { color: 'fg.subtle' }, children: "Subtitle comes here" }), _jsxs(Box, { height: "300px", maxWidth: "380px", children: [_jsx(ReactECharts, { option: ECHART_MOCK_2 }), ";"] }), _jsxs(Text, { as: "p", sx: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx(Link, { children: "Link to somewhere" }), _jsxs(Link, { children: ["Second link", _jsx(LinkIcon, {})] })] })] })] })] })] })] }));
|
|
117
51
|
};
|
|
118
52
|
export default DashboardMock;
|
|
@@ -4,7 +4,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
6
|
import { useState } from 'react';
|
|
7
|
-
import { Box
|
|
7
|
+
import { Box } from '@datalayer/primer-addons';
|
|
8
|
+
import { FormControl, TextInputWithTokens, Autocomplete, Select, Textarea, Heading, } from '@primer/react';
|
|
8
9
|
export const FormMock = (props) => {
|
|
9
10
|
const { title } = props;
|
|
10
11
|
const [tokens, setTokens] = useState([
|
|
@@ -15,7 +16,7 @@ export const FormMock = (props) => {
|
|
|
15
16
|
const onTokenRemove = tokenId => {
|
|
16
17
|
setTokens(tokens.filter(token => token.id !== tokenId));
|
|
17
18
|
};
|
|
18
|
-
return (_jsxs(Box, { display: "grid",
|
|
19
|
+
return (_jsxs(Box, { display: "grid", gap: 3, children: [_jsx(Heading, { children: title }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "TextInputWithTokens" }), _jsx(TextInputWithTokens, { onTokenRemove: onTokenRemove, tokens: tokens })] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Autocomplete" }), _jsxs(Autocomplete, { children: [_jsx(Autocomplete.Input, { block: true }), _jsx(Autocomplete.Overlay, { children: _jsx(Autocomplete.Menu, { items: [
|
|
19
20
|
{ text: 'css', id: '0' },
|
|
20
21
|
{ text: 'css-in-js', id: '1' },
|
|
21
22
|
{ text: 'styled-system', id: '2' },
|
|
@@ -3,7 +3,8 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
|
-
import { Box
|
|
6
|
+
import { Box } from '@datalayer/primer-addons';
|
|
7
|
+
import { LabelGroup, ActionMenu, ActionList, IconButton, Label, RelativeTime, } from '@primer/react';
|
|
7
8
|
import { Table, DataTable } from '@primer/react/experimental';
|
|
8
9
|
import { KebabHorizontalIcon, DownloadIcon } from '@primer/octicons-react';
|
|
9
10
|
import { VisuallyHidden } from './../../components/display/index.js';
|
|
@@ -101,7 +102,7 @@ function uppercase(input) {
|
|
|
101
102
|
}
|
|
102
103
|
export const TableMock = (props) => {
|
|
103
104
|
const { title } = props;
|
|
104
|
-
return (_jsx(Box, { display: "grid",
|
|
105
|
+
return (_jsx(Box, { display: "grid", gap: 3, children: _jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h2", id: "repositories", children: title }), _jsx(Table.Subtitle, { as: "p", id: "repositories-subtitle", children: "A subtitle could appear here to give extra context to the data." }), _jsx(DataTable, { "aria-labelledby": "repositories", "aria-describedby": "repositories-subtitle", data: data, columns: [
|
|
105
106
|
{
|
|
106
107
|
header: 'Repository',
|
|
107
108
|
field: 'name',
|
|
@@ -3,7 +3,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
|
-
import { Box
|
|
6
|
+
import { Box } from '@datalayer/primer-addons';
|
|
7
|
+
import { PageHeader, Flash, PageLayout } from '@primer/react';
|
|
7
8
|
import { ConstructionIcon } from '@datalayer/icons-react';
|
|
8
9
|
export const WipMock = (props) => {
|
|
9
10
|
const { title } = props;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** The signed-in person, as a shell needs one. */
|
|
2
|
+
export type Person = {
|
|
3
|
+
uid: string;
|
|
4
|
+
handle: string;
|
|
5
|
+
displayName: string;
|
|
6
|
+
avatarIcon?: string;
|
|
7
|
+
};
|
|
8
|
+
/** The person in IAM's `GET /api/iam/v1/me` answer (`me`); undefined without a uid and a handle. */
|
|
9
|
+
export declare function personOf(raw: unknown): Person | undefined;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/** The person in IAM's `GET /api/iam/v1/me` answer (`me`); undefined without a uid and a handle. */
|
|
6
|
+
export function personOf(raw) {
|
|
7
|
+
if (!raw || typeof raw !== 'object') {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
const user = raw;
|
|
11
|
+
const handle = typeof user.handle_s === 'string' ? user.handle_s : '';
|
|
12
|
+
const uid = typeof user.uid === 'string' ? user.uid : '';
|
|
13
|
+
if (!handle || !uid) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
const names = [user.first_name_t, user.last_name_t].filter((part) => typeof part === 'string' && part.trim() !== '');
|
|
17
|
+
return {
|
|
18
|
+
uid,
|
|
19
|
+
handle,
|
|
20
|
+
displayName: names.length ? names.join(' ') : handle,
|
|
21
|
+
avatarIcon: typeof user.avatar_icon_s === 'string' ? user.avatar_icon_s : undefined,
|
|
22
|
+
};
|
|
23
|
+
}
|
package/lib/otel/index.d.ts
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
*/
|
|
14
14
|
export type { OtelSpan, OtelLog, OtelMetric, OtelSpanEvent, OtelSpanLink, SignalType, OtelLiveProps, OtelTracesListProps, OtelSpanDetailProps, OtelTimelineProps, OtelLogsListProps, OtelMetricsListProps, OtelSpanTreeProps, OtelSearchBarProps, OtelTimelineRangeSliderProps, OtelQueryRow, OtelQueryResult, } from './types';
|
|
15
15
|
export { toMs, formatDuration, formatTime, serviceColor, kindColor, severityColor, severityVariant, buildSpanTree, flattenSpanTree, } from './utils';
|
|
16
|
+
export { createOtelLiveTracer, traceparentOf, PEER_SERVICE, spanConcerns, spansOfService, useOtelLiveSpans, useOtelLiveTracer, } from './live';
|
|
17
|
+
export type { OtelAttributeValue, OtelAttributes, OtelLiveExport, OtelLiveSpan, OtelLiveTracer, OtelLiveTracerOptions, OtelSpanContext, OtelSpanKindName, OtelStartSpanOptions, } from './live';
|
|
16
18
|
export { resolveOtelAuth, resolveOtelUserUid, buildOtelWebSocketUrl, } from './auth';
|
|
17
19
|
export type { ResolvedOtelAuth } from './auth';
|
|
18
20
|
export { useOtelTraces, useOtelTrace, useOtelLogs, useOtelMetrics, useOtelServices, useOtelStats, useOtelQuery, useOtelSystem, useOtelWebSocket, setOtelOnUnauthorized, } from './hooks';
|
|
@@ -29,6 +31,8 @@ export { OtelMetricsList } from './views';
|
|
|
29
31
|
export { OtelMetricsChart } from './views';
|
|
30
32
|
export type { OtelMetricsChartProps } from './views';
|
|
31
33
|
export { OtelTimeline } from './views';
|
|
34
|
+
export { OtelLiveSpans, DEFAULT_SPAN_FACETS, filterSpansByFacets, unfoldedValue, } from './views';
|
|
35
|
+
export type { OtelLiveSpansProps, OtelSpanFacet } from './views';
|
|
32
36
|
export { OtelTimelineRangeSlider } from './views';
|
|
33
37
|
export { OtelSqlView } from './views';
|
|
34
38
|
export type { OtelSqlViewProps } from './views';
|
package/lib/otel/index.js
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
// ── Utils ─────────────────────────────────────────────────────────────────────
|
|
6
6
|
export { toMs, formatDuration, formatTime, serviceColor, kindColor, severityColor, severityVariant, buildSpanTree, flattenSpanTree, } from './utils.js';
|
|
7
|
+
// ── In the page ───────────────────────────────────────────────────────────────
|
|
8
|
+
export { createOtelLiveTracer, traceparentOf, PEER_SERVICE, spanConcerns, spansOfService, useOtelLiveSpans, useOtelLiveTracer, } from './live/index.js';
|
|
7
9
|
// ── Auth helpers ──────────────────────────────────────────────────────────────
|
|
8
10
|
export { resolveOtelAuth, resolveOtelUserUid, buildOtelWebSocketUrl, } from './auth.js';
|
|
9
11
|
// ── Hooks ─────────────────────────────────────────────────────────────────────
|
|
@@ -20,6 +22,7 @@ export { OtelSearchBar } from './views/index.js';
|
|
|
20
22
|
export { OtelMetricsList } from './views/index.js';
|
|
21
23
|
export { OtelMetricsChart } from './views/index.js';
|
|
22
24
|
export { OtelTimeline } from './views/index.js';
|
|
25
|
+
export { OtelLiveSpans, DEFAULT_SPAN_FACETS, filterSpansByFacets, unfoldedValue, } from './views/index.js';
|
|
23
26
|
export { OtelTimelineRangeSlider } from './views/index.js';
|
|
24
27
|
export { OtelSqlView } from './views/index.js';
|
|
25
28
|
export { OtelSystemView } from './views/index.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which spans concern a service: those it did, and those done toward it — a
|
|
3
|
+
* client span whose `peer.service` names it (the OpenTelemetry attribute for
|
|
4
|
+
* the remote service a call goes to). One message between two services shows
|
|
5
|
+
* in both: sent in one, received in the other.
|
|
6
|
+
*
|
|
7
|
+
* @module otel/live/filter
|
|
8
|
+
*/
|
|
9
|
+
import type { OtelSpan } from '../types';
|
|
10
|
+
/** The OpenTelemetry attribute naming the service a call goes to. */
|
|
11
|
+
export declare const PEER_SERVICE = "peer.service";
|
|
12
|
+
/** Whether a span concerns a service: done by it, or toward it. */
|
|
13
|
+
export declare function spanConcerns(span: OtelSpan, service: string): boolean;
|
|
14
|
+
/** The spans that concern a service; every span without one. */
|
|
15
|
+
export declare function spansOfService(spans: readonly OtelSpan[], service: string | undefined): OtelSpan[];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/** The OpenTelemetry attribute naming the service a call goes to. */
|
|
6
|
+
export const PEER_SERVICE = 'peer.service';
|
|
7
|
+
/** Whether a span concerns a service: done by it, or toward it. */
|
|
8
|
+
export function spanConcerns(span, service) {
|
|
9
|
+
return (span.service_name === service || span.attributes?.[PEER_SERVICE] === service);
|
|
10
|
+
}
|
|
11
|
+
/** The spans that concern a service; every span without one. */
|
|
12
|
+
export function spansOfService(spans, service) {
|
|
13
|
+
return service
|
|
14
|
+
? spans.filter(span => spanConcerns(span, service))
|
|
15
|
+
: [...spans];
|
|
16
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenTelemetry in the page: a tracer whose spans the OTEL views draw as
|
|
3
|
+
* they happen, and which of them concern a service. Light: no view, no
|
|
4
|
+
* client, nothing sent.
|
|
5
|
+
*
|
|
6
|
+
* @module otel/live
|
|
7
|
+
*/
|
|
8
|
+
export { createOtelLiveTracer, traceparentOf, type OtelAttributeValue, type OtelAttributes, type OtelLiveExport, type OtelLiveSpan, type OtelLiveTracer, type OtelLiveTracerOptions, type OtelSpanContext, type OtelSpanKindName, type OtelStartSpanOptions, } from './tracer';
|
|
9
|
+
export { PEER_SERVICE, spanConcerns, spansOfService } from './filter';
|
|
10
|
+
export { useOtelLiveSpans, useOtelLiveTracer } from './useOtelLiveSpans';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* OpenTelemetry in the page: a tracer whose spans the OTEL views draw as
|
|
7
|
+
* they happen, and which of them concern a service. Light: no view, no
|
|
8
|
+
* client, nothing sent.
|
|
9
|
+
*
|
|
10
|
+
* @module otel/live
|
|
11
|
+
*/
|
|
12
|
+
export { createOtelLiveTracer, traceparentOf, } from './tracer.js';
|
|
13
|
+
export { PEER_SERVICE, spanConcerns, spansOfService } from './filter.js';
|
|
14
|
+
export { useOtelLiveSpans, useOtelLiveTracer } from './useOtelLiveSpans.js';
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tracer that lives in the page: spans started and ended in the browser,
|
|
3
|
+
* kept as the OTEL views draw them (`OtelSpan`), as they happen — a span is
|
|
4
|
+
* there from its start (`in_progress`), its events added as they come, its
|
|
5
|
+
* end and status when it ends.
|
|
6
|
+
*
|
|
7
|
+
* What it records is OpenTelemetry: W3C trace and span ids, a span kind, a
|
|
8
|
+
* status, attributes of primitive values (structured values as JSON text, as
|
|
9
|
+
* the GenAI semantic conventions carry arguments and results), events, and an
|
|
10
|
+
* `exception` event for an error. Nothing is sent anywhere: the record is the
|
|
11
|
+
* page's, read by `useOtelLiveSpans` and drawn by `OtelLiveSpans`.
|
|
12
|
+
*
|
|
13
|
+
* A span started without a parent continues the innermost span still open
|
|
14
|
+
* of the same service — what one agent of the page is doing — so a tool call
|
|
15
|
+
* nests under its turn without the caller carrying a context; `parent: null`
|
|
16
|
+
* starts a trace of its own.
|
|
17
|
+
*
|
|
18
|
+
* @module otel/live/tracer
|
|
19
|
+
*/
|
|
20
|
+
import type { OtelSpan, OtelSpanLink } from '../types';
|
|
21
|
+
/** What identifies a span: its trace and itself. */
|
|
22
|
+
export interface OtelSpanContext {
|
|
23
|
+
trace_id: string;
|
|
24
|
+
span_id: string;
|
|
25
|
+
}
|
|
26
|
+
/** An attribute's value, as OpenTelemetry allows it. */
|
|
27
|
+
export type OtelAttributeValue = string | number | boolean | readonly string[] | readonly number[] | readonly boolean[];
|
|
28
|
+
/** Attributes; an `undefined` value is left out. */
|
|
29
|
+
export type OtelAttributes = Record<string, OtelAttributeValue | undefined>;
|
|
30
|
+
/** A span's kind, as the OTEL views name it. */
|
|
31
|
+
export type OtelSpanKindName = 'INTERNAL' | 'SERVER' | 'CLIENT' | 'PRODUCER' | 'CONSUMER';
|
|
32
|
+
export interface OtelStartSpanOptions {
|
|
33
|
+
/** The service that does it: the tracer's own unless said. */
|
|
34
|
+
serviceName?: string;
|
|
35
|
+
kind?: OtelSpanKindName;
|
|
36
|
+
attributes?: OtelAttributes;
|
|
37
|
+
/**
|
|
38
|
+
* The span it is part of. Left out: the innermost span still open of the
|
|
39
|
+
* same service; `null`: a trace of its own.
|
|
40
|
+
*/
|
|
41
|
+
parent?: OtelSpanContext | null;
|
|
42
|
+
/** When it started, in ms since the epoch: now unless said. */
|
|
43
|
+
startTime?: number;
|
|
44
|
+
/** The instrumentation scope: the tracer's own unless said. */
|
|
45
|
+
scopeName?: string;
|
|
46
|
+
links?: OtelSpanLink[];
|
|
47
|
+
}
|
|
48
|
+
/** A span being recorded. */
|
|
49
|
+
export interface OtelLiveSpan {
|
|
50
|
+
readonly context: OtelSpanContext;
|
|
51
|
+
/** Whether it has ended. */
|
|
52
|
+
readonly ended: boolean;
|
|
53
|
+
setAttribute(key: string, value: OtelAttributeValue | undefined): void;
|
|
54
|
+
setAttributes(attributes: OtelAttributes): void;
|
|
55
|
+
addEvent(name: string, attributes?: OtelAttributes, time?: number): void;
|
|
56
|
+
setStatus(code: 'OK' | 'ERROR', message?: string): void;
|
|
57
|
+
/** An `exception` event, and the status `ERROR`. */
|
|
58
|
+
recordException(error: unknown, time?: number): void;
|
|
59
|
+
updateName(name: string): void;
|
|
60
|
+
/** End it; a second end is ignored. */
|
|
61
|
+
end(time?: number): void;
|
|
62
|
+
}
|
|
63
|
+
/** The record, saved. */
|
|
64
|
+
export interface OtelLiveExport {
|
|
65
|
+
exportedAt: string;
|
|
66
|
+
spans: OtelSpan[];
|
|
67
|
+
}
|
|
68
|
+
export interface OtelLiveTracer {
|
|
69
|
+
/** The service a span is done by unless it says. */
|
|
70
|
+
readonly serviceName: string;
|
|
71
|
+
startSpan(name: string, options?: OtelStartSpanOptions): OtelLiveSpan;
|
|
72
|
+
/** The innermost span still open of a service (the tracer's own unless said). */
|
|
73
|
+
activeSpan(serviceName?: string): OtelSpanContext | undefined;
|
|
74
|
+
/** The spans, oldest first: a new array each time one changes. */
|
|
75
|
+
spans(): readonly OtelSpan[];
|
|
76
|
+
subscribe(listener: () => void): () => void;
|
|
77
|
+
/** Forget every span; those still open are recorded no more. */
|
|
78
|
+
clear(): void;
|
|
79
|
+
exportSpans(): OtelLiveExport;
|
|
80
|
+
}
|
|
81
|
+
export interface OtelLiveTracerOptions {
|
|
82
|
+
serviceName?: string;
|
|
83
|
+
scopeName?: string;
|
|
84
|
+
/** The clock: `Date.now` unless a test sets it. */
|
|
85
|
+
now?: () => number;
|
|
86
|
+
/** The most spans kept: the oldest ended ones go first. Default 2000. */
|
|
87
|
+
limit?: number;
|
|
88
|
+
/** Random bytes as hex, for ids: `crypto.getRandomValues` unless a test sets it. */
|
|
89
|
+
randomHex?: (bytes: number) => string;
|
|
90
|
+
}
|
|
91
|
+
/** A W3C `traceparent` header for a span: `00-<trace>-<span>-01`. */
|
|
92
|
+
export declare function traceparentOf(context: OtelSpanContext): string;
|
|
93
|
+
/** Make a tracer for the page. */
|
|
94
|
+
export declare function createOtelLiveTracer(options?: OtelLiveTracerOptions): OtelLiveTracer;
|