Skip to content

Commit b9eccec

Browse files
feat(Sky): Add OTEL + PostHog telemetry bridges and streamline workbench loading
Implement build-baked telemetry for debug builds: - Add OTELBridge.ts: PerformanceObserver capturing all `land:*` marks → OTLP/HTTP - Add PostHogBridge.ts: Error tracking and analytics via CDN (tree-shaken in prod) - Add TelemetryBridge.astro: Shared component loading both bridges for all workbenches Refactor workbench loading to use performance.mark() instead of console.log: - Browser.astro, BrowserTest.astro, Electron/Layout.astro, Mountain.astro - Consistent `land:{workbench}:{stage}:{start|done|error}` naming - Enables OTELBridge to capture complete boot sequence timing Update Wind preload import paths: - `@codeeditorland/wind/Target/Function/Install` → `@codeeditorland/wind/Target/Function/Install/Function/Install` Enhance astro.config.ts build: - Step 13: Copy built-in VS Code extensions from .build/extensions/ - PostHog build telemetry: sends step timings to analytics on build complete - Vite proxy: OTLP /v1/traces → localhost:4318 for Jaeger/OTEL collector BREAKING CHANGE: Wind preload import path changed; ensure Wind is rebuilt.
1 parent 35dd98e commit b9eccec

16 files changed

Lines changed: 507 additions & 582 deletions

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ The UI Component Layer for `Land` 🏞️.
3838

3939
Welcome to **Sky** 🌌, the declarative **UI component layer** of the
4040
**Land** 🏞️ Code Editor. Built with the **`Astro`** framework, `Sky` renders
41-
the user interface editor, side bar, activity bar, status bar, and panels. It
41+
the user interface - editor, side bar, activity bar, status bar, and panels. It
4242
operates within the **`Tauri`** webview alongside `Wind`, consuming state and
4343
services from the `Wind` service layer to display and manage the editor's visual
4444
presentation.
@@ -74,7 +74,7 @@ presentation.
7474
through environment-based selection:
7575
- **A1 (Browser/BrowserProxy):** Browser-based workbench with optional service
7676
proxy.
77-
- **A2 (Mountain RECOMMENDED):** Browser workbench with Mountain-backed
77+
- **A2 (Mountain - RECOMMENDED):** Browser workbench with Mountain-backed
7878
providers.
7979
- **A3 (Electron):** Electron workbench with polyfills for `VS Code`.
8080
- **Component Modularity:** Organized into Pages (routes), Workbenches
@@ -147,26 +147,26 @@ graph LR
147147
classDef mountain fill:#f0d0ff,stroke:#9b59b6,stroke-width:2px,color:#2c0050;
148148
classDef external fill:#ebebeb,stroke:#888,stroke-dasharray:5 5,color:#333;
149149
150-
subgraph "🌌 Sky UI Component Layer (Tauri Webview)"
151-
Pages["Pages index, Browser, Electron, Mountain, Isolation"]:::sky
152-
Workbenches["Workbench Components Browser, Mountain, Default, NLS"]:::sky
153-
WorkbenchImpl["Workbench Implementations BrowserProxy/, Electron/"]:::sky
150+
subgraph "🌌 Sky - UI Component Layer (Tauri Webview)"
151+
Pages["Pages - index, Browser, Electron, Mountain, Isolation"]:::sky
152+
Workbenches["Workbench Components - Browser, Mountain, Default, NLS"]:::sky
153+
WorkbenchImpl["Workbench Implementations - BrowserProxy/, Electron/"]:::sky
154154
end
155155
156-
subgraph "🍃 Wind Service Layer (Tauri Webview)"
157-
PreloadJS["Preload.js Environment Shim"]:::wind
156+
subgraph "🍃 Wind - Service Layer (Tauri Webview)"
157+
PreloadJS["Preload.js - Environment Shim"]:::wind
158158
WindServices["Wind Effect-TS Services"]:::wind
159159
TauriIntegrations["Wind/Tauri Integrations"]:::wind
160160
end
161161
162-
subgraph "📱 Tauri Shell & Mountain Rust Backend"
162+
subgraph "📱 Tauri Shell & Mountain - Rust Backend"
163163
TauriWindow["Tauri Window API"]:::tauri
164164
TauriEvents["Tauri Event System"]:::tauri
165-
MountainCore["⛰️ Mountain Rust Core"]:::mountain
165+
MountainCore["⛰️ Mountain - Rust Core"]:::mountain
166166
end
167167
168168
subgraph "📦 External"
169-
VSCodeComponents["VS Code Core UI @codeeditorland/output"]:::external
169+
VSCodeComponents["VS Code Core UI - @codeeditorland/output"]:::external
170170
end
171171
172172
Pages --> Workbenches

Source/Function/Markup/Base.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import Meta from "../Meta.astro";
2828
// (resolves against http://localhost URL) instead of
2929
// vscode-file:// URLs that WKWebView can't import().
3030
globalThis._VSCODE_USE_RELATIVE_IMPORTS = true;
31-
// esbuild __name helper required by Dependency/out/ files loaded in
31+
// esbuild __name helper - required by Dependency/out/ files loaded in
3232
// extension host worker contexts that don't have their own __name definition.
3333
if (typeof globalThis.__name === "undefined") {
3434
Object.defineProperty(globalThis, "__name", {

Source/Function/SkyBridge.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ function GetOrCreateChannel(Id: string, Name?: string): string[] {
6161
// Announce channel creation to VS Code workbench output panel
6262
const Wb = GetWorkbench();
6363
if (Wb && Name) {
64-
// Use logger as a lightweight sink a real IOutputService integration
64+
// Use logger as a lightweight sink - a real IOutputService integration
6565
// requires AMD require('vs/workbench/services/output/common/output')
6666
Wb.commands
6767
.executeCommand("workbench.action.output.show")

Source/Workbench/Browser.astro

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
---
22
import NLS from "./NLS.astro";
3+
import TelemetryBridge from "./TelemetryBridge.astro";
34
---
45

56
<Fragment>
67
<NLS />
8+
<TelemetryBridge />
79

8-
<!-- VS Code Browser Workbench — loaded via inline script to bypass Vite bundling.
9-
/vs/ is served from Sky/Public/vs → Output/Target/Microsoft/VSCode/vs (symlink).
10-
Relative imports inside workbench.js (../../../base/...) resolve against /vs/. -->
1110
<script is:inline type="module">
1211
try {
12+
performance.mark("land:browser:workbench:start");
1313
await import("/vs/code/browser/workbench/workbench.js");
14-
} catch (error) {
15-
console.error(
16-
"[Browser] Failed to load VS Code browser workbench:",
17-
error,
18-
);
14+
performance.mark("land:browser:workbench:loaded");
15+
} catch {
16+
performance.mark("land:browser:workbench:error");
1917
}
2018
</script>
2119
</Fragment>

Source/Workbench/BrowserProxy/Layout.astro

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424
import { Astro } from "astro:global";
2525
2626
import NLS from "../NLS.astro";
27+
import TelemetryBridge from "../TelemetryBridge.astro";
2728
---
2829

2930
<Fragment>
3031
<NLS />
32+
<TelemetryBridge />
3133

3234
<!-- Wind Preload Script - Required for VSCode workbench -->
3335
<script type="module">
Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,14 @@
11
/**
2-
* browser-proxy-wind-preload.ts - Wind preload installation script for Browser Proxy
3-
*
4-
* This script installs the Wind preload polyfill which provides VSCode-compatible
5-
* globals (window.vscode, window.preloadGlobals) for the browser workbench.
2+
* Wind preload for BrowserProxy workbench (A1).
3+
* Zero console.* output. Tracing via performance.mark().
64
*/
75

8-
import Install from "@codeeditorland/wind/Target/Function/Install";
6+
import Install from "@codeeditorland/wind/Target/Function/Install/Function/Install";
97

10-
// Install the Wind preload polyfill (window.vscode globals)
11-
Install()
12-
.then(() => {
13-
14-
// Verify preloadGlobals is available
15-
if (window.preloadGlobals && window.preloadGlobals.process) {
16-
const process = window.preloadGlobals.process;
17-
} else {
18-
}
19-
20-
// Verify window.vscode is available
21-
if (window.vscode) {
22-
} else {
23-
}
24-
25-
// Verify Wind preload ready flag
26-
if (window.__WIND_PRELOAD_READY__) {
27-
} else {
28-
}
29-
})
30-
.catch((error: unknown) => {
31-
});
8+
try {
9+
performance.mark("land:browserproxy:preload:start");
10+
await Install();
11+
performance.mark("land:browserproxy:preload:done");
12+
} catch {
13+
performance.mark("land:browserproxy:preload:error");
14+
}

Source/Workbench/BrowserProxy/Workbench.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ interface MountainProxyWindow extends Window {
1010
}
1111

1212
try {
13-
// Variable URL: Rollup only analyzes string literals an identifier
13+
// Variable URL: Rollup only analyzes string literals - an identifier
1414
// reference is treated as truly dynamic and never resolved at build time.
1515
const WorkbenchUrl = "/vs/code/browser/workbench/workbench.js";
1616
await import(WorkbenchUrl);

Source/Workbench/BrowserTest.astro

Lines changed: 16 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,37 @@
11
---
22
/**
33
* BrowserTest.astro - Browser VSCode Workbench Test Page
4-
*
5-
* This page tests the browser-compatible VSCode workbench in the Tauri environment.
6-
* It's a diagnostic tool to verify if the browser workbench can load without
7-
* the vscode-file:// CSP error that the Electron workbench causes.
8-
*
9-
* Key differences from Default.astro:
10-
* - Uses browser workbench (vs/code/browser/workbench/workbench.js)
11-
* - Not Electron workbench (vs/code/electron-browser/workbench/workbench.js)
12-
*
13-
* Expected outcome:
14-
* - Browser workbench should load without vscode-file:// CSP errors
15-
* - Identifies what additional setup is needed (providers, IPC handlers, etc.)
16-
* - Informs whether to proceed with Approach A2 (browser workbench + Mountain providers)
4+
* Diagnostic: tests browser workbench in Tauri without Electron polyfills.
175
*/
186
197
import NLS from "./NLS.astro";
8+
import TelemetryBridge from "./TelemetryBridge.astro";
209
---
2110

2211
<Fragment>
2312
<NLS />
13+
<TelemetryBridge />
2414

25-
<!-- Wind Preload Script - Required for VSCode workbench -->
2615
<script type="module">
27-
import Install from "@codeeditorland/wind/Target/Function/Install";
28-
29-
console.log(
30-
"[BrowserTest] ===== Starting Wind preload installation =====",
31-
);
32-
33-
// Install the Wind preload polyfill (window.vscode globals)
34-
// This must run before VSCode workbench.js which expects window.vscode
35-
Install()
36-
.then(() => {
37-
console.log(
38-
"[BrowserTest] ✓ Wind preload installed successfully",
39-
);
40-
41-
// Verify preloadGlobals is available
42-
if (window.preloadGlobals && window.preloadGlobals.process) {
43-
console.log(
44-
"[BrowserTest] ✓ preloadGlobals.process is available",
45-
);
46-
} else {
47-
console.warn(
48-
"[BrowserTest] ⚠ preloadGlobals.process not available",
49-
);
50-
}
51-
52-
// Verify window.vscode is available
53-
if (window.vscode) {
54-
console.log("[BrowserTest] ✓ window.vscode is available");
55-
console.log(
56-
"[BrowserTest] ✓ Window.vscode methods:",
57-
Object.keys(window.vscode || {}),
58-
);
59-
} else {
60-
console.error(
61-
"[BrowserTest] ✗ window.vscode not available",
62-
);
63-
}
64-
65-
console.log(
66-
"[BrowserTest] ===== Wind preload installation complete =====",
67-
);
68-
})
69-
.catch(
70-
/** @param {any} _error */ (_error) => {
71-
console.error("[BrowserTest] ✗ Wind preload install error");
72-
},
16+
performance.mark("land:browsertest:preload:start");
17+
try {
18+
const { default: Install } = await import(
19+
"@codeeditorland/wind/Target/Function/Install/Function/Install"
7320
);
21+
await Install();
22+
performance.mark("land:browsertest:preload:done");
23+
} catch {
24+
performance.mark("land:browsertest:preload:error");
25+
}
7426
</script>
7527

76-
<!-- Browser Workbench Script — is:inline bypasses Vite bundling entirely -->
7728
<script is:inline type="module">
7829
try {
30+
performance.mark("land:browsertest:workbench:start");
7931
await import("/vs/code/browser/workbench/workbench.js");
80-
console.log(
81-
"[BrowserTest] ===== Loading browser VSCode workbench =====",
82-
);
83-
console.log(
84-
"[BrowserTest] ✓ Browser workbench script loaded successfully",
85-
);
86-
} catch (error) {
87-
console.error(
88-
"[BrowserTest] Failed to load VS Code browser workbench:",
89-
error,
90-
);
32+
performance.mark("land:browsertest:workbench:loaded");
33+
} catch {
34+
performance.mark("land:browsertest:workbench:error");
9135
}
92-
console.log("[BrowserTest] ===== Workbench load attempted =====");
9336
</script>
9437
</Fragment>

Source/Workbench/Electron/Layout.astro

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,35 @@
33
* Electron Workbench Layout (Approach A3)
44
*
55
* Scripts must load sequentially:
6-
* 1. Wind Preload (Install) sets window.vscode, process globals
7-
* 2. Polyfills augments process/fs/ipc (depends on #1)
8-
* 3. Bootstrap Effect-TS service init (depends on #1)
9-
* 4. Workbench loads electron-browser/workbench.js (depends on #1-3)
6+
* 1. Wind Preload (Install) - sets window.vscode, process globals
7+
* 2. Polyfills - augments process/fs/ipc (depends on #1)
8+
* 3. Bootstrap - Effect-TS service init (depends on #1)
9+
* 4. Workbench - loads electron-browser/workbench.js (depends on #1-3)
1010
*
1111
* All four are chained in a single <script type="module"> so that
1212
* each `await import()` completes before the next begins.
1313
*/
1414
1515
import NLS from "../NLS.astro";
16+
import TelemetryBridge from "../TelemetryBridge.astro";
1617
---
1718

1819
<Fragment>
1920
<NLS />
21+
<TelemetryBridge />
2022

2123
<!-- Sequential: Preload → Polyfills → Bootstrap → Workbench -->
2224
<script type="module">
23-
// 0. OTEL Bridge — PerformanceObserver for land:* marks → OTLP/HTTP
24-
// Build-baked: included in dev, tree-shaken in prod.
25-
// Catches all marks (buffered:true) including those from steps 1-4.
26-
import "./OTELBridge.js";
27-
28-
// 1. Wind Preload — must complete first (sets window.vscode)
25+
// 1. Wind Preload - must complete first (sets window.vscode)
2926
await import("./WindPreload.js");
3027

31-
// 2. Electron API Polyfills depends on Wind process globals
28+
// 2. Electron API Polyfills - depends on Wind process globals
3229
await import("./Polyfills.js");
3330

34-
// 3. Wind Effect-TS Bootstrap depends on preload
31+
// 3. Wind Effect-TS Bootstrap - depends on preload
3532
await import("./Bootstrap.js");
3633

37-
// 4. Electron Workbench depends on everything above
34+
// 4. Electron Workbench - depends on everything above
3835
await import("./Workbench.js");
3936
</script>
4037
</Fragment>

0 commit comments

Comments
 (0)