-- 服务端埋点日志服务 local skynet = require "skynet" local nodeMgr = require "nodeMgr" local baseService = require("baseService") local timeUtil = require "utils.timeUtil" local serverLogUtil = require "utils.serverLogUtil" local lib_game_redis = require("lib_game_redis") local util_record_item = require("utils.util_record_item") local moduleData = require("data.module") local SEND_COUNT, ACTIVE_SEND_COUNT if IS_TEST then SEND_COUNT, ACTIVE_SEND_COUNT = 2, 10 else SEND_COUNT, ACTIVE_SEND_COUNT = 50, 100 end local logQueue = {} local lTimerLogSync = nil -- 同步日志定时器 local timeSync = 600 * 100 -- 资源变化日志 local itemList = {} local timerItem = nil local logAddr local function l_sned_logs_to_resource(logList) logAddr = logAddr or nodeMgr.query_node_service_addr("resource", ".server_log") nodeMgr.send("resource", logAddr, "writeLogList", logList) end -- 发送日志 local function l_send_log(stop) -- 销毁定时器 if lTimerLogSync then lTimerLogSync.delete() lTimerLogSync = nil end local count = 0 if stop then count = #logQueue else count = math.min(SEND_COUNT, #logQueue) end local data = {} for i = 1, count do table.insert(data, table.remove(logQueue, 1)) end if #data <= 0 then return end l_sned_logs_to_resource(data) end -- 同步日志 local function l_sync_log_data() if #logQueue >= SEND_COUNT then l_send_log() else if lTimerLogSync == nil then lTimerLogSync = create_timeout(timeSync, l_send_log) end end end -- 写入数据库 local function _write_to_db(stop) -- 销毁定时器 if timerItem then timerItem.delete() timerItem = nil end local count = 0 if stop then count = #itemList else count = math.min(SEND_COUNT, #itemList) end local list = {} for i = 1, count do table.insert(list, table.remove(itemList, 1)) end if #list <= 0 then return end util_record_item:add_item_record(list) if #itemList > 0 then if timerItem == nil then timerItem = create_timeout(timeSync, _write_to_db) end end end -- 同步资源日志 local function l_sync_item_data() if #itemList >= SEND_COUNT then _write_to_db() else if timerItem == nil then timerItem = create_timeout(timeSync, _write_to_db) end end end local function l_sync_active_log_data(filename, dataStr) l_sned_logs_to_resource({{filename = filename, dataStr = dataStr}}) end local root = {} function root.add_file_log(key, date, cnt) local filename = string.format("%s-%s", key, date) table.insert(logQueue, {filename = filename, dataStr = cnt}) l_sync_log_data() -- 资源变化 if key == "resource" then table.insert(itemList, cnt) l_sync_item_data() end end -- 活跃用户埋点 local bagData = require("data.bag") local function l_log_user_active(uid, date) local lastLoginTime = timeUtil.toString(moduleData:hget_int(uid, "player", "lastLoginTime")) local data = { date, uid or 0, moduleData:get_channel(uid) or "", -- 渠道 bagData:get_item_count(uid, 101), -- 金币持有量 bagData:get_item_count(uid, 102), -- 钻石持有量 lastLoginTime, -- 最后一次登录时间 moduleData:get_nickname(uid) } return serverLogUtil.formatData(data) end -- 生成活跃用户日志(每日统计) local function l_log_day_before_active() local now = skynet_time() local logDate = timeUtil.toDate(now - 24 * 3600) local key = serverLogUtil.getActiveKey(logDate) local uidList = lib_game_redis:smembers(key) if is_empty(uidList) then return end log.warning("生成活跃用户日志 开始时间:%s", now) local filename = string.format("user-%s", logDate) local count, list = 0, {} for _, uid in ipairs(uidList) do count = count + 1 local ok, actStr = pcall(l_log_user_active, tonumber(uid), logDate) if not ok then log.error("生成活跃用户日志error uid:%s err:%s", uid, actStr) else table.insert(list, actStr) end if count >= ACTIVE_SEND_COUNT then l_sync_active_log_data(filename, table.concat(list, "\n")) count, list = 0, {} skynet.sleep(10) end end if count > 0 then l_sync_active_log_data(filename, table.concat(list, "\n")) end log.error("生成活跃用户日志 结束时间:%s", skynet_time()) -- 暂时先保存日志 local newKey = string.format("%s:%s", "old", key) lib_game_redis:rename(key, newKey) end local function l_timer_next_day() -- 生成昨日活跃用户数据 l_log_day_before_active() local now = skynet_time() local timeDiff = (timeUtil.getUnixtimeTomorrow() - now) + 60 -- 现在到第二天1分 create_timeout(timeDiff * 100, l_timer_next_day) end function root.onStart() local nodename = skynet.getenv("nodeName") if nodename == "clientlog" then -- 每日 0 点在线统计 l_timer_next_day() end end function root.onStop() l_send_log(true) end baseService.start(root, "statisticLog")