Packages

Generic Elixir toolkit for deploying, observing, and readiness-verifying Coolify apps

Current section

Files

Jump to
coolify_ex lib mix tasks coolify.app_logs.ex
Raw

lib/mix/tasks/coolify.app_logs.ex

defmodule Mix.Tasks.Coolify.AppLogs do
use Mix.Task
@shortdoc "Fetches runtime application logs from Coolify"
alias CoolifyEx.ApplicationLogs
alias CoolifyEx.Config
alias CoolifyEx.MixTaskSupport
@moduledoc """
Fetches runtime logs for one configured Coolify app.
mix coolify.app_logs
mix coolify.app_logs --project web
mix coolify.app_logs --project web --lines 200 --follow
"""
@impl Mix.Task
def run(args) do
MixTaskSupport.ensure_started!()
{opts, _argv, _invalid} =
OptionParser.parse(args,
strict: [
project: :string,
app: :string,
config: :string,
lines: :integer,
follow: :boolean,
poll_interval: :integer
]
)
case Config.load(Keyword.get(opts, :config)) do
{:ok, config} ->
run_logs(config, opts)
{:error, reason} ->
Mix.raise("Could not load config: #{inspect(reason)}")
end
end
defp run_logs(config, opts) do
target_name = Keyword.get(opts, :project) || Keyword.get(opts, :app)
fetch_opts = [lines: Keyword.get(opts, :lines, 100)]
if Keyword.get(opts, :follow, false) do
case ApplicationLogs.follow(
config,
target_name,
&print_log_line/1,
fetch_opts ++ [poll_interval: Keyword.get(opts, :poll_interval, 2_000)]
) do
:ok -> :ok
{:error, reason} -> Mix.raise("Could not fetch application logs: #{inspect(reason)}")
end
else
case ApplicationLogs.fetch(config, target_name, fetch_opts) do
{:ok, application_logs} ->
Enum.each(application_logs.logs, &print_log_line/1)
{:error, reason} ->
Mix.raise("Could not fetch application logs: #{inspect(reason)}")
end
end
end
defp print_log_line(line) do
prefix =
case line.timestamp do
nil -> ""
timestamp -> "[#{timestamp}] "
end
Mix.shell().info(prefix <> line.output)
end
end