statisticLogSrv.lua 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. -- 服务端埋点日志服务
  2. local skynet = require "skynet"
  3. local nodeMgr = require "nodeMgr"
  4. local baseService = require("baseService")
  5. local timeUtil = require "utils.timeUtil"
  6. local serverLogUtil = require "utils.serverLogUtil"
  7. local lib_game_redis = require("lib_game_redis")
  8. local moduleData = require("data.module")
  9. local SEND_COUNT, ACTIVE_SEND_COUNT
  10. if IS_TEST then
  11. SEND_COUNT, ACTIVE_SEND_COUNT = 1, 10
  12. else
  13. SEND_COUNT, ACTIVE_SEND_COUNT = 50, 100
  14. end
  15. local logQueue = {}
  16. local lTimerLogSync = nil -- 同步日志定时器
  17. local timeSync = 600 * 100
  18. local tabKeyFind = table.key_find
  19. local logAddr
  20. local function l_sned_logs_to_resource(logList)
  21. logAddr = logAddr or nodeMgr.query_node_service_addr("resource", ".server_log")
  22. nodeMgr.send("resource", logAddr, "writeLogList", logList)
  23. end
  24. -- 发送日志
  25. local function l_send_log(stop)
  26. -- 销毁定时器
  27. if lTimerLogSync then
  28. lTimerLogSync.delete()
  29. lTimerLogSync = nil
  30. end
  31. local count = 0
  32. if stop then
  33. count = #logQueue
  34. else
  35. count = math.min(SEND_COUNT, #logQueue)
  36. end
  37. local data = {}
  38. for i = 1, count do
  39. table.insert(data, table.remove(logQueue, 1))
  40. end
  41. if #data <= 0 then
  42. return
  43. end
  44. l_sned_logs_to_resource(data)
  45. end
  46. -- 同步日志
  47. local function l_sync_log_data()
  48. if #logQueue >= SEND_COUNT then
  49. l_send_log()
  50. else
  51. if lTimerLogSync == nil then
  52. lTimerLogSync = create_timeout(timeSync, l_send_log)
  53. end
  54. end
  55. end
  56. local function l_sync_active_log_data(filename, dataStr)
  57. l_sned_logs_to_resource({{filename = filename, dataStr = dataStr}})
  58. end
  59. local root = {}
  60. function root.add_file_log(filename, dataStr)
  61. table.insert(logQueue, {filename = filename, dataStr = dataStr})
  62. l_sync_log_data()
  63. end
  64. -- 活跃用户埋点
  65. local bagData = require("data.bag")
  66. local function l_log_user_active(uid, date)
  67. local lastLoginTime = timeUtil.toString(moduleData:hget_int(uid, "player", "lastLoginTime"))
  68. local mainProgress = ""
  69. do
  70. local maxChapterId = moduleData:hget_int(uid, "tb_pve_stars", "maxChapterId") or 1 --
  71. local passLevel = moduleData:hget_int(uid, "tb_pve_stars", "passLevel") or 0 --
  72. mainProgress = maxChapterId .. "-" .. passLevel
  73. end
  74. local data = {
  75. date,
  76. uid or 0,
  77. moduleData:get_channel(uid) or "", -- 渠道
  78. bagData:get_item_count(uid, 101), -- 金币持有量
  79. bagData:get_item_count(uid, 102), -- 钻石持有量
  80. lastLoginTime, -- 最后一次登录时间
  81. moduleData:get_nickname(uid)
  82. }
  83. return serverLogUtil.formatData(data)
  84. end
  85. -- 生成活跃用户日志(每日统计)
  86. local function l_log_day_before_active()
  87. local now = skynet_time()
  88. local logDate = timeUtil.toDate(now - 24 * 3600)
  89. local key = serverLogUtil.getActiveKey(logDate)
  90. local uidList = lib_game_redis:smembers(key)
  91. if is_empty(uidList) then
  92. return
  93. end
  94. log.warning("生成活跃用户日志 开始时间:%s", now)
  95. local filename = string.format("user-%s", logDate)
  96. local count, list = 0, {}
  97. for _, uid in ipairs(uidList) do
  98. count = count + 1
  99. local ok, actStr = pcall(l_log_user_active, tonumber(uid), logDate)
  100. if not ok then
  101. log.error("生成活跃用户日志error uid:%s err:%s", uid, actStr)
  102. else
  103. table.insert(list, actStr)
  104. end
  105. if count >= ACTIVE_SEND_COUNT then
  106. l_sync_active_log_data(filename, table.concat(list, "\n"))
  107. count, list = 0, {}
  108. skynet.sleep(10)
  109. end
  110. end
  111. if count > 0 then
  112. l_sync_active_log_data(filename, table.concat(list, "\n"))
  113. end
  114. log.error("生成活跃用户日志 结束时间:%s", skynet_time())
  115. -- 暂时先保存日志
  116. local newKey = string.format("%s:%s", "old", key)
  117. lib_game_redis:rename(key, newKey)
  118. end
  119. local function l_timer_next_day()
  120. -- 生成昨日活跃用户数据
  121. l_log_day_before_active()
  122. local now = skynet_time()
  123. local timeDiff = (timeUtil.getUnixtimeTomorrow() - now) + 60 -- 现在到第二天1分
  124. create_timeout(timeDiff * 100, l_timer_next_day)
  125. end
  126. function root.onStart()
  127. local nodename = skynet.getenv("nodeName")
  128. if nodename == "clientlog" then
  129. -- 每日 0 点在线统计
  130. l_timer_next_day()
  131. end
  132. end
  133. function root.onStop()
  134. l_send_log(true)
  135. end
  136. baseService.start(root, "statisticLog")