Is it possible to have multiple log files with custom file names?

Hi,

This is my very first post now that I am a very happy elixir user. :slight_smile:

I am currently using logger_file_backend to log events in my game server. Is it possible for me to have logs grouped (in my case, per game) in to multiple files? For example, game_0001.log, game_0002.log, and so on.

Thank you in advance !

Here is my current logging configuration:

config :logger, :analytics,
  path: "var/log/analytics.log",
  level: :info,
  utc_log: true,
  format: "$date $time $metadata[$level] $message\n",
  metadata: [:event_type]
2 Likes

Doesn’t look like the logger_file_backend supports path patterns.

You can possibly copy/fork it on your own project (it’s only 1 file: https://github.com/onkel-dirtus/logger_file_backend/blob/master/lib/logger_file_backend.ex) and grab the current game ID from the metadata then use it to choose the output path.

4 Likes

Thanks for also checking it out !

I solved it just now by using logger_file_backend’s runtime configuration.

Basically, in the event that a game is created, I configure logging dynamically by doing the following:

    Logger.add_backend {LoggerFileBackend, String.to_atom("game_#{game_id}")}
    Logger.configure_backend {LoggerFileBackend, String.to_atom("game_#{game_id}")},
      path: "var/log/game_#{game_id}.log",
      level: :info,
      utc_log: true,
      format: "$date $time $metadata[$level] $message\n",
      metadata: [:game_id, :event_type],
      metadata_filter: [game_id: game_id]

Then I remove the backend when game ends.

Logger.remove_backend(String.to_atom("game_#{game_id}"))

Am I doing it right ?

BTW, Elixir is really awesome so far :yum:

2 Likes

For note, if this creates a new atom then you can exhaust the atom supply in the VM. It’s best to use existing hardcoded atoms only unless your game_id range is very tiny, I’d say keep it to a thousand or less to be safe, but honestly hardcoding them via compile-time generation is best I’d think, something like:

valid_game_ids = 0..1000
for game_id <- valid_game_ids do
  def get_game_atom(unquote(game_id)), do: unquote(:"game_#{game_id}")
end
def get_game_atom(game_id), do: throw {:invalid_game_id, game_id}
2 Likes