-- ------------------------------------------------------------------------------ -- -- TradeSkillMaster -- -- https://tradeskillmaster.com -- -- All Rights Reserved - Detailed license information included with addon. -- -- ------------------------------------------------------------------------------ -- local _, TSM = ... local Analytics = TSM.Init("Util.Analytics") local Debug = TSM.Include("Util.Debug") local Log = TSM.Include("Util.Log") local private = { events = {}, lastEventTime = nil, argsTemp = {}, session = time(), sequenceNumber = 1, } local MAX_ANALYTICS_AGE = 14 * 24 * 60 * 60 -- 2 weeks local HIT_TYPE_IS_VALID = { AC = true, } -- ============================================================================ -- Module Functions -- ============================================================================ function Analytics.Action(name, ...) private.InsertHit("AC", name, ...) end function Analytics.Save(appDB) appDB.analytics = appDB.analytics or {updateTime=0, data={}} if private.lastEventTime then appDB.analytics.updateTime = private.lastEventTime end -- remove any events which are too old for i = #appDB.analytics.data, 1, -1 do local _, _, timeStr = strsplit(",", appDB.analytics.data[i]) local eventTime = (tonumber(timeStr) or 0) / 1000 if eventTime < time() - MAX_ANALYTICS_AGE then tremove(appDB.analytics.data, i) end end for _, event in ipairs(private.events) do tinsert(appDB.analytics.data, event) end end -- ============================================================================ -- Private Helper Functions -- ============================================================================ function private.InsertHit(hitType, ...) assert(HIT_TYPE_IS_VALID[hitType]) wipe(private.argsTemp) for i = 1, select("#", ...) do local arg = select(i, ...) local argType = type(arg) if argType == "string" then -- remove non-printable and non-ascii characters arg = gsub(arg, "[^ -~]", "") -- remove characters we don't want in the JSON arg = gsub(arg, "[\\\"]", "") arg = private.AddQuotes(arg) elseif argType == "number" then -- pass elseif argType == "boolean" then arg = tostring(arg) else error("Invalid arg type: "..argType) end tinsert(private.argsTemp, arg) end Log.Info("%s %s", hitType, strjoin(" ", tostringall(...))) hitType = private.AddQuotes(hitType) local version = private.AddQuotes(TSM.GetVersion() or "???") local timeMs = Debug.GetTimeMilliseconds() local jsonStr = strjoin(",", hitType, version, timeMs, private.session, private.sequenceNumber, unpack(private.argsTemp)) tinsert(private.events, "["..jsonStr.."]") private.sequenceNumber = private.sequenceNumber + 1 private.lastEventTime = time() end function private.AddQuotes(str) return "\""..str.."\"" end