# HG changeset patch # User Matthew Wild # Date 1637156100 0 # Node ID 1132f2888cd20812b8561f5ea7173f5ea190fdb5 # Parent eb63890ae8fcad910253801035120352b57f3e4c mod_measure_active_users: Calculate active user counts over fixed time periods diff -r eb63890ae8fc -r 1132f2888cd2 mod_measure_active_users/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_measure_active_users/README.md Wed Nov 17 13:35:00 2021 +0000 @@ -0,0 +1,40 @@ +--- +labels: +- 'Stage-Alpha' +summary: 'Measure number of daily, weekly and monthly active users' +... + +Introduction +============ + +This module calculates the number of daily, weekly and monthly active users - +often abbreviated as DAU, WAU and MAU. + +These metrics are more accurate for determining how many people are actually +using a service. For example simply counting registered accounts will typically +include many dormant accounts that aren't really being used. Many servers also +track the number of connected users. This is a useful metric for many purposes, +but it is generally lower than the actual number of users - because some users +may only connect at certain times of day. + +The module defines "activity" as any login/logout event during the time period, +and for this it depends on mod_lastlog2 being loaded (it reads the data stored +by mod_lastlog2). Each individual user is only counted once. + +"Daily" means any event within the past 24 hours, "weekly" means within the +past 7 days, and "monthly" means within the past 30 days. + +Details +======= + +The user count is calculated shortly after startup, and then recalculated +hourly after that. + +Metrics are exported using Prosody's built-in statistics API. + +There is no configuration for this module. + +Compatibility +============= + +Requires Prosody 0.11 or later with mod_lastlog2 enabled. diff -r eb63890ae8fc -r 1132f2888cd2 mod_measure_active_users/mod_measure_active_users.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_measure_active_users/mod_measure_active_users.lua Wed Nov 17 13:35:00 2021 +0000 @@ -0,0 +1,47 @@ +local store = module:open_store("lastlog2"); + +local measure_d1 = module:measure("active_users_1d", "amount"); +local measure_d7 = module:measure("active_users_7d", "amount"); +local measure_d30 = module:measure("active_users_30d", "amount"); + +function update_calculations() + module:log("debug", "Calculating active users"); + local host_user_sessions = prosody.hosts[module.host].sessions; + local active_d1, active_d7, active_d30 = 0, 0, 0; + local now = os.time(); + for username in store:users() do + if host_user_sessions[username] then + -- Active now + active_d1, active_d7, active_d30 = + active_d1 + 1, active_d7 + 1, active_d30 + 1; + else + local lastlog_data = store:get(username); + if lastlog_data then + -- Due to server restarts/crashes/etc. some events + -- may not always get recorded, so we'll just take the + -- latest as a sign of last activity + local last_active = math.max( + lastlog_data.login and lastlog_data.login.timestamp or 0, + lastlog_data.logout and lastlog_data.logout.timestamp or 0 + ); + if now - last_active < 86400 then + active_d1 = active_d1 + 1; + end + if now - last_active < 86400*7 then + active_d7 = active_d7 + 1; + end + if now - last_active < 86400*30 then + active_d30 = active_d30 + 1; + end + end + end + end + module:log("debug", "Active users (took %ds): %d (24h), %d (7d), %d (30d)", os.time()-now, active_d1, active_d7, active_d30); + measure_d1(active_d1); + measure_d7(active_d7); + measure_d30(active_d30); + + return 3600 + (300*math.random()); +end + +module:add_timer(15, update_calculations);