@@ -6,10 +6,12 @@ import {
66import { VMTier } from "./VMTier" ;
77import { API } from "./API" ;
88import { SandboxClient } from "./SandboxClient" ;
9- import { StartSandboxOpts } from "./types" ;
109import { retryWithDelay } from "./utils/api" ;
10+ import { Tracer , SpanStatusCode } from "@opentelemetry/api" ;
1111
1212export class Sandbox {
13+ private tracer ?: Tracer ;
14+
1315 /**
1416 * How the Sandbox booted up:
1517 * - RUNNING: Already running
@@ -41,36 +43,93 @@ export class Sandbox {
4143 constructor (
4244 public id : string ,
4345 private api : API ,
44- private pitcherManagerResponse : PitcherManagerResponse
45- ) { }
46+ private pitcherManagerResponse : PitcherManagerResponse ,
47+ tracer ?: Tracer
48+ ) {
49+ this . tracer = tracer ;
50+ }
51+
52+ private async withSpan < T > (
53+ operationName : string ,
54+ attributes : Record < string , string | number | boolean > = { } ,
55+ operation : ( ) => Promise < T >
56+ ) : Promise < T > {
57+ if ( ! this . tracer ) {
58+ return operation ( ) ;
59+ }
60+
61+ return this . tracer . startActiveSpan (
62+ operationName ,
63+ { attributes } ,
64+ async ( span ) => {
65+ try {
66+ const result = await operation ( ) ;
67+ span . setStatus ( { code : SpanStatusCode . OK } ) ;
68+ return result ;
69+ } catch ( error ) {
70+ span . setStatus ( {
71+ code : SpanStatusCode . ERROR ,
72+ message : error instanceof Error ? error . message : String ( error ) ,
73+ } ) ;
74+ span . recordException (
75+ error instanceof Error ? error : new Error ( String ( error ) )
76+ ) ;
77+ throw error ;
78+ } finally {
79+ span . end ( ) ;
80+ }
81+ }
82+ ) ;
83+ }
4684
4785 /**
4886 * Updates the specs that this sandbox runs on. It will dynamically scale the sandbox to the
4987 * new specs without a reboot. Be careful when scaling specs down, if the VM is using more memory
5088 * than it can scale down to, it can become very slow.
5189 */
5290 async updateTier ( tier : VMTier ) : Promise < void > {
53- await this . api . updateSpecs ( this . id , {
54- tier : tier . name ,
55- } ) ;
91+ return this . withSpan (
92+ "sandbox.updateTier" ,
93+ {
94+ "sandbox.id" : this . id ,
95+ "tier.name" : tier . name
96+ } ,
97+ async ( ) => {
98+ await this . api . updateSpecs ( this . id , {
99+ tier : tier . name ,
100+ } ) ;
101+ }
102+ ) ;
56103 }
57104
58105 /**
59106 * Updates the hibernation timeout for this sandbox. This is the amount of seconds the sandbox
60107 * will be kept alive without activity before it is automatically hibernated. Activity can be sessions or interactions with any endpoints exposed by the Sandbox.
61108 */
62109 async updateHibernationTimeout ( timeoutSeconds : number ) : Promise < void > {
63- await this . api . updateHibernationTimeout ( this . id , {
64- hibernation_timeout_seconds : timeoutSeconds ,
65- } ) ;
110+ return this . withSpan (
111+ "sandbox.updateHibernationTimeout" ,
112+ {
113+ "sandbox.id" : this . id ,
114+ "hibernation.timeoutSeconds" : timeoutSeconds
115+ } ,
116+ async ( ) => {
117+ await this . api . updateHibernationTimeout ( this . id , {
118+ hibernation_timeout_seconds : timeoutSeconds ,
119+ } ) ;
120+ }
121+ ) ;
66122 }
67123
68124 private async initializeCustomSession (
69125 customSession : SessionCreateOptions ,
70126 session : SandboxSession
71127 ) {
72- const client = await SandboxClient . create ( session , async ( ) =>
73- this . getSession ( await this . api . startVm ( this . id ) , customSession )
128+ const client = await SandboxClient . create (
129+ session ,
130+ async ( ) => this . getSession ( await this . api . startVm ( this . id ) , customSession ) ,
131+ undefined ,
132+ this . tracer
74133 ) ;
75134
76135 if ( customSession . env ) {
@@ -156,29 +215,42 @@ export class Sandbox {
156215 }
157216
158217 async connect ( customSession ?: SessionCreateOptions ) {
159- return await retryWithDelay (
218+ return this . withSpan (
219+ "sandbox.connect" ,
220+ {
221+ "sandbox.id" : this . id ,
222+ "session.hasCustomSession" : ! ! customSession ,
223+ "session.id" : customSession ?. id || "default"
224+ } ,
160225 async ( ) => {
161- const session = await this . getSession (
162- this . pitcherManagerResponse ,
163- customSession
164- ) ;
226+ return await retryWithDelay (
227+ async ( ) => {
228+ const session = await this . getSession (
229+ this . pitcherManagerResponse ,
230+ customSession
231+ ) ;
165232
166- let client : SandboxClient | undefined ;
233+ let client : SandboxClient | undefined ;
167234
168- // We might create a client here if git or env is configured, we can reuse that
169- if ( customSession ) {
170- client = await this . initializeCustomSession ( customSession , session ) ;
171- }
235+ // We might create a client here if git or env is configured, we can reuse that
236+ if ( customSession ) {
237+ client = await this . initializeCustomSession ( customSession , session ) ;
238+ }
172239
173- return (
174- client ||
175- SandboxClient . create ( session , async ( ) =>
176- this . getSession ( await this . api . startVm ( this . id ) , customSession )
177- )
240+ return (
241+ client ||
242+ SandboxClient . create (
243+ session ,
244+ async ( ) => this . getSession ( await this . api . startVm ( this . id ) , customSession ) ,
245+ undefined ,
246+ this . tracer
247+ )
248+ ) ;
249+ } ,
250+ 3 ,
251+ 100
178252 ) ;
179- } ,
180- 3 ,
181- 100
253+ }
182254 ) ;
183255 }
184256
@@ -192,20 +264,32 @@ export class Sandbox {
192264 async createSession (
193265 customSession ?: SessionCreateOptions
194266 ) : Promise < SandboxSession > {
195- if ( customSession ?. git || customSession ?. env ) {
196- const configureSession = await this . getSession (
197- this . pitcherManagerResponse ,
198- customSession
199- ) ;
200-
201- const client = await this . initializeCustomSession (
202- customSession ,
203- configureSession
204- ) ;
205-
206- client ?. dispose ( ) ;
207- }
267+ return this . withSpan (
268+ "sandbox.createSession" ,
269+ {
270+ "sandbox.id" : this . id ,
271+ "session.hasCustomSession" : ! ! customSession ,
272+ "session.id" : customSession ?. id || "default" ,
273+ "session.hasGit" : ! ! customSession ?. git ,
274+ "session.hasEnv" : ! ! customSession ?. env
275+ } ,
276+ async ( ) => {
277+ if ( customSession ?. git || customSession ?. env ) {
278+ const configureSession = await this . getSession (
279+ this . pitcherManagerResponse ,
280+ customSession
281+ ) ;
282+
283+ const client = await this . initializeCustomSession (
284+ customSession ,
285+ configureSession
286+ ) ;
208287
209- return this . getSession ( this . pitcherManagerResponse , customSession ) ;
288+ client ?. dispose ( ) ;
289+ }
290+
291+ return this . getSession ( this . pitcherManagerResponse , customSession ) ;
292+ }
293+ ) ;
210294 }
211295}
0 commit comments