Class: Clacky::DeployTools::FetchRuntimeLogs

Inherits:
Object
  • Object
show all
Defined in:
lib/clacky/default_skills/deploy/tools/fetch_runtime_logs.rb

Overview

Fetch runtime (environment) logs from a deployed Railway service via the Clacky Deploy API SSE endpoint.

Uses DeployApiClient#stream_build_logs for build-phase logs (on failure), and this class for runtime log fetching (e.g. post-deploy diagnostics).

Constant Summary collapse

DEFAULT_LINES =
50
MAX_LINES =
200
STREAM_TIMEOUT =

seconds

60

Class Method Summary collapse

Class Method Details

.execute(project_id:, workspace_key:, base_url:, lines: DEFAULT_LINES, keyword: nil) ⇒ Hash

Fetch recent runtime logs for a project.

Parameters:

  • project_id (String)

    Clacky project ID

  • workspace_key (String)

    clacky_ak_* key

  • base_url (String)

    API base URL

  • lines (Integer) (defaults to: DEFAULT_LINES)

    max log lines to collect

  • keyword (String) (defaults to: nil)

    optional filter keyword

Returns:

  • (Hash)

    { success: true, logs: Array<String> } or { success: false, error: String }



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/clacky/default_skills/deploy/tools/fetch_runtime_logs.rb', line 28

def self.execute(project_id:, workspace_key:, base_url:,
                 lines: DEFAULT_LINES, keyword: nil)
  lines = [[lines.to_i, 1].max, MAX_LINES].min

  params  = "project_id=#{URI.encode_www_form_component(project_id)}"
  params += "&keyword=#{URI.encode_www_form_component(keyword)}" if keyword

  uri = URI.parse(
    "#{base_url.to_s.sub(%r{/+$}, "")}" \
    "/openclacky/v1/deploy/logs/environment/stream?#{params}"
  )

  collected = []

  http              = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl      = (uri.scheme == "https")
  http.open_timeout = 10
  http.read_timeout = STREAM_TIMEOUT

  req                    = Net::HTTP::Get.new(uri.request_uri)
  req["Authorization"]   = "Bearer #{workspace_key}"
  req["Accept"]          = "text/event-stream"

  http.request(req) do |response|
    response.read_body do |chunk|
      chunk.split("\n").each do |raw|
        next unless raw.start_with?("data:")

        json_str = raw.sub(/\Adata:\s*/, "")
        next if json_str.strip.empty?

        begin
          event = JSON.parse(json_str)
          msg   = event["message"].to_s
          collected << msg unless msg.empty?
          return { success: true, logs: collected } if collected.size >= lines
        rescue JSON::ParserError
          # skip malformed events
        end
      end
    end
  end

  { success: true, logs: collected }
rescue => e
  { success: false, error: "Failed to fetch runtime logs: #{e.message}" }
end