2

I have a Phoenix repository that other engineers clone when creating a new app.

I have the following in the prod.exs

config :foo, Foo.Repo,
  adapter: Ecto.Adapters.Postgres,
  url: {:system, "DATABASE_URL"},
  pool_size: 1

The engineer normally deploys the Phoenix server to production before its database is set up. The engineer will set up the database within a few days, but in the meantime my problem is that this generates a huge volume of log messages which my logging system has trouble handling.

Here is the log message.

15:48:29.496 [error] GenServer #PID<0.20959.1> terminating
** (KeyError) key :database not found in: [hostname: "localhost", username: "foo", types: Ecto.Adapters.Postgres.TypeModule, port: 5432, name: Foo.Repo.Pool, otp_app: :foo, repo: Foo.Repo, adapter: Ecto.Adapters.Postgres, pool_size: 1, pool_timeout: 5000, timeout: 15000, adapter: Ecto.Adapters.Postgres, url: {:system, "DATABASE_URL"}, pool_size: 1, pool: DBConnection.Poolboy]
    (elixir) lib/keyword.ex:333: Keyword.fetch!/2
    (postgrex) lib/postgrex/protocol.ex:76: Postgrex.Protocol.connect/1
    (db_connection) lib/db_connection/connection.ex:134: DBConnection.Connection.connect/2
    (connection) lib/connection.ex:622: Connection.enter_connect/5
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
15:48:29.496 [error] GenServer #PID<0.20960.1> terminating
** (KeyError) key :database not found in: [hostname: "localhost", username: "foo", types: Ecto.Adapters.Postgres.TypeModule, port: 5432, name: Foo.Repo.Pool, otp_app: :foo, repo: Foo.Repo, adapter: Ecto.Adapters.Postgres, pool_size: 1, pool_timeout: 5000, timeout: 15000, adapter: Ecto.Adapters.Postgres, url: {:system, "DATABASE_URL"}, pool_size: 1, pool: DBConnection.Poolboy]
    (elixir) lib/keyword.ex:333: Keyword.fetch!/2
    (postgrex) lib/postgrex/protocol.ex:76: Postgrex.Protocol.connect/1
    (db_connection) lib/db_connection/connection.ex:134: DBConnection.Connection.connect/2
    (connection) lib/connection.ex:622: Connection.enter_connect/5
    (stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
15:48:29.497 [error] GenServer #PID<0.20961.1> terminating

I know how to fix the error, but it is the engineer's responsibility to eventually set the DATABASE_URL environment variable. I can only modify the Phoenix app template repository that the engineer clones at the start.

Is there some way to modify prod.exs so that an app without a DATABASE_URL set doesn't generate tons of logs?

Jesse Shieh
  • 4,660
  • 5
  • 34
  • 49
  • I have no idea if this is related, but my best guess is that this happens because max_restart is set to 0 here: https://github.com/elixir-ecto/db_connection/blob/d0cbabaa0eacd67d3b4cdaa84e2c3082c500f8ac/lib/db_connection/ownership/pool.ex#L11 – Jesse Shieh Jun 26 '17 at 23:07
  • Or maybe it's this where backoff_type is set to :stop. https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/adapters/postgres.ex#L218 – Jesse Shieh Jun 26 '17 at 23:21

2 Answers2

0

this generates a huge volume of log messages which my logging system has trouble handling

In my understanding, this is the biggest problem. You probably need to set logrotate up to make the logging system robust, otherwise, sooner or later you’ll run into issues. Erlang might be quite verbose sometimes.

I can only modify the Phoenix app template repository

Suppressing logs is not the desired task and I doubt Erlang has tools to screw logging up built in. I would suggest you use LoggerFileBackend with the following configuration:

config :logger,
  format: "$date $time [$level] $message\n",
  backends: [
    {LoggerFileBackend, :stub}
  ]

config :logger, :stub,
  path: "/dev/null",
  level: :info

And as soon as the database is delivered, you might redeploy the application with normal log settings.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • This would work, but since I have no control over the app after the template is cloned, I'd have to ask the engineer to make this modification. If possible I'd prefer to make their life simpler by providing as much out of the box as possible. – Jesse Shieh Jun 27 '17 at 11:02
0

Maybe add some handling for that case? Something like

database_url = System.get_env("DATABASE_URL")
if database_url do
  config :foo, Foo.Repo,
    adapter: Ecto.Adapters.Postgres,
    url: database_url,
    pool_size: 1
else
  # Maybe fail, maybe log an error, maybe have a dummy db?
end
stoodfarback
  • 1,299
  • 9
  • 12