daytona 0.140.0 → 0.141.0
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.
- checksums.yaml +4 -4
- data/lib/daytona/code_interpreter.rb +11 -1
- data/lib/daytona/computer_use.rb +85 -16
- data/lib/daytona/config.rb +10 -2
- data/lib/daytona/daytona.rb +28 -7
- data/lib/daytona/file_system.rb +15 -1
- data/lib/daytona/git.rb +14 -1
- data/lib/daytona/lsp_server.rb +12 -1
- data/lib/daytona/otel.rb +180 -0
- data/lib/daytona/process.rb +15 -1
- data/lib/daytona/sandbox.rb +24 -7
- data/lib/daytona/sdk/version.rb +1 -1
- data/lib/daytona/sdk.rb +1 -0
- data/lib/daytona/snapshot_service.rb +10 -1
- data/lib/daytona/volume_service.rb +10 -1
- metadata +63 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0c236b5ef310e5792aa5d1fcb33692ef2fda2a9c089e0ebe5dd0ee7e1a9b7a90
|
|
4
|
+
data.tar.gz: 2e0c388b5daa26e90b8eac72b578e0bcc8d5ce189b3cdfe128cb1a9d44da53e2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5e9dd352903ba61d1de768ab36c41ccfa94d0756b2cca41b11a30727d7b89a00a0add7a676d2c9fd663a364680f7f3ebeddd681c130d7a396db862d7242545e3
|
|
7
|
+
data.tar.gz: b0acf6153a896da1027e34c85e20d0433e5d741b5af700c4bd63e1a55f073e8d38fe34aafe6cf3df49a99795f8191ea1612f88d3538223f3d7aa5bd07c420325
|
|
@@ -15,6 +15,8 @@ module Daytona
|
|
|
15
15
|
# For other languages, use the `code_run` method from the `Process` interface,
|
|
16
16
|
# or execute the appropriate command directly in the sandbox terminal.
|
|
17
17
|
class CodeInterpreter
|
|
18
|
+
include Instrumentation
|
|
19
|
+
|
|
18
20
|
WEBSOCKET_TIMEOUT_CODE = 4008
|
|
19
21
|
WS_PORT = 2280
|
|
20
22
|
private_constant :WS_PORT
|
|
@@ -22,10 +24,12 @@ module Daytona
|
|
|
22
24
|
# @param sandbox_id [String]
|
|
23
25
|
# @param toolbox_api [DaytonaToolboxApiClient::InterpreterApi]
|
|
24
26
|
# @param get_preview_link [Proc]
|
|
25
|
-
|
|
27
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
28
|
+
def initialize(sandbox_id:, toolbox_api:, get_preview_link:, otel_state: nil)
|
|
26
29
|
@sandbox_id = sandbox_id
|
|
27
30
|
@toolbox_api = toolbox_api
|
|
28
31
|
@get_preview_link = get_preview_link
|
|
32
|
+
@otel_state = otel_state
|
|
29
33
|
end
|
|
30
34
|
|
|
31
35
|
# Execute Python code in the sandbox.
|
|
@@ -288,8 +292,14 @@ module Daytona
|
|
|
288
292
|
raise Sdk::Error, "Failed to delete interpreter context: #{e.message}"
|
|
289
293
|
end
|
|
290
294
|
|
|
295
|
+
instrument :run_code, :create_context, :list_contexts, :delete_context,
|
|
296
|
+
component: 'CodeInterpreter'
|
|
297
|
+
|
|
291
298
|
private
|
|
292
299
|
|
|
300
|
+
# @return [Daytona::OtelState, nil]
|
|
301
|
+
attr_reader :otel_state
|
|
302
|
+
|
|
293
303
|
# @return [Hash<String, String>]
|
|
294
304
|
def build_headers
|
|
295
305
|
headers = {}
|
data/lib/daytona/computer_use.rb
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
module Daytona
|
|
4
4
|
class ComputerUse
|
|
5
5
|
class Mouse
|
|
6
|
+
include Instrumentation
|
|
7
|
+
|
|
6
8
|
# @return [String] The ID of the sandbox
|
|
7
9
|
attr_reader :sandbox_id
|
|
8
10
|
|
|
@@ -11,9 +13,11 @@ module Daytona
|
|
|
11
13
|
|
|
12
14
|
# @param sandbox_id [String] The ID of the sandbox
|
|
13
15
|
# @param toolbox_api [DaytonaToolboxApiClient::ComputerUseApi] API client for sandbox operations
|
|
14
|
-
|
|
16
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
17
|
+
def initialize(sandbox_id:, toolbox_api:, otel_state: nil)
|
|
15
18
|
@sandbox_id = sandbox_id
|
|
16
19
|
@toolbox_api = toolbox_api
|
|
20
|
+
@otel_state = otel_state
|
|
17
21
|
end
|
|
18
22
|
|
|
19
23
|
# Gets the current mouse cursor position.
|
|
@@ -40,7 +44,7 @@ module Daytona
|
|
|
40
44
|
# @example
|
|
41
45
|
# result = sandbox.computer_use.mouse.move(x: 100, y: 200)
|
|
42
46
|
# puts "Mouse moved to: #{result.x}, #{result.y}"
|
|
43
|
-
def move(x:, y:)
|
|
47
|
+
def move(x:, y:)
|
|
44
48
|
request = DaytonaToolboxApiClient::MouseMoveRequest.new(x:, y:)
|
|
45
49
|
toolbox_api.move_mouse(request)
|
|
46
50
|
rescue StandardError => e
|
|
@@ -65,7 +69,7 @@ module Daytona
|
|
|
65
69
|
#
|
|
66
70
|
# # Right click
|
|
67
71
|
# right_click = sandbox.computer_use.mouse.click(x: 100, y: 200, button: 'right')
|
|
68
|
-
def click(x:, y:, button: 'left', double: false)
|
|
72
|
+
def click(x:, y:, button: 'left', double: false)
|
|
69
73
|
request = DaytonaToolboxApiClient::MouseClickRequest.new(x:, y:, button:, double:)
|
|
70
74
|
toolbox_api.click(request)
|
|
71
75
|
rescue StandardError => e
|
|
@@ -107,17 +111,26 @@ module Daytona
|
|
|
107
111
|
#
|
|
108
112
|
# # Scroll down
|
|
109
113
|
# scroll_down = sandbox.computer_use.mouse.scroll(x: 100, y: 200, direction: 'down', amount: 5)
|
|
110
|
-
def scroll(x:, y:, direction:, amount: 1)
|
|
114
|
+
def scroll(x:, y:, direction:, amount: 1)
|
|
111
115
|
request = DaytonaToolboxApiClient::MouseScrollRequest.new(x:, y:, direction:, amount:)
|
|
112
116
|
toolbox_api.scroll(request)
|
|
113
117
|
true
|
|
114
118
|
rescue StandardError => e
|
|
115
119
|
raise Sdk::Error, "Failed to scroll mouse: #{e.message}"
|
|
116
120
|
end
|
|
121
|
+
|
|
122
|
+
instrument :position, :move, :click, :drag, :scroll, component: 'Mouse'
|
|
123
|
+
|
|
124
|
+
private
|
|
125
|
+
|
|
126
|
+
# @return [Daytona::OtelState, nil]
|
|
127
|
+
attr_reader :otel_state
|
|
117
128
|
end
|
|
118
129
|
|
|
119
130
|
# Keyboard operations for computer use functionality.
|
|
120
131
|
class Keyboard
|
|
132
|
+
include Instrumentation
|
|
133
|
+
|
|
121
134
|
# @return [String] The ID of the sandbox
|
|
122
135
|
attr_reader :sandbox_id
|
|
123
136
|
|
|
@@ -126,9 +139,11 @@ module Daytona
|
|
|
126
139
|
|
|
127
140
|
# @param sandbox_id [String] The ID of the sandbox
|
|
128
141
|
# @param toolbox_api [DaytonaToolboxApiClient::ComputerUseApi] API client for sandbox operations
|
|
129
|
-
|
|
142
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
143
|
+
def initialize(sandbox_id:, toolbox_api:, otel_state: nil)
|
|
130
144
|
@sandbox_id = sandbox_id
|
|
131
145
|
@toolbox_api = toolbox_api
|
|
146
|
+
@otel_state = otel_state
|
|
132
147
|
end
|
|
133
148
|
|
|
134
149
|
# Types the specified text.
|
|
@@ -194,10 +209,19 @@ module Daytona
|
|
|
194
209
|
rescue StandardError => e
|
|
195
210
|
raise Sdk::Error, "Failed to press hotkey: #{e.message}"
|
|
196
211
|
end
|
|
212
|
+
|
|
213
|
+
instrument :type, :press, :hotkey, component: 'Keyboard'
|
|
214
|
+
|
|
215
|
+
private
|
|
216
|
+
|
|
217
|
+
# @return [Daytona::OtelState, nil]
|
|
218
|
+
attr_reader :otel_state
|
|
197
219
|
end
|
|
198
220
|
|
|
199
221
|
# Screenshot operations for computer use functionality.
|
|
200
222
|
class Screenshot
|
|
223
|
+
include Instrumentation
|
|
224
|
+
|
|
201
225
|
# @return [String] The ID of the sandbox
|
|
202
226
|
attr_reader :sandbox_id
|
|
203
227
|
|
|
@@ -206,9 +230,11 @@ module Daytona
|
|
|
206
230
|
|
|
207
231
|
# @param sandbox_id [String] The ID of the sandbox
|
|
208
232
|
# @param toolbox_api [DaytonaToolboxApiClient::ComputerUseApi] API client for sandbox operations
|
|
209
|
-
|
|
233
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
234
|
+
def initialize(sandbox_id:, toolbox_api:, otel_state: nil)
|
|
210
235
|
@sandbox_id = sandbox_id
|
|
211
236
|
@toolbox_api = toolbox_api
|
|
237
|
+
@otel_state = otel_state
|
|
212
238
|
end
|
|
213
239
|
|
|
214
240
|
# Takes a screenshot of the entire screen.
|
|
@@ -292,7 +318,7 @@ module Daytona
|
|
|
292
318
|
# options: ScreenshotOptions.new(format: "webp", quality: 80, show_cursor: true)
|
|
293
319
|
# )
|
|
294
320
|
# puts "Compressed size: #{screenshot.size_bytes} bytes"
|
|
295
|
-
def take_compressed_region(region:, options: nil)
|
|
321
|
+
def take_compressed_region(region:, options: nil)
|
|
296
322
|
options ||= ScreenshotOptions.new
|
|
297
323
|
toolbox_api.take_compressed_region_screenshot(
|
|
298
324
|
sandbox_id,
|
|
@@ -308,10 +334,20 @@ module Daytona
|
|
|
308
334
|
rescue StandardError => e
|
|
309
335
|
raise Sdk::Error, "Failed to take compressed region screenshot: #{e.message}"
|
|
310
336
|
end
|
|
337
|
+
|
|
338
|
+
instrument :take_full_screen, :take_region, :take_compressed, :take_compressed_region,
|
|
339
|
+
component: 'Screenshot'
|
|
340
|
+
|
|
341
|
+
private
|
|
342
|
+
|
|
343
|
+
# @return [Daytona::OtelState, nil]
|
|
344
|
+
attr_reader :otel_state
|
|
311
345
|
end
|
|
312
346
|
|
|
313
347
|
# Display operations for computer use functionality.
|
|
314
348
|
class Display
|
|
349
|
+
include Instrumentation
|
|
350
|
+
|
|
315
351
|
# @return [String] The ID of the sandbox
|
|
316
352
|
attr_reader :sandbox_id
|
|
317
353
|
|
|
@@ -320,9 +356,11 @@ module Daytona
|
|
|
320
356
|
|
|
321
357
|
# @param sandbox_id [String] The ID of the sandbox
|
|
322
358
|
# @param toolbox_api [DaytonaToolboxApiClient::ComputerUseApi] API client for sandbox operations
|
|
323
|
-
|
|
359
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
360
|
+
def initialize(sandbox_id:, toolbox_api:, otel_state: nil)
|
|
324
361
|
@sandbox_id = sandbox_id
|
|
325
362
|
@toolbox_api = toolbox_api
|
|
363
|
+
@otel_state = otel_state
|
|
326
364
|
end
|
|
327
365
|
|
|
328
366
|
# Gets information about the displays.
|
|
@@ -359,6 +397,13 @@ module Daytona
|
|
|
359
397
|
rescue StandardError => e
|
|
360
398
|
raise Sdk::Error, "Failed to get windows: #{e.message}"
|
|
361
399
|
end
|
|
400
|
+
|
|
401
|
+
instrument :info, :windows, component: 'Display'
|
|
402
|
+
|
|
403
|
+
private
|
|
404
|
+
|
|
405
|
+
# @return [Daytona::OtelState, nil]
|
|
406
|
+
attr_reader :otel_state
|
|
362
407
|
end
|
|
363
408
|
|
|
364
409
|
# Region coordinates for screenshot operations.
|
|
@@ -379,7 +424,7 @@ module Daytona
|
|
|
379
424
|
# @param y [Integer] Y coordinate of the region
|
|
380
425
|
# @param width [Integer] Width of the region
|
|
381
426
|
# @param height [Integer] Height of the region
|
|
382
|
-
def initialize(x:, y:, width:, height:)
|
|
427
|
+
def initialize(x:, y:, width:, height:)
|
|
383
428
|
@x = x
|
|
384
429
|
@y = y
|
|
385
430
|
@width = width
|
|
@@ -415,6 +460,8 @@ module Daytona
|
|
|
415
460
|
|
|
416
461
|
# Recording operations for computer use functionality.
|
|
417
462
|
class Recording
|
|
463
|
+
include Instrumentation
|
|
464
|
+
|
|
418
465
|
# @return [String] The ID of the sandbox
|
|
419
466
|
attr_reader :sandbox_id
|
|
420
467
|
|
|
@@ -423,9 +470,11 @@ module Daytona
|
|
|
423
470
|
|
|
424
471
|
# @param sandbox_id [String] The ID of the sandbox
|
|
425
472
|
# @param toolbox_api [DaytonaToolboxApiClient::ComputerUseApi] API client for sandbox operations
|
|
426
|
-
|
|
473
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
474
|
+
def initialize(sandbox_id:, toolbox_api:, otel_state: nil)
|
|
427
475
|
@sandbox_id = sandbox_id
|
|
428
476
|
@toolbox_api = toolbox_api
|
|
477
|
+
@otel_state = otel_state
|
|
429
478
|
end
|
|
430
479
|
|
|
431
480
|
# Starts a new screen recording session.
|
|
@@ -568,8 +617,17 @@ module Daytona
|
|
|
568
617
|
File.delete(local_path) if File.exist?(local_path)
|
|
569
618
|
raise Sdk::Error, "Failed to download recording: #{e.message}"
|
|
570
619
|
end
|
|
620
|
+
|
|
621
|
+
instrument :start, :stop, :list, :get, :delete, :download, component: 'Recording'
|
|
622
|
+
|
|
623
|
+
private
|
|
624
|
+
|
|
625
|
+
# @return [Daytona::OtelState, nil]
|
|
626
|
+
attr_reader :otel_state
|
|
571
627
|
end
|
|
572
628
|
|
|
629
|
+
include Instrumentation
|
|
630
|
+
|
|
573
631
|
# @return [String] The ID of the sandbox
|
|
574
632
|
attr_reader :sandbox_id
|
|
575
633
|
|
|
@@ -595,14 +653,16 @@ module Daytona
|
|
|
595
653
|
#
|
|
596
654
|
# @param sandbox_id [String] The ID of the sandbox
|
|
597
655
|
# @param toolbox_api [DaytonaApiClient::ToolboxApi] API client for sandbox operations
|
|
598
|
-
|
|
656
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
657
|
+
def initialize(sandbox_id:, toolbox_api:, otel_state: nil)
|
|
599
658
|
@sandbox_id = sandbox_id
|
|
600
659
|
@toolbox_api = toolbox_api
|
|
601
|
-
@
|
|
602
|
-
@
|
|
603
|
-
@
|
|
604
|
-
@
|
|
605
|
-
@
|
|
660
|
+
@otel_state = otel_state
|
|
661
|
+
@mouse = Mouse.new(sandbox_id:, toolbox_api:, otel_state:)
|
|
662
|
+
@keyboard = Keyboard.new(sandbox_id:, toolbox_api:, otel_state:)
|
|
663
|
+
@screenshot = Screenshot.new(sandbox_id:, toolbox_api:, otel_state:)
|
|
664
|
+
@display = Display.new(sandbox_id:, toolbox_api:, otel_state:)
|
|
665
|
+
@recording = Recording.new(sandbox_id:, toolbox_api:, otel_state:)
|
|
606
666
|
end
|
|
607
667
|
|
|
608
668
|
# Starts all computer use processes (Xvfb, xfce4, x11vnc, novnc).
|
|
@@ -706,5 +766,14 @@ module Daytona
|
|
|
706
766
|
rescue StandardError => e
|
|
707
767
|
raise Sdk::Error, "Failed to get process errors: #{e.message}"
|
|
708
768
|
end
|
|
769
|
+
|
|
770
|
+
instrument :start, :stop, :status, :get_process_status, :restart_process,
|
|
771
|
+
:get_process_logs, :get_process_errors,
|
|
772
|
+
component: 'ComputerUse'
|
|
773
|
+
|
|
774
|
+
private
|
|
775
|
+
|
|
776
|
+
# @return [Daytona::OtelState, nil]
|
|
777
|
+
attr_reader :otel_state
|
|
709
778
|
end
|
|
710
779
|
end
|
data/lib/daytona/config.rb
CHANGED
|
@@ -31,6 +31,11 @@ module Daytona
|
|
|
31
31
|
# @return [String, nil] Daytona target
|
|
32
32
|
attr_accessor :target
|
|
33
33
|
|
|
34
|
+
# Experimental configuration options
|
|
35
|
+
#
|
|
36
|
+
# @return [Hash, nil] Experimental configuration hash
|
|
37
|
+
attr_accessor :_experimental
|
|
38
|
+
|
|
34
39
|
# Initializes a new Daytona::Config object.
|
|
35
40
|
#
|
|
36
41
|
# @param api_key [String, nil] Daytona API key. Defaults to ENV['DAYTONA_API_KEY'].
|
|
@@ -38,12 +43,14 @@ module Daytona
|
|
|
38
43
|
# @param api_url [String, nil] Daytona API URL. Defaults to ENV['DAYTONA_API_URL'] or Daytona::Config::API_URL.
|
|
39
44
|
# @param organization_id [String, nil] Daytona organization ID. Defaults to ENV['DAYTONA_ORGANIZATION_ID'].
|
|
40
45
|
# @param target [String, nil] Daytona target. Defaults to ENV['DAYTONA_TARGET'].
|
|
41
|
-
|
|
46
|
+
# @param _experimental [Hash, nil] Experimental configuration options.
|
|
47
|
+
def initialize( # rubocop:disable Metrics/ParameterLists
|
|
42
48
|
api_key: nil,
|
|
43
49
|
jwt_token: nil,
|
|
44
50
|
api_url: nil,
|
|
45
51
|
organization_id: nil,
|
|
46
|
-
target: nil
|
|
52
|
+
target: nil,
|
|
53
|
+
_experimental: nil
|
|
47
54
|
)
|
|
48
55
|
# Load environment variables from .env and .env.local files
|
|
49
56
|
# Files are loaded from the current working directory (where the code is executed)
|
|
@@ -54,6 +61,7 @@ module Daytona
|
|
|
54
61
|
@api_url = api_url || ENV.fetch('DAYTONA_API_URL', API_URL)
|
|
55
62
|
@target = target || ENV.fetch('DAYTONA_TARGET', nil)
|
|
56
63
|
@organization_id = organization_id || ENV.fetch('DAYTONA_ORGANIZATION_ID', nil)
|
|
64
|
+
@_experimental = _experimental
|
|
57
65
|
end
|
|
58
66
|
|
|
59
67
|
private
|
data/lib/daytona/daytona.rb
CHANGED
|
@@ -4,7 +4,9 @@ require 'json'
|
|
|
4
4
|
require 'uri'
|
|
5
5
|
|
|
6
6
|
module Daytona
|
|
7
|
-
class Daytona
|
|
7
|
+
class Daytona
|
|
8
|
+
include Instrumentation
|
|
9
|
+
|
|
8
10
|
# @return [Daytona::Config]
|
|
9
11
|
attr_reader :config
|
|
10
12
|
|
|
@@ -27,20 +29,33 @@ module Daytona
|
|
|
27
29
|
attr_reader :snapshot
|
|
28
30
|
|
|
29
31
|
# @param config [Daytona::Config] Configuration options. Defaults to Daytona::Config.new
|
|
30
|
-
def initialize(config = Config.new)
|
|
32
|
+
def initialize(config = Config.new)
|
|
31
33
|
@config = config
|
|
32
34
|
ensure_access_token_defined
|
|
35
|
+
|
|
36
|
+
otel_enabled = config._experimental&.dig('otel_enabled') || ENV['DAYTONA_EXPERIMENTAL_OTEL_ENABLED'] == 'true'
|
|
37
|
+
@otel_state = (::Daytona.init_otel(Sdk::VERSION) if otel_enabled)
|
|
38
|
+
|
|
33
39
|
@api_client = build_api_client
|
|
34
40
|
@sandbox_api = DaytonaApiClient::SandboxApi.new(api_client)
|
|
35
41
|
@config_api = DaytonaApiClient::ConfigApi.new(api_client)
|
|
36
|
-
@volume = VolumeService.new(DaytonaApiClient::VolumesApi.new(api_client))
|
|
42
|
+
@volume = VolumeService.new(DaytonaApiClient::VolumesApi.new(api_client), otel_state:)
|
|
37
43
|
@object_storage_api = DaytonaApiClient::ObjectStorageApi.new(api_client)
|
|
38
44
|
@snapshots_api = DaytonaApiClient::SnapshotsApi.new(api_client)
|
|
39
|
-
@snapshot = SnapshotService.new(snapshots_api:, object_storage_api:, default_region_id: config.target
|
|
45
|
+
@snapshot = SnapshotService.new(snapshots_api:, object_storage_api:, default_region_id: config.target,
|
|
46
|
+
otel_state:)
|
|
40
47
|
@proxy_toolbox_url_cache = {}
|
|
41
48
|
@proxy_toolbox_url_mutex = Mutex.new
|
|
42
49
|
end
|
|
43
50
|
|
|
51
|
+
# Shuts down OTel providers, flushing any pending telemetry data.
|
|
52
|
+
#
|
|
53
|
+
# @return [void]
|
|
54
|
+
def close
|
|
55
|
+
::Daytona.shutdown_otel(@otel_state)
|
|
56
|
+
@otel_state = nil
|
|
57
|
+
end
|
|
58
|
+
|
|
44
59
|
# Creates a sandbox with the specified parameters
|
|
45
60
|
#
|
|
46
61
|
# @param params [Daytona::CreateSandboxFromSnapshotParams, Daytona::CreateSandboxFromImageParams, Nil] Sandbox creation parameters
|
|
@@ -93,7 +108,7 @@ module Daytona
|
|
|
93
108
|
# @param limit [Integer, Nil]
|
|
94
109
|
# @return [Daytona::PaginatedResource]
|
|
95
110
|
# @raise [Daytona::Sdk::Error]
|
|
96
|
-
def list(labels = {}, page: nil, limit: nil)
|
|
111
|
+
def list(labels = {}, page: nil, limit: nil)
|
|
97
112
|
raise Sdk::Error, 'page must be positive integer' if page && page < 1
|
|
98
113
|
|
|
99
114
|
raise Sdk::Error, 'limit must be positive integer' if limit && limit < 1
|
|
@@ -124,8 +139,13 @@ module Daytona
|
|
|
124
139
|
# @return [void]
|
|
125
140
|
def stop(sandbox, timeout = Sandbox::DEFAULT_TIMEOUT) = sandbox.stop(timeout)
|
|
126
141
|
|
|
142
|
+
instrument :create, :delete, :get, :find_one, :list, :start, :stop, component: 'Daytona'
|
|
143
|
+
|
|
127
144
|
private
|
|
128
145
|
|
|
146
|
+
# @return [Daytona::OtelState, nil]
|
|
147
|
+
attr_reader :otel_state
|
|
148
|
+
|
|
129
149
|
# Creates a sandbox with the specified parameters
|
|
130
150
|
#
|
|
131
151
|
# @param params [Daytona::CreateSandboxFromSnapshotParams, Daytona::CreateSandboxFromImageParams] Sandbox creation parameters
|
|
@@ -133,7 +153,7 @@ module Daytona
|
|
|
133
153
|
# @param on_snapshot_create_logs [Proc]
|
|
134
154
|
# @return [Daytona::Sandbox] The created sandbox
|
|
135
155
|
# @raise [Daytona::Sdk::Error] If auto_stop_interval or auto_archive_interval is negative
|
|
136
|
-
def _create(params, timeout: 60, on_snapshot_create_logs: nil)
|
|
156
|
+
def _create(params, timeout: 60, on_snapshot_create_logs: nil)
|
|
137
157
|
raise Sdk::Error, 'Timeout must be a non-negative number' if timeout.negative?
|
|
138
158
|
|
|
139
159
|
start_time = Time.now
|
|
@@ -245,7 +265,8 @@ module Daytona
|
|
|
245
265
|
config:,
|
|
246
266
|
sandbox_api:,
|
|
247
267
|
code_toolbox:,
|
|
248
|
-
get_proxy_toolbox_url: proc { |sandbox_id, region_id| proxy_toolbox_url(sandbox_id, region_id) }
|
|
268
|
+
get_proxy_toolbox_url: proc { |sandbox_id, region_id| proxy_toolbox_url(sandbox_id, region_id) },
|
|
269
|
+
otel_state: @otel_state
|
|
249
270
|
)
|
|
250
271
|
end
|
|
251
272
|
|
data/lib/daytona/file_system.rb
CHANGED
|
@@ -5,6 +5,8 @@ require 'fileutils'
|
|
|
5
5
|
|
|
6
6
|
module Daytona
|
|
7
7
|
class FileSystem
|
|
8
|
+
include Instrumentation
|
|
9
|
+
|
|
8
10
|
# @return [String] The Sandbox ID
|
|
9
11
|
attr_reader :sandbox_id
|
|
10
12
|
|
|
@@ -15,9 +17,11 @@ module Daytona
|
|
|
15
17
|
#
|
|
16
18
|
# @param sandbox_id [String] The Sandbox ID
|
|
17
19
|
# @param toolbox_api [DaytonaToolboxApiClient::FileSystemApi] API client for Sandbox operations
|
|
18
|
-
|
|
20
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
21
|
+
def initialize(sandbox_id:, toolbox_api:, otel_state: nil)
|
|
19
22
|
@sandbox_id = sandbox_id
|
|
20
23
|
@toolbox_api = toolbox_api
|
|
24
|
+
@otel_state = otel_state
|
|
21
25
|
end
|
|
22
26
|
|
|
23
27
|
# Creates a new directory in the Sandbox at the specified path with the given
|
|
@@ -355,5 +359,15 @@ module Daytona
|
|
|
355
359
|
rescue StandardError => e
|
|
356
360
|
raise Sdk::Error, "Failed to set file permissions: #{e.message}"
|
|
357
361
|
end
|
|
362
|
+
|
|
363
|
+
instrument :create_folder, :delete_file, :get_file_info, :list_files, :download_file,
|
|
364
|
+
:upload_file, :upload_files, :find_files, :search_files, :move_files,
|
|
365
|
+
:replace_in_files, :set_file_permissions,
|
|
366
|
+
component: 'FileSystem'
|
|
367
|
+
|
|
368
|
+
private
|
|
369
|
+
|
|
370
|
+
# @return [Daytona::OtelState, nil]
|
|
371
|
+
attr_reader :otel_state
|
|
358
372
|
end
|
|
359
373
|
end
|
data/lib/daytona/git.rb
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Daytona
|
|
4
4
|
class Git
|
|
5
|
+
include Instrumentation
|
|
6
|
+
|
|
5
7
|
# @return [String] The Sandbox ID
|
|
6
8
|
attr_reader :sandbox_id
|
|
7
9
|
|
|
@@ -12,9 +14,11 @@ module Daytona
|
|
|
12
14
|
#
|
|
13
15
|
# @param sandbox_id [String] The Sandbox ID.
|
|
14
16
|
# @param toolbox_api [DaytonaToolboxApiClient::GitApi] API client for Sandbox operations.
|
|
15
|
-
|
|
17
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
18
|
+
def initialize(sandbox_id:, toolbox_api:, otel_state: nil)
|
|
16
19
|
@sandbox_id = sandbox_id
|
|
17
20
|
@toolbox_api = toolbox_api
|
|
21
|
+
@otel_state = otel_state
|
|
18
22
|
end
|
|
19
23
|
|
|
20
24
|
# Stages the specified files for the next commit, similar to
|
|
@@ -276,5 +280,14 @@ module Daytona
|
|
|
276
280
|
rescue StandardError => e
|
|
277
281
|
raise Sdk::Error, "Failed to delete branch: #{e.message}"
|
|
278
282
|
end
|
|
283
|
+
|
|
284
|
+
instrument :add, :branches, :clone, :commit, :push, :pull, :status,
|
|
285
|
+
:checkout_branch, :create_branch, :delete_branch,
|
|
286
|
+
component: 'Git'
|
|
287
|
+
|
|
288
|
+
private
|
|
289
|
+
|
|
290
|
+
# @return [Daytona::OtelState, nil]
|
|
291
|
+
attr_reader :otel_state
|
|
279
292
|
end
|
|
280
293
|
end
|
data/lib/daytona/lsp_server.rb
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Daytona
|
|
4
4
|
class LspServer
|
|
5
|
+
include Instrumentation
|
|
6
|
+
|
|
5
7
|
module Language
|
|
6
8
|
ALL = [
|
|
7
9
|
JAVASCRIPT = :javascript,
|
|
@@ -31,11 +33,13 @@ module Daytona
|
|
|
31
33
|
# @param path_to_project [String]
|
|
32
34
|
# @param toolbox_api [DaytonaToolboxApiClient::LspApi]
|
|
33
35
|
# @param sandbox_id [String]
|
|
34
|
-
|
|
36
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
37
|
+
def initialize(language_id:, path_to_project:, toolbox_api:, sandbox_id:, otel_state: nil)
|
|
35
38
|
@language_id = language_id
|
|
36
39
|
@path_to_project = path_to_project
|
|
37
40
|
@toolbox_api = toolbox_api
|
|
38
41
|
@sandbox_id = sandbox_id
|
|
42
|
+
@otel_state = otel_state
|
|
39
43
|
end
|
|
40
44
|
|
|
41
45
|
# Gets completion suggestions at a position in a file
|
|
@@ -114,8 +118,15 @@ module Daytona
|
|
|
114
118
|
)
|
|
115
119
|
end
|
|
116
120
|
|
|
121
|
+
instrument :completions, :did_close, :did_open, :document_symbols, :sandbox_symbols,
|
|
122
|
+
:start, :stop,
|
|
123
|
+
component: 'LspServer'
|
|
124
|
+
|
|
117
125
|
private
|
|
118
126
|
|
|
127
|
+
# @return [Daytona::OtelState, nil]
|
|
128
|
+
attr_reader :otel_state
|
|
129
|
+
|
|
119
130
|
# Convert path to file uri.
|
|
120
131
|
#
|
|
121
132
|
# @param path [String]
|
data/lib/daytona/otel.rb
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Daytona
|
|
4
|
+
# Holds OTel provider state for the SDK.
|
|
5
|
+
class OtelState
|
|
6
|
+
attr_reader :tracer_provider
|
|
7
|
+
attr_reader :meter_provider
|
|
8
|
+
attr_reader :tracer
|
|
9
|
+
attr_reader :meter
|
|
10
|
+
|
|
11
|
+
def initialize(tracer_provider:, meter_provider:, tracer:, meter:)
|
|
12
|
+
@tracer_provider = tracer_provider
|
|
13
|
+
@meter_provider = meter_provider
|
|
14
|
+
@tracer = tracer
|
|
15
|
+
@meter = meter
|
|
16
|
+
@histograms = {}
|
|
17
|
+
@histograms_mutex = Mutex.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Returns a cached histogram for the given metric name.
|
|
21
|
+
def histogram(name)
|
|
22
|
+
@histograms_mutex.synchronize do
|
|
23
|
+
@histograms[name] ||= meter.create_histogram(name, unit: 'ms')
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def shutdown
|
|
28
|
+
tracer_provider.shutdown
|
|
29
|
+
meter_provider.shutdown
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Initializes OTel providers, sets globals, installs Typhoeus propagation.
|
|
34
|
+
# OTel gems are required lazily so they are never loaded when disabled.
|
|
35
|
+
#
|
|
36
|
+
# @param sdk_version [String]
|
|
37
|
+
# @return [OtelState]
|
|
38
|
+
def self.init_otel(sdk_version) # rubocop:disable Metrics/MethodLength
|
|
39
|
+
require 'opentelemetry-sdk'
|
|
40
|
+
require 'opentelemetry-metrics-sdk'
|
|
41
|
+
require 'opentelemetry-exporter-otlp'
|
|
42
|
+
require 'opentelemetry-exporter-otlp-metrics'
|
|
43
|
+
|
|
44
|
+
resource = OpenTelemetry::SDK::Resources::Resource.create(
|
|
45
|
+
'service.name' => 'daytona-ruby-sdk',
|
|
46
|
+
'service.version' => sdk_version
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
tracer_provider = OpenTelemetry::SDK::Trace::TracerProvider.new(resource:)
|
|
50
|
+
tracer_provider.add_span_processor(
|
|
51
|
+
OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
|
|
52
|
+
OpenTelemetry::Exporter::OTLP::Exporter.new
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
OpenTelemetry.tracer_provider = tracer_provider
|
|
56
|
+
|
|
57
|
+
meter_provider = OpenTelemetry::SDK::Metrics::MeterProvider.new(resource:)
|
|
58
|
+
meter_provider.add_metric_reader(
|
|
59
|
+
OpenTelemetry::SDK::Metrics::Export::PeriodicMetricReader.new(
|
|
60
|
+
exporter: OpenTelemetry::Exporter::OTLP::Metrics::MetricsExporter.new
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
OpenTelemetry.meter_provider = meter_provider
|
|
64
|
+
|
|
65
|
+
tracer = tracer_provider.tracer('daytona-ruby-sdk', sdk_version)
|
|
66
|
+
meter = meter_provider.meter('daytona-ruby-sdk')
|
|
67
|
+
|
|
68
|
+
# Install Typhoeus trace-context propagation
|
|
69
|
+
install_typhoeus_propagation
|
|
70
|
+
|
|
71
|
+
OtelState.new(tracer_provider:, meter_provider:, tracer:, meter:)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Flushes and shuts down OTel providers.
|
|
75
|
+
def self.shutdown_otel(state)
|
|
76
|
+
state&.shutdown
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Wraps a block with OTel span creation and duration histogram recording.
|
|
80
|
+
# When otel_state is nil (OTel disabled), calls the block directly.
|
|
81
|
+
#
|
|
82
|
+
# @param otel_state [OtelState, nil]
|
|
83
|
+
# @param component [String]
|
|
84
|
+
# @param method_name [String]
|
|
85
|
+
# @return [Object] The block's return value
|
|
86
|
+
def self.with_instrumentation(otel_state, component, method_name, &block) # rubocop:disable Metrics/MethodLength
|
|
87
|
+
return block.call unless otel_state
|
|
88
|
+
|
|
89
|
+
span_name = "#{component}.#{method_name}"
|
|
90
|
+
metric_name = "#{to_snake_case(span_name)}_duration"
|
|
91
|
+
status = 'success'
|
|
92
|
+
|
|
93
|
+
otel_state.tracer.in_span(
|
|
94
|
+
span_name,
|
|
95
|
+
attributes: { 'component' => component, 'method' => method_name }
|
|
96
|
+
) do |_span|
|
|
97
|
+
start_time = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
|
|
98
|
+
begin
|
|
99
|
+
block.call
|
|
100
|
+
rescue StandardError => e
|
|
101
|
+
status = 'error'
|
|
102
|
+
raise e
|
|
103
|
+
ensure
|
|
104
|
+
duration_ms = (::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - start_time) * 1000.0
|
|
105
|
+
otel_state.histogram(metric_name).record(
|
|
106
|
+
duration_ms,
|
|
107
|
+
attributes: { 'component' => component, 'method' => method_name, 'status' => status }
|
|
108
|
+
)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Converts "ClassName.method_name" to "class_name_method_name".
|
|
114
|
+
def self.to_snake_case(str)
|
|
115
|
+
result = +''
|
|
116
|
+
str.each_char.with_index do |char, i|
|
|
117
|
+
if char == '.'
|
|
118
|
+
result << '_'
|
|
119
|
+
elsif char =~ /[A-Z]/ && i > 0 && str[i - 1] != '.'
|
|
120
|
+
result << '_' << char.downcase
|
|
121
|
+
else
|
|
122
|
+
result << char.downcase
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
result
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Installs Typhoeus.before callback for W3C trace-context propagation.
|
|
129
|
+
def self.install_typhoeus_propagation
|
|
130
|
+
return unless defined?(Typhoeus)
|
|
131
|
+
|
|
132
|
+
Typhoeus.before do |request|
|
|
133
|
+
headers = request.options[:headers] ||= {}
|
|
134
|
+
OpenTelemetry.propagation.inject(headers)
|
|
135
|
+
true
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Mixin that provides the `instrument` class macro for wrapping methods
|
|
140
|
+
# with OTel spans and metrics.
|
|
141
|
+
module Instrumentation
|
|
142
|
+
def self.included(base)
|
|
143
|
+
base.extend(ClassMethods)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
module ClassMethods
|
|
147
|
+
# Instruments the listed methods with OTel tracing/metrics.
|
|
148
|
+
# Must be called after all target methods are defined.
|
|
149
|
+
#
|
|
150
|
+
# @param method_names [Array<Symbol>] methods to instrument
|
|
151
|
+
# @param component [String] component name for span/metric attributes
|
|
152
|
+
def instrument(*method_names, component:) # rubocop:disable Metrics/MethodLength
|
|
153
|
+
method_names.each do |method_name|
|
|
154
|
+
original = instance_method(method_name)
|
|
155
|
+
|
|
156
|
+
# Detect original visibility
|
|
157
|
+
visibility = if private_method_defined?(method_name, false)
|
|
158
|
+
:private
|
|
159
|
+
elsif protected_method_defined?(method_name, false)
|
|
160
|
+
:protected
|
|
161
|
+
else
|
|
162
|
+
:public
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
define_method(method_name) do |*args, **kwargs, &blk|
|
|
166
|
+
::Daytona.with_instrumentation(otel_state, component, method_name.to_s) do
|
|
167
|
+
original.bind_call(self, *args, **kwargs, &blk)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Restore visibility
|
|
172
|
+
case visibility
|
|
173
|
+
when :private then private method_name
|
|
174
|
+
when :protected then protected method_name
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
data/lib/daytona/process.rb
CHANGED
|
@@ -6,6 +6,8 @@ require 'uri'
|
|
|
6
6
|
|
|
7
7
|
module Daytona
|
|
8
8
|
class Process # rubocop:disable Metrics/ClassLength
|
|
9
|
+
include Instrumentation
|
|
10
|
+
|
|
9
11
|
# @return [Daytona::SandboxPythonCodeToolbox,
|
|
10
12
|
attr_reader :code_toolbox
|
|
11
13
|
|
|
@@ -24,11 +26,13 @@ module Daytona
|
|
|
24
26
|
# @param sandbox_id [String] The ID of the Sandbox
|
|
25
27
|
# @param toolbox_api [DaytonaToolboxApiClient::ProcessApi] API client for Sandbox operations
|
|
26
28
|
# @param get_preview_link [Proc] Function to get preview link for a port
|
|
27
|
-
|
|
29
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
30
|
+
def initialize(code_toolbox:, sandbox_id:, toolbox_api:, get_preview_link:, otel_state: nil)
|
|
28
31
|
@code_toolbox = code_toolbox
|
|
29
32
|
@sandbox_id = sandbox_id
|
|
30
33
|
@toolbox_api = toolbox_api
|
|
31
34
|
@get_preview_link = get_preview_link
|
|
35
|
+
@otel_state = otel_state
|
|
32
36
|
end
|
|
33
37
|
|
|
34
38
|
# Execute a shell command in the Sandbox
|
|
@@ -448,8 +452,18 @@ module Daytona
|
|
|
448
452
|
toolbox_api.get_pty_session(session_id)
|
|
449
453
|
end
|
|
450
454
|
|
|
455
|
+
instrument :exec, :code_run, :create_session, :get_session, :get_session_command,
|
|
456
|
+
:execute_session_command, :get_session_command_logs, :get_session_command_logs_async,
|
|
457
|
+
:send_session_command_input, :list_sessions, :delete_session,
|
|
458
|
+
:create_pty_session, :connect_pty_session, :resize_pty_session,
|
|
459
|
+
:delete_pty_session, :list_pty_sessions, :get_pty_session_info,
|
|
460
|
+
component: 'Process'
|
|
461
|
+
|
|
451
462
|
private
|
|
452
463
|
|
|
464
|
+
# @return [Daytona::OtelState, nil]
|
|
465
|
+
attr_reader :otel_state
|
|
466
|
+
|
|
453
467
|
# Parse the output of a command to extract ExecutionArtifacts
|
|
454
468
|
#
|
|
455
469
|
# @param lines [Array<String>] A list of lines of output from a command
|
data/lib/daytona/sandbox.rb
CHANGED
|
@@ -4,6 +4,8 @@ require 'timeout'
|
|
|
4
4
|
|
|
5
5
|
module Daytona
|
|
6
6
|
class Sandbox # rubocop:disable Metrics/ClassLength
|
|
7
|
+
include Instrumentation
|
|
8
|
+
|
|
7
9
|
DEFAULT_TIMEOUT = 60
|
|
8
10
|
|
|
9
11
|
# @return [String] The ID of the sandbox
|
|
@@ -116,12 +118,14 @@ module Daytona
|
|
|
116
118
|
# @params config [Daytona::Config]
|
|
117
119
|
# @params sandbox_api [DaytonaApiClient::SandboxApi]
|
|
118
120
|
# @params sandbox_dto [DaytonaApiClient::Sandbox]
|
|
119
|
-
|
|
121
|
+
# @params otel_state [Daytona::OtelState, nil]
|
|
122
|
+
def initialize(code_toolbox:, sandbox_dto:, config:, sandbox_api:, get_proxy_toolbox_url:, otel_state: nil) # rubocop:disable Metrics/MethodLength
|
|
120
123
|
process_response(sandbox_dto)
|
|
121
124
|
@code_toolbox = code_toolbox
|
|
122
125
|
@config = config
|
|
123
126
|
@sandbox_api = sandbox_api
|
|
124
127
|
@get_proxy_toolbox_url = get_proxy_toolbox_url
|
|
128
|
+
@otel_state = otel_state
|
|
125
129
|
|
|
126
130
|
# Create toolbox API clients with dynamic configuration
|
|
127
131
|
toolbox_api_config = build_toolbox_api_config
|
|
@@ -148,15 +152,17 @@ module Daytona
|
|
|
148
152
|
sandbox_id: id,
|
|
149
153
|
code_toolbox:,
|
|
150
154
|
toolbox_api: process_api,
|
|
151
|
-
get_preview_link: proc { |port| preview_url(port) }
|
|
155
|
+
get_preview_link: proc { |port| preview_url(port) },
|
|
156
|
+
otel_state:
|
|
152
157
|
)
|
|
153
|
-
@fs = FileSystem.new(sandbox_id: id, toolbox_api: fs_api)
|
|
154
|
-
@git = Git.new(sandbox_id: id, toolbox_api: git_api)
|
|
155
|
-
@computer_use = ComputerUse.new(sandbox_id: id, toolbox_api: computer_use_api)
|
|
158
|
+
@fs = FileSystem.new(sandbox_id: id, toolbox_api: fs_api, otel_state:)
|
|
159
|
+
@git = Git.new(sandbox_id: id, toolbox_api: git_api, otel_state:)
|
|
160
|
+
@computer_use = ComputerUse.new(sandbox_id: id, toolbox_api: computer_use_api, otel_state:)
|
|
156
161
|
@code_interpreter = CodeInterpreter.new(
|
|
157
162
|
sandbox_id: id,
|
|
158
163
|
toolbox_api: interpreter_api,
|
|
159
|
-
get_preview_link: proc { |port| preview_url(port) }
|
|
164
|
+
get_preview_link: proc { |port| preview_url(port) },
|
|
165
|
+
otel_state:
|
|
160
166
|
)
|
|
161
167
|
@lsp_api = lsp_api
|
|
162
168
|
@info_api = info_api
|
|
@@ -382,7 +388,7 @@ module Daytona
|
|
|
382
388
|
# based on the sandbox working directory.
|
|
383
389
|
# @return [Daytona::LspServer]
|
|
384
390
|
def create_lsp_server(language_id:, path_to_project:)
|
|
385
|
-
LspServer.new(language_id:, path_to_project:, toolbox_api: @lsp_api, sandbox_id: id)
|
|
391
|
+
LspServer.new(language_id:, path_to_project:, toolbox_api: @lsp_api, sandbox_id: id, otel_state:)
|
|
386
392
|
end
|
|
387
393
|
|
|
388
394
|
# Validates an SSH access token for the sandbox.
|
|
@@ -411,8 +417,19 @@ module Daytona
|
|
|
411
417
|
DaytonaApiClient::SandboxState::DESTROYED])
|
|
412
418
|
end
|
|
413
419
|
|
|
420
|
+
instrument :archive, :auto_archive_interval=, :auto_delete_interval=, :auto_stop_interval=,
|
|
421
|
+
:create_ssh_access, :delete, :get_user_home_dir, :get_work_dir, :labels=,
|
|
422
|
+
:preview_url, :create_signed_preview_url, :expire_signed_preview_url,
|
|
423
|
+
:refresh, :refresh_activity, :revoke_ssh_access, :start, :recover, :stop,
|
|
424
|
+
:create_lsp_server, :validate_ssh_access, :wait_for_sandbox_start,
|
|
425
|
+
:wait_for_sandbox_stop,
|
|
426
|
+
component: 'Sandbox'
|
|
427
|
+
|
|
414
428
|
private
|
|
415
429
|
|
|
430
|
+
# @return [Daytona::OtelState, nil]
|
|
431
|
+
attr_reader :otel_state
|
|
432
|
+
|
|
416
433
|
# Build toolbox API configuration with dynamic base URL from preview link
|
|
417
434
|
# @return [DaytonaToolboxApiClient::Configuration]
|
|
418
435
|
def build_toolbox_api_config
|
data/lib/daytona/sdk/version.rb
CHANGED
data/lib/daytona/sdk.rb
CHANGED
|
@@ -4,15 +4,19 @@ require 'uri'
|
|
|
4
4
|
|
|
5
5
|
module Daytona
|
|
6
6
|
class SnapshotService
|
|
7
|
+
include Instrumentation
|
|
8
|
+
|
|
7
9
|
SNAPSHOTS_FETCH_LIMIT = 200
|
|
8
10
|
|
|
9
11
|
# @param snapshots_api [DaytonaApiClient::SnapshotsApi] The snapshots API client
|
|
10
12
|
# @param object_storage_api [DaytonaApiClient::ObjectStorageApi] The object storage API client
|
|
11
13
|
# @param default_region_id [String, nil] Default region ID for snapshot creation
|
|
12
|
-
|
|
14
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
15
|
+
def initialize(snapshots_api:, object_storage_api:, default_region_id: nil, otel_state: nil)
|
|
13
16
|
@snapshots_api = snapshots_api
|
|
14
17
|
@object_storage_api = object_storage_api
|
|
15
18
|
@default_region_id = default_region_id
|
|
19
|
+
@otel_state = otel_state
|
|
16
20
|
end
|
|
17
21
|
|
|
18
22
|
# List all Snapshots.
|
|
@@ -119,6 +123,8 @@ module Daytona
|
|
|
119
123
|
# @return [Daytona::Snapshot]
|
|
120
124
|
def activate(snapshot) = Snapshot.from_dto(snapshots_api.activate_snapshot(snapshot.id))
|
|
121
125
|
|
|
126
|
+
instrument :list, :delete, :get, :create, :activate, component: 'SnapshotService'
|
|
127
|
+
|
|
122
128
|
# Processes the image context by uploading it to object storage
|
|
123
129
|
#
|
|
124
130
|
# @param image [Daytona::Image] The Image instance
|
|
@@ -156,6 +162,9 @@ module Daytona
|
|
|
156
162
|
# @return [String, nil] Default region ID for snapshot creation
|
|
157
163
|
attr_reader :default_region_id
|
|
158
164
|
|
|
165
|
+
# @return [Daytona::OtelState, nil]
|
|
166
|
+
attr_reader :otel_state
|
|
167
|
+
|
|
159
168
|
# Wait for snapshot to reach a terminal state (ACTIVE, ERROR, or BUILD_FAILED)
|
|
160
169
|
# Optionally streams logs if on_logs callback is provided
|
|
161
170
|
#
|
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module Daytona
|
|
4
4
|
class VolumeService
|
|
5
|
+
include Instrumentation
|
|
6
|
+
|
|
5
7
|
# Service for managing Daytona Volumes. Can be used to list, get, create and delete Volumes.
|
|
6
8
|
#
|
|
7
9
|
# @param volumes_api [DaytonaApiClient::VolumesApi]
|
|
8
|
-
|
|
10
|
+
# @param otel_state [Daytona::OtelState, nil]
|
|
11
|
+
def initialize(volumes_api, otel_state: nil)
|
|
9
12
|
@volumes_api = volumes_api
|
|
13
|
+
@otel_state = otel_state
|
|
10
14
|
end
|
|
11
15
|
|
|
12
16
|
# Create new Volume.
|
|
@@ -41,9 +45,14 @@ module Daytona
|
|
|
41
45
|
volumes_api.list_volumes.map { |volume| Volume.new(volume) }
|
|
42
46
|
end
|
|
43
47
|
|
|
48
|
+
instrument :create, :delete, :get, :list, component: 'VolumeService'
|
|
49
|
+
|
|
44
50
|
private
|
|
45
51
|
|
|
46
52
|
# @return [DaytonaApiClient::VolumesApi]
|
|
47
53
|
attr_reader :volumes_api
|
|
54
|
+
|
|
55
|
+
# @return [Daytona::OtelState, nil]
|
|
56
|
+
attr_reader :otel_state
|
|
48
57
|
end
|
|
49
58
|
end
|
metadata
CHANGED
|
@@ -1,15 +1,71 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: daytona
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.141.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daytona Platforms Inc.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: opentelemetry-exporter-otlp
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '0.29'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '0.29'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: opentelemetry-exporter-otlp-metrics
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0.1'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0.1'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: opentelemetry-metrics-sdk
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.2'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0.2'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: opentelemetry-sdk
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '1.4'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '1.4'
|
|
13
69
|
- !ruby/object:Gem::Dependency
|
|
14
70
|
name: aws-sdk-s3
|
|
15
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -30,28 +86,28 @@ dependencies:
|
|
|
30
86
|
requirements:
|
|
31
87
|
- - '='
|
|
32
88
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 0.
|
|
89
|
+
version: 0.141.0
|
|
34
90
|
type: :runtime
|
|
35
91
|
prerelease: false
|
|
36
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
93
|
requirements:
|
|
38
94
|
- - '='
|
|
39
95
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 0.
|
|
96
|
+
version: 0.141.0
|
|
41
97
|
- !ruby/object:Gem::Dependency
|
|
42
98
|
name: daytona_toolbox_api_client
|
|
43
99
|
requirement: !ruby/object:Gem::Requirement
|
|
44
100
|
requirements:
|
|
45
101
|
- - '='
|
|
46
102
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 0.
|
|
103
|
+
version: 0.141.0
|
|
48
104
|
type: :runtime
|
|
49
105
|
prerelease: false
|
|
50
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
107
|
requirements:
|
|
52
108
|
- - '='
|
|
53
109
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 0.
|
|
110
|
+
version: 0.141.0
|
|
55
111
|
- !ruby/object:Gem::Dependency
|
|
56
112
|
name: dotenv
|
|
57
113
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -131,6 +187,7 @@ files:
|
|
|
131
187
|
- lib/daytona/git.rb
|
|
132
188
|
- lib/daytona/lsp_server.rb
|
|
133
189
|
- lib/daytona/object_storage.rb
|
|
190
|
+
- lib/daytona/otel.rb
|
|
134
191
|
- lib/daytona/process.rb
|
|
135
192
|
- lib/daytona/sandbox.rb
|
|
136
193
|
- lib/daytona/sdk.rb
|