Compare commits
2 Commits
a055491f6b
...
42e2d1c76e
Author | SHA1 | Date | |
---|---|---|---|
42e2d1c76e | |||
064d2d3988 |
@ -3,6 +3,7 @@
|
|||||||
- Improve templates
|
- Improve templates
|
||||||
- Improve invites, record usage
|
- Improve invites, record usage
|
||||||
- Fix padding on more pages when using chrome
|
- Fix padding on more pages when using chrome
|
||||||
|
- Add oban metrics to server log and live dashboard
|
||||||
|
|
||||||
# v0.8.1
|
# v0.8.1
|
||||||
- Update dependencies
|
- Update dependencies
|
||||||
|
@ -64,8 +64,9 @@ config :cannery, CanneryWeb.Endpoint,
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
# Do not include metadata nor timestamps in development logs
|
config :logger, :console,
|
||||||
config :logger, :console, format: "[$level] $message\n"
|
format: "[$level] $message $metadata\n\n",
|
||||||
|
metadata: [:data]
|
||||||
|
|
||||||
# Set a higher stacktrace during development. Avoid configuring such
|
# Set a higher stacktrace during development. Avoid configuring such
|
||||||
# in production as building large stacktraces may be expensive.
|
# in production as building large stacktraces may be expensive.
|
||||||
|
@ -44,8 +44,6 @@ config :cannery, Cannery.Repo,
|
|||||||
pool_size: String.to_integer(System.get_env("POOL_SIZE", "10")),
|
pool_size: String.to_integer(System.get_env("POOL_SIZE", "10")),
|
||||||
socket_options: maybe_ipv6
|
socket_options: maybe_ipv6
|
||||||
|
|
||||||
config :cannery, Cannery.Accounts, registration: System.get_env("REGISTRATION", "invite")
|
|
||||||
|
|
||||||
config :cannery, CanneryWeb.Endpoint,
|
config :cannery, CanneryWeb.Endpoint,
|
||||||
url: [scheme: "https", host: host, port: 443],
|
url: [scheme: "https", host: host, port: 443],
|
||||||
http: [
|
http: [
|
||||||
@ -56,6 +54,10 @@ config :cannery, CanneryWeb.Endpoint,
|
|||||||
],
|
],
|
||||||
server: true
|
server: true
|
||||||
|
|
||||||
|
if config_env() in [:dev, :prod] do
|
||||||
|
config :cannery, Cannery.Accounts, registration: System.get_env("REGISTRATION", "invite")
|
||||||
|
end
|
||||||
|
|
||||||
if config_env() == :prod do
|
if config_env() == :prod do
|
||||||
# The secret key base is used to sign/encrypt cookies and other secrets.
|
# The secret key base is used to sign/encrypt cookies and other secrets.
|
||||||
# A default value is used in config/dev.exs and config/test.exs but you
|
# A default value is used in config/dev.exs and config/test.exs but you
|
||||||
|
@ -22,6 +22,9 @@ config :cannery, CanneryWeb.Endpoint,
|
|||||||
# In test we don't send emails.
|
# In test we don't send emails.
|
||||||
config :cannery, Cannery.Mailer, adapter: Swoosh.Adapters.Test
|
config :cannery, Cannery.Mailer, adapter: Swoosh.Adapters.Test
|
||||||
|
|
||||||
|
# Don't require invites for signups
|
||||||
|
config :cannery, Cannery.Accounts, registration: "public"
|
||||||
|
|
||||||
# Print only warnings and errors during test
|
# Print only warnings and errors during test
|
||||||
config :logger, level: :warn
|
config :logger, level: :warn
|
||||||
|
|
||||||
|
@ -117,6 +117,8 @@ defmodule Cannery.Accounts do
|
|||||||
:passed
|
:passed
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@spec register_user(attrs :: map()) ::
|
||||||
|
{:ok, User.t()} | {:error, :invalid_token | User.changeset()}
|
||||||
@spec register_user(attrs :: map(), Invite.token() | nil) ::
|
@spec register_user(attrs :: map(), Invite.token() | nil) ::
|
||||||
{:ok, User.t()} | {:error, :invalid_token | User.changeset()}
|
{:ok, User.t()} | {:error, :invalid_token | User.changeset()}
|
||||||
def register_user(attrs, invite_token \\ nil) do
|
def register_user(attrs, invite_token \\ nil) do
|
||||||
|
@ -85,7 +85,9 @@ defmodule Cannery.Accounts.Invites do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec get_invite_by_token(Invite.token()) :: {:ok, Invite.t()} | {:error, :invalid_token}
|
@spec get_invite_by_token(Invite.token() | nil) :: {:ok, Invite.t()} | {:error, :invalid_token}
|
||||||
|
defp get_invite_by_token(token) when token in [nil, ""], do: {:error, :invalid_token}
|
||||||
|
|
||||||
defp get_invite_by_token(token) do
|
defp get_invite_by_token(token) do
|
||||||
Repo.one(
|
Repo.one(
|
||||||
from i in Invite,
|
from i in Invite,
|
||||||
|
@ -4,6 +4,7 @@ defmodule Cannery.Application do
|
|||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Application
|
use Application
|
||||||
|
alias Cannery.ErrorReporter
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def start(_type, _args) do
|
def start(_type, _args) do
|
||||||
@ -17,16 +18,24 @@ defmodule Cannery.Application do
|
|||||||
# Start the Endpoint (http/https)
|
# Start the Endpoint (http/https)
|
||||||
CanneryWeb.Endpoint,
|
CanneryWeb.Endpoint,
|
||||||
# Add Oban
|
# Add Oban
|
||||||
{Oban, oban_config()}
|
{Oban, oban_config()},
|
||||||
|
Cannery.Repo.Migrator
|
||||||
# Start a worker by calling: Cannery.Worker.start_link(arg)
|
# Start a worker by calling: Cannery.Worker.start_link(arg)
|
||||||
# {Cannery.Worker, arg}
|
# {Cannery.Worker, arg}
|
||||||
]
|
]
|
||||||
|
|
||||||
# Automatically migrate on start in prod
|
# Oban events logging https://hexdocs.pm/oban/Oban.html#module-reporting-errors
|
||||||
children =
|
:ok =
|
||||||
if Application.get_env(:cannery, Cannery.Application, automigrate: false)[:automigrate],
|
:telemetry.attach_many(
|
||||||
do: children ++ [Cannery.Repo.Migrator],
|
"oban-logger",
|
||||||
else: children
|
[
|
||||||
|
[:oban, :job, :exception],
|
||||||
|
[:oban, :job, :start],
|
||||||
|
[:oban, :job, :stop]
|
||||||
|
],
|
||||||
|
&ErrorReporter.handle_event/4,
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
|
||||||
# See https://hexdocs.pm/elixir/Supervisor.html
|
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||||
# for other strategies and supported options
|
# for other strategies and supported options
|
||||||
|
57
lib/cannery/error_reporter.ex
Normal file
57
lib/cannery/error_reporter.ex
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
defmodule Cannery.ErrorReporter do
|
||||||
|
@moduledoc """
|
||||||
|
Custom logger for telemetry events
|
||||||
|
|
||||||
|
Oban implementation taken from
|
||||||
|
https://hexdocs.pm/oban/Oban.html#module-reporting-errors
|
||||||
|
"""
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
def handle_event([:oban, :job, :exception], measure, %{stacktrace: stacktrace} = meta, _config) do
|
||||||
|
data =
|
||||||
|
get_oban_job_data(meta, measure)
|
||||||
|
|> Map.put(:stacktrace, Exception.format_stacktrace(stacktrace))
|
||||||
|
|
||||||
|
Logger.error(meta.reason, data: pretty_encode(data))
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event([:oban, :job, :start], measure, meta, _config) do
|
||||||
|
Logger.info("Started oban job", data: get_oban_job_data(meta, measure) |> pretty_encode())
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event([:oban, :job, :stop], measure, meta, _config) do
|
||||||
|
Logger.info("Finished oban job", data: get_oban_job_data(meta, measure) |> pretty_encode())
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event([:oban, :job, unhandled_event], measure, meta, _config) do
|
||||||
|
data =
|
||||||
|
get_oban_job_data(meta, measure)
|
||||||
|
|> Map.put(:event, unhandled_event)
|
||||||
|
|
||||||
|
Logger.warning("Unhandled oban job event", data: pretty_encode(data))
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_event(unhandled_event, measure, meta, config) do
|
||||||
|
data = %{
|
||||||
|
event: unhandled_event,
|
||||||
|
meta: meta,
|
||||||
|
measurements: measure,
|
||||||
|
config: config
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.warning("Unhandled telemetry event", data: pretty_encode(data))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_oban_job_data(%{job: job}, measure) do
|
||||||
|
job
|
||||||
|
|> Map.take([:id, :args, :meta, :queue, :worker])
|
||||||
|
|> Map.merge(measure)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp pretty_encode(data) do
|
||||||
|
data
|
||||||
|
|> Jason.encode!()
|
||||||
|
|> Jason.Formatter.pretty_print()
|
||||||
|
end
|
||||||
|
end
|
@ -11,12 +11,15 @@ defmodule Cannery.Repo.Migrator do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def init(_opts) do
|
def init(_opts) do
|
||||||
migrate!()
|
{:ok, if(automigrate_enabled?(), do: migrate!())}
|
||||||
{:ok, nil}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def migrate! do
|
def migrate! do
|
||||||
path = Application.app_dir(:cannery, "priv/repo/migrations")
|
path = Application.app_dir(:cannery, "priv/repo/migrations")
|
||||||
Ecto.Migrator.run(Cannery.Repo, path, :up, all: true)
|
Ecto.Migrator.run(Cannery.Repo, path, :up, all: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp automigrate_enabled? do
|
||||||
|
Application.get_env(:cannery, Cannery.Application, automigrate: false)[:automigrate]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -57,6 +57,30 @@ defmodule CanneryWeb.Telemetry do
|
|||||||
"The time the connection spent waiting before being checked out for the query"
|
"The time the connection spent waiting before being checked out for the query"
|
||||||
),
|
),
|
||||||
|
|
||||||
|
# Oban Metrics
|
||||||
|
counter("oban.job.exception",
|
||||||
|
tags: [:queue, :worker],
|
||||||
|
event_name: [:oban, :job, :exception],
|
||||||
|
measurement: :duration,
|
||||||
|
description: "Number of oban jobs that raised an exception"
|
||||||
|
),
|
||||||
|
counter("oban.job.start",
|
||||||
|
tags: [:queue, :worker],
|
||||||
|
event_name: [:oban, :job, :start],
|
||||||
|
measurement: :system_time,
|
||||||
|
description: "Number of oban jobs started"
|
||||||
|
),
|
||||||
|
summary("oban.job.stop.duration",
|
||||||
|
tags: [:queue, :worker],
|
||||||
|
unit: {:native, :millisecond},
|
||||||
|
description: "Length of time spent processing the oban job"
|
||||||
|
),
|
||||||
|
summary("oban.job.stop.queue_time",
|
||||||
|
tags: [:queue, :worker],
|
||||||
|
unit: {:native, :millisecond},
|
||||||
|
description: "Time the oban job spent waiting in milliseconds"
|
||||||
|
),
|
||||||
|
|
||||||
# VM Metrics
|
# VM Metrics
|
||||||
summary("vm.memory.total", unit: {:byte, :kilobyte}),
|
summary("vm.memory.total", unit: {:byte, :kilobyte}),
|
||||||
summary("vm.total_run_queue_lengths.total"),
|
summary("vm.total_run_queue_lengths.total"),
|
||||||
|
Loading…
Reference in New Issue
Block a user