com.amanotes.gdk 0.2.46 → 0.2.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/Editor/AmaGDKEditor.cs +281 -104
- package/Editor/MatchSDKVersion.cs +3 -6
- package/Editor/Utils/AmaGDKEditor.ExtractVersion.cs +5 -1
- package/Extra/AmaGDKInstaller.unitypackage +0 -0
- package/Extra/AmaGDKProject.unitypackage +0 -0
- package/Packages/AmaGDKConfig.unitypackage +0 -0
- package/Packages/AmaGDKExample.unitypackage +0 -0
- package/Packages/AmaGDKTest.unitypackage +0 -0
- package/Packages/AppsFlyerAdapter.unitypackage +0 -0
- package/Packages/{FirebaseRemoteConfigAdapter_v9.1.0.unitypackage.meta → AppsFlyerAdapter.unitypackage.meta} +1 -1
- package/Packages/FirebaseAnalyticsAdapter.unitypackage +0 -0
- package/Packages/{AppsFlyerAdapter_v6.5.4.unitypackage.meta → FirebaseAnalyticsAdapter.unitypackage.meta} +1 -1
- package/Packages/FirebaseRemoteConfigAdapter.unitypackage +0 -0
- package/Packages/{IronSourceAdapter_v7.5.2.unitypackage.meta → FirebaseRemoteConfigAdapter.unitypackage.meta} +1 -1
- package/Packages/IronSourceAdapter.unitypackage +0 -0
- package/Packages/{FirebaseAnalyticsAdapter_v9.1.0.unitypackage.meta → IronSourceAdapter.unitypackage.meta} +1 -1
- package/Packages/RevenueCatAdapter.unitypackage +0 -0
- package/Packages/RevenueCatAdapter.unitypackage.meta +7 -0
- package/Runtime/AmaGDK.Adapters.cs +55 -77
- package/Runtime/AmaGDK.Ads.cs +160 -174
- package/Runtime/AmaGDK.Analytics.cs +245 -125
- package/Runtime/AmaGDK.Config.cs +2 -1
- package/Runtime/AmaGDK.IAP.cs +47 -48
- package/Runtime/AmaGDK.RemoteConfig.cs +38 -35
- package/Runtime/AmaGDK.UserProfile.cs +27 -19
- package/Runtime/AmaGDK.cs +158 -111
- package/Runtime/Core.meta +8 -0
- package/Runtime/Internal/AmaGDK.Internal.AmaGUI.cs +8 -3
- package/Runtime/Internal/AmaGDK.Internal.SemVer.cs +21 -17
- package/Runtime/Internal/AmaGDK.Internal.cs +17 -6
- package/Runtime/Internal/AmaGDK.Utils.cs +78 -11
- package/package.json +1 -1
- package/Packages/AppsFlyerAdapter_v6.5.4.unitypackage +0 -0
- package/Packages/FirebaseAnalyticsAdapter_v9.1.0.unitypackage +0 -0
- package/Packages/FirebaseRemoteConfigAdapter_v9.1.0.unitypackage +0 -0
- package/Packages/IronSourceAdapter_v7.5.2.unitypackage +0 -0
- package/Packages/IronsourceAdapter_v7.2.6.unitypackage +0 -0
- package/Packages/IronsourceAdapter_v7.2.6.unitypackage.meta +0 -7
- package/Packages/RevenueCatAdapter_v6.0.0.unitypackage +0 -0
- package/Packages/RevenueCatAdapter_v6.0.0.unitypackage.meta +0 -7
|
@@ -1,29 +1,15 @@
|
|
|
1
1
|
using System;
|
|
2
2
|
using System.Collections.Generic;
|
|
3
3
|
using System.Text;
|
|
4
|
+
using System.Text.RegularExpressions;
|
|
4
5
|
using Amanotes.Core.Internal;
|
|
5
6
|
using UnityEngine;
|
|
7
|
+
using UnityEngine.Profiling;
|
|
6
8
|
using static Amanotes.Core.AmaGDK.Analytics;
|
|
7
9
|
using static Amanotes.Core.Internal.Logging;
|
|
8
10
|
|
|
9
11
|
namespace Amanotes.Core
|
|
10
12
|
{
|
|
11
|
-
[Serializable]
|
|
12
|
-
public class AnalyticsAdapterConfig
|
|
13
|
-
{
|
|
14
|
-
public bool SendEventByDefault;
|
|
15
|
-
|
|
16
|
-
public List<string> NeverSend;
|
|
17
|
-
public List<string> AlwaysSend;
|
|
18
|
-
|
|
19
|
-
public bool IsForbidden(string eventName)
|
|
20
|
-
{
|
|
21
|
-
return SendEventByDefault
|
|
22
|
-
? NeverSend.Contains(eventName)
|
|
23
|
-
: !AlwaysSend.Contains(eventName);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
13
|
partial class AmaGDK
|
|
28
14
|
{
|
|
29
15
|
//PUBLIC APIS
|
|
@@ -85,6 +71,11 @@ namespace Amanotes.Core
|
|
|
85
71
|
public static IEventParamsBuilder LogEvent(string eventName)
|
|
86
72
|
{
|
|
87
73
|
NormalizeEventName(ref eventName, true);
|
|
74
|
+
if (localData.GetEventDetail(eventName) == null && localData.eventDetails.Count >= 500)
|
|
75
|
+
{
|
|
76
|
+
LogWarning($" - You have reported 500 types of events. New event <{eventName}> will be ignored.");
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
88
79
|
var result = new EventParams(eventName);
|
|
89
80
|
eventQueue.Enqueue(result);
|
|
90
81
|
return result;
|
|
@@ -146,41 +137,45 @@ namespace Amanotes.Core
|
|
|
146
137
|
|
|
147
138
|
private static IntegrityFlag MergeData(List<string> funnelEvents, Dictionary<string, int> eventCountMap, bool sumEventCount)
|
|
148
139
|
{
|
|
140
|
+
Profiler.BeginSample("AmaGDK.Analytics.MergeData()");
|
|
149
141
|
var flag = IntegrityFlag.Ok;
|
|
150
142
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (localData.funnelSignatures.Contains(e)) continue;
|
|
154
|
-
|
|
155
|
-
flag |= IntegrityFlag.NewFunnel;
|
|
156
|
-
localData.AddFunnelSignature(e);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
foreach (KeyValuePair<string, int> e in eventCountMap)
|
|
160
|
-
{
|
|
161
|
-
EventDetail eventDetail = localData.GetEventDetail(e.Key);
|
|
162
|
-
if (eventDetail == null)
|
|
143
|
+
if (funnelEvents != null)
|
|
144
|
+
foreach (string e in funnelEvents)
|
|
163
145
|
{
|
|
164
|
-
localData.
|
|
165
|
-
{
|
|
166
|
-
eventName = e.Key,
|
|
167
|
-
totalCount = e.Value
|
|
168
|
-
});
|
|
169
|
-
flag |= IntegrityFlag.NewEvent;
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
146
|
+
if (localData.funnelSignatures.Contains(e)) continue;
|
|
172
147
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
flag |= IntegrityFlag.DifferentCount;
|
|
148
|
+
flag |= IntegrityFlag.NewFunnel;
|
|
149
|
+
localData.AddFunnelSignature(e);
|
|
176
150
|
}
|
|
177
151
|
|
|
178
|
-
|
|
152
|
+
if (eventCountMap != null)
|
|
153
|
+
foreach (KeyValuePair<string, int> e in eventCountMap)
|
|
179
154
|
{
|
|
180
|
-
eventDetail
|
|
181
|
-
|
|
182
|
-
|
|
155
|
+
EventDetail eventDetail = localData.GetEventDetail(e.Key);
|
|
156
|
+
if (eventDetail == null)
|
|
157
|
+
{
|
|
158
|
+
localData.eventDetails.Add(new EventDetail
|
|
159
|
+
{
|
|
160
|
+
eventName = e.Key,
|
|
161
|
+
totalCount = e.Value
|
|
162
|
+
});
|
|
163
|
+
flag |= IntegrityFlag.NewEvent;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (eventDetail.totalCount != e.Value)
|
|
168
|
+
{
|
|
169
|
+
flag |= IntegrityFlag.DifferentCount;
|
|
170
|
+
}
|
|
183
171
|
|
|
172
|
+
if (sumEventCount)
|
|
173
|
+
{
|
|
174
|
+
eventDetail.totalCount += e.Value;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
Profiler.EndSample();
|
|
184
179
|
return flag;
|
|
185
180
|
}
|
|
186
181
|
|
|
@@ -197,7 +192,7 @@ namespace Amanotes.Core
|
|
|
197
192
|
}
|
|
198
193
|
|
|
199
194
|
//Integrity check
|
|
200
|
-
if (!Config.
|
|
195
|
+
if (!Config.analytics.checkMigrationIntegrity) return;
|
|
201
196
|
|
|
202
197
|
// False: DO NOT UPDATE EXISTED COUNT VALUE BECAUSE WE DON'T HAVE
|
|
203
198
|
// ENOUGH INFORMATION TO DECIDE WHICH ONE IS MORE ACCURATE
|
|
@@ -211,11 +206,9 @@ namespace Amanotes.Core
|
|
|
211
206
|
{
|
|
212
207
|
foreach (string adapterID in adapterIDs)
|
|
213
208
|
{
|
|
214
|
-
|
|
209
|
+
AnalyticsAdapter adapter = listAdapters.Find(a => a.adapterId == adapterID);
|
|
215
210
|
if (adapter == null) continue;
|
|
216
|
-
|
|
217
|
-
var config = adapter.GetAdapterConfig<AnalyticsAdapterConfig>();
|
|
218
|
-
config.AlwaysSend = eventNames;
|
|
211
|
+
adapter.AlwaysSend = eventNames;
|
|
219
212
|
}
|
|
220
213
|
}
|
|
221
214
|
|
|
@@ -223,11 +216,9 @@ namespace Amanotes.Core
|
|
|
223
216
|
{
|
|
224
217
|
foreach (string adapterID in adapterIDs)
|
|
225
218
|
{
|
|
226
|
-
|
|
219
|
+
AnalyticsAdapter adapter = listAdapters.Find(a => a.adapterId == adapterID);
|
|
227
220
|
if (adapter == null) continue;
|
|
228
|
-
|
|
229
|
-
var config = adapter.GetAdapterConfig<AnalyticsAdapterConfig>();
|
|
230
|
-
config.NeverSend = eventNames;
|
|
221
|
+
adapter.NeverSend = eventNames;
|
|
231
222
|
}
|
|
232
223
|
}
|
|
233
224
|
}
|
|
@@ -244,33 +235,78 @@ namespace Amanotes.Core
|
|
|
244
235
|
}
|
|
245
236
|
|
|
246
237
|
internal static readonly Dictionary<string, EventConfig> sendAtCount = new Dictionary<string, EventConfig>();
|
|
247
|
-
internal static Predicate<EventParams> logEventHook
|
|
238
|
+
internal static Predicate<EventParams> logEventHook;
|
|
248
239
|
internal static readonly Queue<EventParams> eventQueue = new Queue<EventParams>();
|
|
249
240
|
internal static readonly Queue<Action> actionQueue = new Queue<Action>();
|
|
250
|
-
internal static readonly List<
|
|
241
|
+
internal static readonly List<AnalyticsAdapter> listAdapters = new List<AnalyticsAdapter>();
|
|
251
242
|
internal static readonly AnalyticsData localData = new AnalyticsData().LoadJsonFromFile();
|
|
252
243
|
internal static readonly SessionStat sessionStat = new SessionStat();
|
|
253
|
-
internal static
|
|
254
|
-
|
|
255
|
-
|
|
244
|
+
internal static AnalyticsAdapter primaryAdapter;
|
|
245
|
+
internal static readonly HashSet<string> blackListPrefixes = new HashSet<string>() {
|
|
246
|
+
"firebase_", "google_", "ga_"
|
|
247
|
+
};
|
|
248
|
+
internal static readonly HashSet<string> blackListEvents = new HashSet<string>()
|
|
249
|
+
{
|
|
250
|
+
"ad_activeview",
|
|
251
|
+
"ad_click",
|
|
252
|
+
"ad_exposure",
|
|
253
|
+
"ad_query",
|
|
254
|
+
"ad_reward",
|
|
255
|
+
"adunit_exposure",
|
|
256
|
+
"app_background",
|
|
257
|
+
"app_clear_data",
|
|
258
|
+
"app_exception",
|
|
259
|
+
"app_remove",
|
|
260
|
+
"app_store_refund",
|
|
261
|
+
"app_store_subscription_cancel",
|
|
262
|
+
"app_store_subscription_convert",
|
|
263
|
+
"app_store_subscription_renew",
|
|
264
|
+
"app_update",
|
|
265
|
+
"app_upgrade",
|
|
266
|
+
"dynamic_link_app_open",
|
|
267
|
+
"dynamic_link_app_update",
|
|
268
|
+
"dynamic_link_first_open",
|
|
269
|
+
"error",
|
|
270
|
+
"first_open",
|
|
271
|
+
"first_visit",
|
|
272
|
+
"in_app_purchase",
|
|
273
|
+
"notification_dismiss",
|
|
274
|
+
"notification_foreground",
|
|
275
|
+
"notification_open",
|
|
276
|
+
"notification_receive",
|
|
277
|
+
"os_update",
|
|
278
|
+
"session_start",
|
|
279
|
+
"session_start_with_rollout",
|
|
280
|
+
"user_engagement"
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
internal static void InitModule()
|
|
256
284
|
{
|
|
257
285
|
listAdapters.Clear();
|
|
258
|
-
listAdapters.AddRange(
|
|
286
|
+
listAdapters.AddRange(Adapter2.GetAllAdapter<AnalyticsAdapter>());
|
|
259
287
|
if (listAdapters.Count != 0)
|
|
260
288
|
primaryAdapter = listAdapters.Find(a => a.adapterId == AdapterID.FIREBASE_ANALYTICS) ?? listAdapters[0];
|
|
289
|
+
}
|
|
261
290
|
|
|
291
|
+
internal static void StartModule()
|
|
292
|
+
{
|
|
293
|
+
// All adapters should be ready now!
|
|
294
|
+
|
|
295
|
+
// TODO: Refactor Resolve Early Calls
|
|
262
296
|
onFrameUpdate -= ProcessEventQueue;
|
|
263
297
|
onFrameUpdate += ProcessEventQueue;
|
|
264
298
|
|
|
265
299
|
onFrameUpdate -= ProcessActionQueue;
|
|
266
300
|
onFrameUpdate += ProcessActionQueue;
|
|
267
301
|
}
|
|
268
|
-
|
|
302
|
+
|
|
269
303
|
internal static void ProcessEventQueue()
|
|
270
304
|
{
|
|
271
305
|
if (eventQueue.Count <= 0) return;
|
|
272
|
-
|
|
273
|
-
|
|
306
|
+
|
|
307
|
+
Profiler.BeginSample("AmaGDK.Analytics.ProcessEventQueue()");
|
|
308
|
+
AnalyticsConfig config = Config.analytics;
|
|
309
|
+
bool showAnalyticsLog = config.showAnalyticsLog;
|
|
274
310
|
sessionStat.ClearLastFrameEventInfo();
|
|
275
311
|
|
|
276
312
|
while (eventQueue.Count > 0)
|
|
@@ -279,27 +315,25 @@ namespace Amanotes.Core
|
|
|
279
315
|
if (!ShouldSendEvent(eventData)) continue;
|
|
280
316
|
|
|
281
317
|
var (countInSession, totalCount) = localData.IncreaseCounter(eventData);
|
|
282
|
-
if (eventData.accumulated)
|
|
318
|
+
if (eventData.accumulated || eventData.parameters.ContainsKey("accumulated_count"))
|
|
283
319
|
{
|
|
284
|
-
eventData
|
|
320
|
+
UpdateAccumulatedCount(eventData, countInSession, totalCount);
|
|
285
321
|
}
|
|
286
322
|
|
|
287
323
|
eventData.AddParam("ama_device_id", User.AmaDeviceId);
|
|
288
|
-
|
|
324
|
+
|
|
289
325
|
string eventNameToSend = GetEventNameToSend(eventData.eventName, countInSession, totalCount);
|
|
290
|
-
if (
|
|
326
|
+
if (config.normalizeEventName) NormalizeEventName(ref eventNameToSend);
|
|
291
327
|
|
|
292
328
|
if (showAnalyticsLog) Debug.Log($"AmaGDK | [Analytics] Event <{eventNameToSend}> (in session: {countInSession}, total: {totalCount})\n{JsonUtils.DictionaryToJson(eventData.parameters, true)}");
|
|
293
329
|
|
|
294
|
-
|
|
330
|
+
config.quality.CheckEventQuality(eventData.eventName, eventData.parameters);
|
|
295
331
|
|
|
296
332
|
var inUseAdapterIDs = new List<string>();
|
|
297
|
-
foreach (
|
|
333
|
+
foreach (AnalyticsAdapter m in listAdapters)
|
|
298
334
|
{
|
|
299
335
|
if (IsAdapterForbidden(m, eventData)) continue;
|
|
300
|
-
|
|
301
|
-
var api = m.GetAdapterApi<IAnalyticAdapter>();
|
|
302
|
-
api.LogEvent(eventNameToSend, eventData.parameters);
|
|
336
|
+
m.LogEvent(eventNameToSend, eventData.parameters);
|
|
303
337
|
inUseAdapterIDs.Add(m.adapterId);
|
|
304
338
|
}
|
|
305
339
|
sessionStat.Add(eventNameToSend, eventData, inUseAdapterIDs);
|
|
@@ -307,24 +341,45 @@ namespace Amanotes.Core
|
|
|
307
341
|
|
|
308
342
|
localData.SaveIfDirty();
|
|
309
343
|
sessionStat.Save();
|
|
344
|
+
Profiler.EndSample();
|
|
310
345
|
}
|
|
311
346
|
|
|
312
|
-
internal static
|
|
347
|
+
internal static void UpdateAccumulatedCount(EventParams eventData, int countInSession, int totalCount)
|
|
313
348
|
{
|
|
314
|
-
|
|
315
|
-
var
|
|
349
|
+
var ACCUMULATED_COUNT = "accumulated_count";
|
|
350
|
+
var countByGDK = eventData.withinSession ? countInSession : totalCount;
|
|
316
351
|
|
|
352
|
+
if (!eventData.parameters.ContainsKey(ACCUMULATED_COUNT))
|
|
353
|
+
{
|
|
354
|
+
eventData.AddParam(ACCUMULATED_COUNT, countByGDK);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
int.TryParse(eventData.parameters[ACCUMULATED_COUNT].ToString(), out int oriAccCount);
|
|
359
|
+
if (oriAccCount == countByGDK)
|
|
360
|
+
{
|
|
361
|
+
eventData.AddParam(ACCUMULATED_COUNT, countByGDK);
|
|
362
|
+
}
|
|
363
|
+
else
|
|
364
|
+
{
|
|
365
|
+
LogWarning($"[Analytics] event <{eventData.eventName}> has difference in accumulated count. Original count: {oriAccCount}. AmaGDK count: {countByGDK}");
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
internal static bool IsAdapterForbidden(AnalyticsAdapter adapter, EventParams eventData)
|
|
370
|
+
{
|
|
371
|
+
if (adapter == null) return false;
|
|
317
372
|
if (eventData.overrideConfig)
|
|
318
373
|
{
|
|
319
374
|
// IMPORTANT NOTE:
|
|
320
375
|
//
|
|
321
376
|
// Once set overrideConfig, we should skip the adapter config completely!!!
|
|
322
377
|
//
|
|
323
|
-
if (eventData.IsAdapterForbidden(
|
|
378
|
+
if (eventData.IsAdapterForbidden(adapter.adapterId)) return true;
|
|
324
379
|
}
|
|
325
380
|
else // Do not remove else
|
|
326
381
|
{
|
|
327
|
-
if (
|
|
382
|
+
if (adapter.IsForbidden(eventData.eventName)) return true;
|
|
328
383
|
}
|
|
329
384
|
|
|
330
385
|
return false;
|
|
@@ -338,36 +393,70 @@ namespace Amanotes.Core
|
|
|
338
393
|
return $"{eventName}_{(config.withinSession ? countInSession : totalCount).ToString(config.numberFormat)}";
|
|
339
394
|
}
|
|
340
395
|
|
|
396
|
+
//https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Event
|
|
341
397
|
internal static void NormalizeEventName(ref string eventName, bool dryRun = false)
|
|
342
398
|
{
|
|
343
|
-
|
|
344
|
-
sb.Clear();
|
|
345
|
-
|
|
346
|
-
if (string.IsNullOrEmpty(eventName))
|
|
399
|
+
Profiler.BeginSample("AmaGDK.Analytics.NormalizeEventName()");
|
|
347
400
|
{
|
|
348
|
-
sb
|
|
349
|
-
|
|
401
|
+
StringBuilder sb = tmpWarningSB;
|
|
402
|
+
sb.Clear();
|
|
403
|
+
NormalizeKeyString(ref eventName, sb, dryRun);
|
|
404
|
+
if (blackListEvents.Contains(eventName))
|
|
405
|
+
sb.AppendLine($" - EventName <{eventName}> is reserved and should not be used");
|
|
406
|
+
if (sb.Length > 0 && dryRun) LogWarningOnce($"Warning for event name <{eventName}>:\n{sb}", $"NormalizeEventName<{eventName}>");
|
|
350
407
|
}
|
|
408
|
+
Profiler.EndSample();
|
|
409
|
+
}
|
|
351
410
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
if (eventName != normalizedEventName)
|
|
411
|
+
internal static void NormalizeKeyString(ref string key, StringBuilder warningLog, bool dryRun = false)
|
|
412
|
+
{
|
|
413
|
+
Profiler.BeginSample("AmaGDK.Analytics.NormalizeEventName()");
|
|
357
414
|
{
|
|
358
|
-
if (
|
|
415
|
+
if (string.IsNullOrWhiteSpace(key))
|
|
359
416
|
{
|
|
360
|
-
|
|
417
|
+
LogWarning($" - Name should not be empty");
|
|
418
|
+
Profiler.EndSample();
|
|
419
|
+
return;
|
|
361
420
|
}
|
|
362
|
-
|
|
421
|
+
|
|
422
|
+
string normalizedString = key.Trim()
|
|
423
|
+
.Replace(' ', '_')
|
|
424
|
+
.Replace('-', '_');
|
|
425
|
+
|
|
426
|
+
if (key != normalizedString)
|
|
427
|
+
{
|
|
428
|
+
if (!dryRun)
|
|
429
|
+
{
|
|
430
|
+
key = normalizedString;
|
|
431
|
+
} else
|
|
432
|
+
{
|
|
433
|
+
warningLog.AppendLine($" - Malformed name (should not contains <space> or <dash>): <{key}>");
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
var r = new Regex("^[a-zA-Z0-9_]*$");
|
|
438
|
+
if (!r.IsMatch(normalizedString))
|
|
439
|
+
{
|
|
440
|
+
warningLog.AppendLine($" - Name may only contain alphanumeric characters and underscores");
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (!char.IsLetter(key[0]))
|
|
363
444
|
{
|
|
364
|
-
|
|
445
|
+
warningLog.AppendLine($" - Name must start with a letter: <{key}> ");
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
foreach (var prefix in blackListPrefixes)
|
|
449
|
+
{
|
|
450
|
+
if (!normalizedString.StartsWith(prefix)) continue;
|
|
451
|
+
warningLog.AppendLine($" - <{key}> starts with reserved prefix <{prefix}>");
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (key.Length > 40)
|
|
455
|
+
{
|
|
456
|
+
warningLog.AppendLine($" - Name is too long ({key.Length} > 40): <{key}> ");
|
|
365
457
|
}
|
|
366
458
|
}
|
|
367
|
-
|
|
368
|
-
if (!char.IsLetter(eventName[0])) sb.AppendLine($" - EventName must start with a letter: <{eventName}> ");
|
|
369
|
-
if (eventName.Length > 40) sb.AppendLine($" - EventName is too long ({eventName.Length} > 40): <{eventName}> ");
|
|
370
|
-
if (sb.Length > 0 && dryRun) LogWarningOnce(sb.ToString(), $"NormalizeEventName<{eventName}>");
|
|
459
|
+
Profiler.EndSample();
|
|
371
460
|
}
|
|
372
461
|
|
|
373
462
|
internal static bool ShouldSendEvent(EventParams eventData)
|
|
@@ -387,7 +476,7 @@ namespace Amanotes.Core
|
|
|
387
476
|
//Check the rule to log event
|
|
388
477
|
if (logEventHook != null)
|
|
389
478
|
{
|
|
390
|
-
|
|
479
|
+
// localData.GetEventDetail(eventData.eventName, true);
|
|
391
480
|
return logEventHook(eventData);
|
|
392
481
|
}
|
|
393
482
|
|
|
@@ -407,17 +496,17 @@ namespace Amanotes.Core
|
|
|
407
496
|
|
|
408
497
|
internal static void InternalSetUserId(string userId)
|
|
409
498
|
{
|
|
410
|
-
foreach (
|
|
499
|
+
foreach (AnalyticsAdapter s in listAdapters)
|
|
411
500
|
{
|
|
412
|
-
s.
|
|
501
|
+
s.SetUserId(userId);
|
|
413
502
|
}
|
|
414
503
|
}
|
|
415
504
|
|
|
416
505
|
internal static void InternalSetUserProperty(string key, string value)
|
|
417
506
|
{
|
|
418
|
-
foreach (
|
|
507
|
+
foreach (AnalyticsAdapter s in listAdapters)
|
|
419
508
|
{
|
|
420
|
-
s.
|
|
509
|
+
s.SetUserProperty(key, value);
|
|
421
510
|
}
|
|
422
511
|
}
|
|
423
512
|
}
|
|
@@ -486,7 +575,6 @@ namespace Amanotes.Core
|
|
|
486
575
|
[Serializable]
|
|
487
576
|
internal class AnalyticsData : IJsonFile
|
|
488
577
|
{
|
|
489
|
-
|
|
490
578
|
public List<string> funnelSignatures = new List<string>();
|
|
491
579
|
public List<EventDetail> eventDetails = new List<EventDetail>();
|
|
492
580
|
public MigrationLog migrationLog = new MigrationLog();
|
|
@@ -561,7 +649,6 @@ namespace Amanotes.Core
|
|
|
561
649
|
|
|
562
650
|
internal class SessionStat
|
|
563
651
|
{
|
|
564
|
-
|
|
565
652
|
private const string TSV_HEADER_ROW = "EventName\tAdapters\tParameters";
|
|
566
653
|
private readonly string fileName = nameof(SessionStat) + DateTime.Now.ToString("_yyMMdd_HHmmss") + ".tsv";
|
|
567
654
|
private StringBuilder contents = new StringBuilder();
|
|
@@ -581,7 +668,7 @@ namespace Amanotes.Core
|
|
|
581
668
|
|
|
582
669
|
internal void Save()
|
|
583
670
|
{
|
|
584
|
-
if (!Config.
|
|
671
|
+
if (!Config.analytics.enableEventStat || lastFrameEventStats.Count == 0) return;
|
|
585
672
|
|
|
586
673
|
contents.Clear();
|
|
587
674
|
if (isFirstSave)
|
|
@@ -607,7 +694,7 @@ namespace Amanotes.Core
|
|
|
607
694
|
if (ap == null) return null;
|
|
608
695
|
|
|
609
696
|
var data = ap as EventParams;
|
|
610
|
-
data
|
|
697
|
+
data!.funnelSignature = string.IsNullOrEmpty(signature) ? data.eventName : signature;
|
|
611
698
|
return ap;
|
|
612
699
|
}
|
|
613
700
|
|
|
@@ -616,7 +703,7 @@ namespace Amanotes.Core
|
|
|
616
703
|
if (ap == null) return null;
|
|
617
704
|
|
|
618
705
|
var data = ap as EventParams;
|
|
619
|
-
data
|
|
706
|
+
data!.accumulated = true;
|
|
620
707
|
data.withinSession = withinSession;
|
|
621
708
|
return ap;
|
|
622
709
|
}
|
|
@@ -631,7 +718,7 @@ namespace Amanotes.Core
|
|
|
631
718
|
}
|
|
632
719
|
|
|
633
720
|
var eventData = ap as EventParams;
|
|
634
|
-
if (eventData
|
|
721
|
+
if (eventData!.overrideConfig)
|
|
635
722
|
{
|
|
636
723
|
LogWarning("Except() can only be set once!");
|
|
637
724
|
return ap;
|
|
@@ -655,7 +742,7 @@ namespace Amanotes.Core
|
|
|
655
742
|
}
|
|
656
743
|
|
|
657
744
|
var eventData = ap as EventParams;
|
|
658
|
-
if (eventData
|
|
745
|
+
if (eventData!.overrideConfig)
|
|
659
746
|
{
|
|
660
747
|
LogWarning("OnlyTo() can only be set once!");
|
|
661
748
|
return ap;
|
|
@@ -674,14 +761,22 @@ namespace Amanotes.Core
|
|
|
674
761
|
if (ap == null) return null;
|
|
675
762
|
if (!IsValidKeyValue(ap, key, value)) return ap;
|
|
676
763
|
|
|
677
|
-
|
|
678
|
-
|
|
764
|
+
var eventParams = ap as EventParams;
|
|
765
|
+
Dictionary<string, object> parameters = eventParams?.parameters;
|
|
766
|
+
if (parameters == null)
|
|
767
|
+
return ap;
|
|
768
|
+
if (parameters.ContainsKey(key))
|
|
679
769
|
{
|
|
680
|
-
LogWarning($"Duplicated key: {key}!");
|
|
770
|
+
LogWarning($"Duplicated key: {key}. Event name: {eventParams.eventName}!");
|
|
771
|
+
return ap;
|
|
772
|
+
}
|
|
773
|
+
if (parameters.Count >= 25)
|
|
774
|
+
{
|
|
775
|
+
LogWarning($"Exceeded key: {key}. Event name: {eventParams.eventName}!");
|
|
681
776
|
return ap;
|
|
682
777
|
}
|
|
683
778
|
|
|
684
|
-
parameters
|
|
779
|
+
parameters.Add(key, value);
|
|
685
780
|
return ap;
|
|
686
781
|
}
|
|
687
782
|
|
|
@@ -707,7 +802,7 @@ namespace Amanotes.Core
|
|
|
707
802
|
if (ap == null) return null;
|
|
708
803
|
if (parameters.Length == 0)
|
|
709
804
|
{
|
|
710
|
-
LogWarning($"Param tuple is null. Event name: {(ap as EventParams)
|
|
805
|
+
LogWarning($"Param tuple is null. Event name: {(ap as EventParams)?.eventName}!");
|
|
711
806
|
return ap;
|
|
712
807
|
}
|
|
713
808
|
|
|
@@ -719,9 +814,16 @@ namespace Amanotes.Core
|
|
|
719
814
|
return ap;
|
|
720
815
|
}
|
|
721
816
|
|
|
817
|
+
//https://firebase.google.com/docs/reference/android/com/google/firebase/analytics/FirebaseAnalytics.Param
|
|
722
818
|
private static bool IsValidKeyValue(IEventParamsBuilder ap, string key, object value)
|
|
723
819
|
{
|
|
724
820
|
string eventName = (ap as EventParams)?.eventName;
|
|
821
|
+
|
|
822
|
+
StringBuilder sb = tmpWarningSB;
|
|
823
|
+
sb.Clear();
|
|
824
|
+
NormalizeKeyString(ref key, sb);
|
|
825
|
+
if (sb.Length > 0) LogWarningOnce($"Warning for event <{eventName}>, param <{key}>:\n{sb}", $"NormalizeParamKey<{eventName}>");
|
|
826
|
+
|
|
725
827
|
if (string.IsNullOrWhiteSpace(key))
|
|
726
828
|
{
|
|
727
829
|
LogWarning($"Param key is empty. Event name: {eventName}!");
|
|
@@ -740,10 +842,20 @@ namespace Amanotes.Core
|
|
|
740
842
|
|
|
741
843
|
namespace Amanotes.Core.Internal
|
|
742
844
|
{
|
|
845
|
+
[Serializable] public class AnalyticsConfig
|
|
846
|
+
{
|
|
847
|
+
// [Header("----- MODULE CONFIG -----")]
|
|
848
|
+
public bool showAnalyticsLog = true;
|
|
849
|
+
public bool normalizeEventName = true;
|
|
850
|
+
public bool checkMigrationIntegrity = true;
|
|
851
|
+
public bool enableEventStat;
|
|
852
|
+
public AnalyticQualityConfig quality;
|
|
853
|
+
}
|
|
854
|
+
|
|
743
855
|
[Serializable]
|
|
744
856
|
public class AnalyticQualityConfig
|
|
745
857
|
{
|
|
746
|
-
public bool enable
|
|
858
|
+
public bool enable;
|
|
747
859
|
public AnalyticQualityAsset qualityAsset;
|
|
748
860
|
|
|
749
861
|
public void CheckEventQuality(string eventName, Dictionary<string, object> parameters)
|
|
@@ -754,24 +866,32 @@ namespace Amanotes.Core.Internal
|
|
|
754
866
|
}
|
|
755
867
|
}
|
|
756
868
|
}
|
|
757
|
-
|
|
758
|
-
public partial class
|
|
869
|
+
|
|
870
|
+
public partial class ConfigAsset
|
|
759
871
|
{
|
|
760
|
-
public
|
|
761
|
-
public bool normalizeEventName = true;
|
|
762
|
-
public bool checkMigrationIntegrity = true;
|
|
763
|
-
public bool enableEventStat;
|
|
764
|
-
public AnalyticQualityConfig quality;
|
|
872
|
+
[SerializeField] public AnalyticsConfig analytics;
|
|
765
873
|
}
|
|
766
|
-
|
|
767
|
-
public
|
|
874
|
+
|
|
875
|
+
public abstract class AnalyticsAdapter : Adapter2
|
|
768
876
|
{
|
|
769
|
-
|
|
877
|
+
public bool SendEventByDefault;
|
|
878
|
+
|
|
879
|
+
public List<string> NeverSend;
|
|
880
|
+
public List<string> AlwaysSend;
|
|
881
|
+
|
|
882
|
+
public bool IsForbidden(string eventName)
|
|
883
|
+
{
|
|
884
|
+
return SendEventByDefault
|
|
885
|
+
? NeverSend.Contains(eventName)
|
|
886
|
+
: !AlwaysSend.Contains(eventName);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
public abstract void LogEvent(string eventNameToSend, Dictionary<string, object> parameters);
|
|
770
890
|
|
|
771
|
-
void SetUserId(string userId);
|
|
891
|
+
public abstract void SetUserId(string userId);
|
|
772
892
|
|
|
773
|
-
void SetUserProperty(string key, string value);
|
|
893
|
+
public abstract void SetUserProperty(string key, string value);
|
|
774
894
|
|
|
775
|
-
void GetAppInstanceID(Action<string> appId);
|
|
895
|
+
public abstract void GetAppInstanceID(Action<string> appId);
|
|
776
896
|
}
|
|
777
897
|
}
|
package/Runtime/AmaGDK.Config.cs
CHANGED
|
@@ -2,6 +2,7 @@ using System;
|
|
|
2
2
|
using System.Collections.Generic;
|
|
3
3
|
using System.Reflection;
|
|
4
4
|
using UnityEngine;
|
|
5
|
+
|
|
5
6
|
#if UNITY_EDITOR
|
|
6
7
|
using UnityEditor;
|
|
7
8
|
#endif
|
|
@@ -51,7 +52,7 @@ namespace Amanotes.Core.Internal
|
|
|
51
52
|
initOrder.Clear();
|
|
52
53
|
|
|
53
54
|
var counter = 0;
|
|
54
|
-
foreach (Type adapter in GetAllAdapters<
|
|
55
|
+
foreach (Type adapter in GetAllAdapters<Adapter2>())
|
|
55
56
|
{
|
|
56
57
|
string id = adapter.Name.Replace("Adapter", string.Empty);
|
|
57
58
|
initOrder.Add(new InitOrder(){ id = id, order = counter++ });
|