Skip to content

Commit

Permalink
Added first steps of event logging
Browse files Browse the repository at this point in the history
  • Loading branch information
Teifion committed May 27, 2024
1 parent e972199 commit e089e3d
Show file tree
Hide file tree
Showing 23 changed files with 475 additions and 22 deletions.
2 changes: 1 addition & 1 deletion documentation/guides/telemetry_events.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
## Event categories
- Server
- Lobby
- ClientApp
- Clientapp
- Match

## Limitations
Expand Down
1 change: 1 addition & 0 deletions lib/angen/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ defmodule Angen.Application do
add_cache(:angen_metadata),
add_cache(:protocol_schemas),
add_cache(:protocol_command_dispatches),
add_cache(:telemetry_event_types_cache, ttl: :timer.minutes(15)),

{Horde.Registry, [keys: :unique, members: :auto, name: Angen.ConnectionRegistry]},
{Registry, [keys: :unique, members: :auto, name: Angen.LocalConnectionRegistry]},
Expand Down
22 changes: 22 additions & 0 deletions lib/angen/helpers/string_helper.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
defmodule Angen.Helper.StringHelper do
def format_number(nil), do: nil
def format_number(%Decimal{} = v), do: v |> Decimal.to_string() |> format_number
def format_number(v) when v < 1000, do: v

def format_number(v) when is_integer(v) do
v
|> Integer.to_string()
|> format_number
end

def format_number(v) when is_float(v) do
v
|> Float.to_string()
|> format_number
end

def format_number(v) do
v
|> String.replace(~r/[0-9](?=(?:[0-9]{3})+(?![0-9]))/, "\\0,")
end
end
10 changes: 7 additions & 3 deletions lib/angen/logging/tasks/persist_server_day_task.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule Angen.Logging.PersistServerDayTask do
@moduledoc false
use Oban.Worker, queue: :logging

alias Angen.{Repo, Logging}
alias Angen.{Repo, Logging, Telemetry}
alias Angen.Logging.ServerMinuteLogLib

# Minutes
Expand Down Expand Up @@ -304,8 +304,12 @@ defmodule Angen.Logging.PersistServerDayTask do
}
end

defp add_telemetry(data, _date, _node) do
data
defp add_telemetry(data, date, _node) do
end_of_day = Timex.shift(date, days: 1)

Map.put(data, :telemetry, %{
simple_clientapp: Telemetry.simple_clientapp_events_summary(after: date, before: end_of_day)
})
end

# Given a day log, calculate the end of day stats
Expand Down
21 changes: 21 additions & 0 deletions lib/angen/telemetry.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ defmodule Angen.Telemetry do
# EventTypes
alias Angen.Telemetry.{EventType, EventTypeLib, EventTypeQueries}

@doc section: :event_type
@spec get_or_add_event_type_id(name :: String.t(), category :: String.t()) :: EventType.id()
defdelegate get_or_add_event_type_id(name, category), to: EventTypeLib

@doc false
@spec event_type_query(Angen.query_args()) :: Ecto.Query.t()
defdelegate event_type_query(args), to: EventTypeQueries
Expand Down Expand Up @@ -65,4 +69,21 @@ defmodule Angen.Telemetry do
@spec change_event_type(EventType.t()) :: Ecto.Changeset.t()
@spec change_event_type(EventType.t(), map) :: Ecto.Changeset.t()
defdelegate change_event_type(event_type, attrs \\ %{}), to: EventTypeLib

# SimpleClientappEvents
alias Angen.Telemetry.{SimpleClientappEvent, SimpleClientappEventLib, SimpleClientappEventQueries}

@doc section: :event_type
@spec log_simple_clientapp_event(String.t(), Teiserver.user_id()) :: :ok | {:error, String.t()}
defdelegate log_simple_clientapp_event(name, user_id), to: SimpleClientappEventLib

@doc false
@spec simple_clientapp_event_query(Angen.query_args()) :: Ecto.Query.t()
defdelegate simple_clientapp_event_query(args), to: SimpleClientappEventQueries

@spec list_simple_clientapp_events(Teiserver.query_args()) :: [SimpleClientappEvent.t()]
defdelegate list_simple_clientapp_events(args), to: SimpleClientappEventLib

@spec simple_clientapp_events_summary(list) :: map()
defdelegate simple_clientapp_events_summary(args), to: SimpleClientappEventQueries
end
36 changes: 36 additions & 0 deletions lib/angen/telemetry/libs/event_type_lib.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,42 @@ defmodule Angen.Telemetry.EventTypeLib do
use TeiserverMacros, :library
alias Angen.Telemetry.{EventType, EventTypeQueries}

defp event_type_key(name, category), do: "#{category}, #{name}"

@doc """
Queries the cache to get the EventType id, if it doesn't exist in the cache
it will populate the cache from the DB
"""
@spec get_or_add_event_type_id(String.t(), String.t()) :: EventType.id()
def get_or_add_event_type_id(name, category) do
key = event_type_key(name, category)

case Cachex.get(:telemetry_event_types_cache, key) do
{:ok, nil} ->
event_type = db_get_or_add_event_type(name, category)
Cachex.put(:telemetry_event_types_cache, key, event_type.id)
event_type.id

{:ok, value} ->
value
end
end

# This does the DB stuff to get or create the event type
@spec db_get_or_add_event_type(String.t(), String.t()) :: EventType.t()
defp db_get_or_add_event_type(name, category) do
case get_event_type(nil, where: [name: name, category: category], limit: 1) do
nil ->
{:ok, event_type} = create_event_type(%{
name: name,
category: category
})
event_type
event_type ->
event_type
end
end

@doc """
Returns the list of event_types.
Expand Down
171 changes: 171 additions & 0 deletions lib/angen/telemetry/libs/simple_clientapp_event_lib.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
defmodule Angen.Telemetry.SimpleClientappEventLib do
@moduledoc """
Library of simple_clientapp_event related functions.
"""
use TeiserverMacros, :library
alias Angen.Telemetry
alias Angen.Telemetry.{SimpleClientappEvent, SimpleClientappEventQueries}

@doc """
A wrapper around create_simple_clientapp_event which handles grabbing the event_type_id
"""
@spec log_simple_clientapp_event(String.t(), Teiserver.user_id()) :: :ok | {:error, String.t()}
def log_simple_clientapp_event(name, user_id) do
type_id = Telemetry.get_or_add_event_type_id(name, "simple_clientapp")

attrs = %{
event_type_id: type_id,
user_id: user_id,
inserted_at: Timex.now()
}

case create_simple_clientapp_event(attrs) do
{:ok, _event} -> :ok
{:error, changeset} ->
IO.puts "#{__MODULE__}:#{__ENV__.line}"
IO.inspect attrs
IO.puts ""

IO.puts "#{__MODULE__}:#{__ENV__.line}"
IO.inspect changeset
IO.puts ""

{:error,
changeset.errors
|> Enum.map_join(", ", fn {key, {message, _}} ->
"#{key}: #{message}"
end)
}
end
end

@doc """
Returns the list of simple_clientapp_events.
## Examples
iex> list_simple_clientapp_events()
[%SimpleClientappEvent{}, ...]
"""
@spec list_simple_clientapp_events(Teiserver.query_args()) :: [SimpleClientappEvent.t()]
def list_simple_clientapp_events(query_args) do
query_args
|> SimpleClientappEventQueries.simple_clientapp_event_query()
|> Repo.all()
end

@doc """
Gets a single simple_clientapp_event.
Raises `Ecto.NoResultsError` if the SimpleClientappEvent does not exist.
## Examples
iex> get_simple_clientapp_event!(123)
%SimpleClientappEvent{}
iex> get_simple_clientapp_event!(456)
** (Ecto.NoResultsError)
"""
@spec get_simple_clientapp_event!(SimpleClientappEvent.id()) :: SimpleClientappEvent.t()
@spec get_simple_clientapp_event!(SimpleClientappEvent.id(), Teiserver.query_args()) :: SimpleClientappEvent.t()
def get_simple_clientapp_event!(simple_clientapp_event_id, query_args \\ []) do
(query_args ++ [id: simple_clientapp_event_id])
|> SimpleClientappEventQueries.simple_clientapp_event_query()
|> Repo.one!()
end

@doc """
Gets a single simple_clientapp_event.
Returns nil if the SimpleClientappEvent does not exist.
## Examples
iex> get_simple_clientapp_event(123)
%SimpleClientappEvent{}
iex> get_simple_clientapp_event(456)
nil
"""
@spec get_simple_clientapp_event(SimpleClientappEvent.id()) :: SimpleClientappEvent.t() | nil
@spec get_simple_clientapp_event(SimpleClientappEvent.id(), Teiserver.query_args()) :: SimpleClientappEvent.t() | nil
def get_simple_clientapp_event(simple_clientapp_event_id, query_args \\ []) do
(query_args ++ [id: simple_clientapp_event_id])
|> SimpleClientappEventQueries.simple_clientapp_event_query()
|> Repo.one()
end

@doc """
Creates a simple_clientapp_event.
## Examples
iex> create_simple_clientapp_event(%{field: value})
{:ok, %SimpleClientappEvent{}}
iex> create_simple_clientapp_event(%{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
@spec create_simple_clientapp_event(map) :: {:ok, SimpleClientappEvent.t()} | {:error, Ecto.Changeset.t()}
def create_simple_clientapp_event(attrs) do
%SimpleClientappEvent{}
|> SimpleClientappEvent.changeset(attrs)
|> Repo.insert()
end

@doc """
Updates a simple_clientapp_event.
## Examples
iex> update_simple_clientapp_event(simple_clientapp_event, %{field: new_value})
{:ok, %SimpleClientappEvent{}}
iex> update_simple_clientapp_event(simple_clientapp_event, %{field: bad_value})
{:error, %Ecto.Changeset{}}
"""
@spec update_simple_clientapp_event(SimpleClientappEvent.t(), map) ::
{:ok, SimpleClientappEvent.t()} | {:error, Ecto.Changeset.t()}
def update_simple_clientapp_event(%SimpleClientappEvent{} = simple_clientapp_event, attrs) do
simple_clientapp_event
|> SimpleClientappEvent.changeset(attrs)
|> Repo.update()
end

@doc """
Deletes a simple_clientapp_event.
## Examples
iex> delete_simple_clientapp_event(simple_clientapp_event)
{:ok, %SimpleClientappEvent{}}
iex> delete_simple_clientapp_event(simple_clientapp_event)
{:error, %Ecto.Changeset{}}
"""
@spec delete_simple_clientapp_event(SimpleClientappEvent.t()) :: {:ok, SimpleClientappEvent.t()} | {:error, Ecto.Changeset.t()}
def delete_simple_clientapp_event(%SimpleClientappEvent{} = simple_clientapp_event) do
Repo.delete(simple_clientapp_event)
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking simple_clientapp_event changes.
## Examples
iex> change_simple_clientapp_event(simple_clientapp_event)
%Ecto.Changeset{data: %SimpleClientappEvent{}}
"""
@spec change_simple_clientapp_event(SimpleClientappEvent.t(), map) :: Ecto.Changeset.t()
def change_simple_clientapp_event(%SimpleClientappEvent{} = simple_clientapp_event, attrs \\ %{}) do
SimpleClientappEvent.changeset(simple_clientapp_event, attrs)
end
end
6 changes: 6 additions & 0 deletions lib/angen/telemetry/queries/event_type_queries.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ defmodule Angen.Telemetry.EventTypeQueries do
)
end

def _where(query, :category, category) do
from(event_types in query,
where: event_types.category == ^category
)
end

@spec do_order_by(Ecto.Query.t(), list | nil) :: Ecto.Query.t()
defp do_order_by(query, nil), do: query

Expand Down
Loading

0 comments on commit e089e3d

Please sign in to comment.