Counting connections to a Phoenix Channel

I was unable to find a quick Google answer to this question, so I thought I should post the “dirty” solution I found:

Realistically you can only count the subscribers to your local node unless there is some clever way for connected nodes to return their subscriber count, which I have not come across (This might be useless anyways as subscribers may have left by the time you get the count back). By default Phoenix stores the PIDs of any subscribers inside an ets table (I believe you can also use Redis). As a result we can just query the ets table directly. The naming convention for the table is APP_NAME.PubSub.Local0.

Ex:

:ets.info(ExometerPhoenixChannelDemo.PubSub.Local0)

returns

[read_concurrency: true, write_concurrency: true, compressed: false,
 memory: 1603, owner: #PID<0.285.0>, heir: :none,
 name: ExometerPhoenixChannelDemo.PubSub.Local0, size: 14, node: :nonode@nohost,
 named_table: true, type: :duplicate_bag, keypos: 1, protection: :public]

All you would need to do then is extract the size key to get a total.

More useful would be get the count of connections per Phoenix topic - this you can do with another ets function ets.foldl/3 which you need to pass a function. Here is an example function that will count all the subscribers per topic:

def count do
  acc = fn {channel, _}, map -> Map.update(map, channel, 1, &(&1 + 1)) end
  :ets.foldl(acc, %{}, ExometerPhoenixChannelDemo.PubSub.Local0)
end

This returns something akin to:

%{"phoenix:live_reload" => 2, "stats:erlang_memory_atom" => 2,
  "stats:erlang_memory_binary" => 2, "stats:erlang_memory_ets" => 2,
  "stats:erlang_memory_processes" => 2, "stats:erlang_memory_total" => 2,
  "stats:socket_connections_count" => 2}

You can see that I have two browsers open with a connection to each topic.

Please note: Cowboy times out web socket connections after 30 seconds if they no longer respond, so statistics are inaccurate for 30 seconds at a time.