Skip to content

Commit

Permalink
feat: add generalProps APIs (#286)
Browse files Browse the repository at this point in the history
* feat: add generalProps APIs

* style: code format

* fix: generalProps bug

* ci: update ci

* fix: hybrid attributes 优先于 generalProps

* style: code format

* fix: hybrid attributes 增加 customEventType 判断是否添加 generalProps

* ci: update ci

---------

Co-authored-by: GIOSDK <[email protected]>
  • Loading branch information
YoloMao and GIOSDK authored Oct 26, 2023
1 parent 569f7ca commit e60f1fa
Show file tree
Hide file tree
Showing 11 changed files with 514 additions and 64 deletions.
296 changes: 263 additions & 33 deletions Example/GrowingAnalyticsTests/A0GrowingAnalyticsTest.m

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions GrowingAutotracker/GrowingAutotracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,17 @@ NS_ASSUME_NONNULL_BEGIN
/// 清除所有事件计时器
- (void)clearTrackTimer;

/// 设置埋点通用属性
/// @param props 事件通用属性,相同字段的新值将覆盖旧值
- (void)setGeneralProps:(NSDictionary<NSString *, NSString *> *)props;

/// 清除指定字段的埋点通用属性
/// @param keys 通用属性指定字段
- (void)removeGeneralProps:(NSArray<NSString *> *)keys;

/// 清除所有埋点通用属性
- (void)clearGeneralProps;

///-------------------------------
#pragma mark Autotrack Event
///-------------------------------
Expand Down
11 changes: 11 additions & 0 deletions GrowingTracker/GrowingTracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ NS_ASSUME_NONNULL_BEGIN
/// 清除所有事件计时器
- (void)clearTrackTimer;

/// 设置埋点通用属性
/// @param props 事件通用属性,相同字段的新值将覆盖旧值
- (void)setGeneralProps:(NSDictionary<NSString *, NSString *> *)props;

/// 清除指定字段的埋点通用属性
/// @param keys 通用属性指定字段
- (void)removeGeneralProps:(NSArray<NSString *> *)keys;

/// 清除所有埋点通用属性
- (void)clearGeneralProps;

///-------------------------------
#pragma mark Unavailable
///-------------------------------
Expand Down
5 changes: 5 additions & 0 deletions GrowingTrackerCore/Event/GrowingEventManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,9 @@
/// @param interceptor 拦截者
- (void)removeInterceptor:(NSObject<GrowingEventInterceptor> *_Nonnull)interceptor;

- (NSDictionary<NSString *, NSString *> *_Nonnull)generalProps;
- (void)setGeneralProps:(NSDictionary<NSString *, NSString *> *_Nonnull)props;
- (void)removeGeneralProps:(NSArray<NSString *> *_Nonnull)keys;
- (void)clearGeneralProps;

@end
22 changes: 22 additions & 0 deletions GrowingTrackerCore/Event/GrowingEventManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#import "GrowingTrackerCore/Event/GrowingEventManager.h"
#import "GrowingTrackerCore/Event/GrowingDataTraffic.h"
#import "GrowingTrackerCore/Event/GrowingEventChannel.h"
#import "GrowingTrackerCore/Event/GrowingGeneralProps.h"
#import "GrowingTrackerCore/FileStorage/GrowingFileStorage.h"
#import "GrowingTrackerCore/Helpers/GrowingHelpers.h"
#import "GrowingTrackerCore/Manager/GrowingConfigurationManager.h"
Expand All @@ -42,6 +43,7 @@
@interface GrowingEventManager ()

@property (nonatomic, strong) NSHashTable *allInterceptor;
@property (nonatomic, strong) GrowingGeneralProps *gProps;

@property (nonatomic, strong, readonly) NSArray<GrowingEventChannel *> *allEventChannels;
@property (nonatomic, strong, readonly) NSDictionary<NSString *, GrowingEventChannel *> *currentEventChannelMap;
Expand Down Expand Up @@ -74,6 +76,7 @@ + (instancetype)sharedInstance {
- (instancetype)init {
if (self = [super init]) {
_allInterceptor = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
_gProps = [[GrowingGeneralProps alloc] init];
}
return self;
}
Expand Down Expand Up @@ -159,6 +162,25 @@ - (void)startTimerSend {
}

#pragma mark - Event

#pragma mark General Props

- (NSDictionary<NSString *, NSString *> *)generalProps {
return self.gProps.props;
}

- (void)setGeneralProps:(NSDictionary<NSString *, NSString *> *)props {
[self.gProps setGeneralProps:props];
}

- (void)removeGeneralProps:(NSArray<NSString *> *)keys {
[self.gProps removeGeneralProps:keys];
}

- (void)clearGeneralProps {
[self.gProps clearGeneralProps];
}

#pragma mark Event Send

- (void)postEventBuilder:(GrowingBaseBuilder *_Nullable)builder {
Expand Down
36 changes: 36 additions & 0 deletions GrowingTrackerCore/Event/GrowingGeneralProps.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// GrowingGeneralProps.h
// GrowingAnalytics
//
// Created by YoloMao on 2023/10/20.
// Copyright (C) 2023 Beijing Yishu Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface GrowingGeneralProps : NSObject

@property (nonatomic, readonly, copy) NSDictionary<NSString *, NSString *> *props;

- (void)setGeneralProps:(NSDictionary<NSString *, NSString *> *)props;

- (void)removeGeneralProps:(NSArray<NSString *> *)keys;

- (void)clearGeneralProps;

@end

NS_ASSUME_NONNULL_END
55 changes: 55 additions & 0 deletions GrowingTrackerCore/Event/GrowingGeneralProps.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// GrowingGeneralProps.m
// GrowingAnalytics
//
// Created by YoloMao on 2023/10/20.
// Copyright (C) 2023 Beijing Yishu Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#import "GrowingTrackerCore/Event/GrowingGeneralProps.h"

@interface GrowingGeneralProps ()

@property (nonatomic, strong) NSMutableDictionary<NSString *, NSString *> *internalProps;

@end

@implementation GrowingGeneralProps

- (void)setGeneralProps:(NSDictionary<NSString *, NSString *> *)props {
[self.internalProps addEntriesFromDictionary:props];
}

- (void)removeGeneralProps:(NSArray<NSString *> *)keys {
[self.internalProps removeObjectsForKeys:keys];
}

- (void)clearGeneralProps {
[self.internalProps removeAllObjects];
}

#pragma mark - Setter && Getter

- (NSDictionary<NSString *, NSString *> *)props {
return self.internalProps.copy;
}

- (NSMutableDictionary<NSString *, NSString *> *)internalProps {
if (!_internalProps) {
_internalProps = [NSMutableDictionary dictionary];
}
return _internalProps;
}

@end
44 changes: 42 additions & 2 deletions GrowingTrackerCore/GrowingRealTracker.m
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,31 @@ - (void)trackCustomEvent:(NSString *)eventName {
if ([GrowingArgumentChecker isIllegalEventName:eventName]) {
return;
}
[GrowingEventGenerator generateCustomEvent:eventName attributes:nil];
[GrowingDispatchManager dispatchInGrowingThread:^{
NSDictionary *generalProps = [GrowingEventManager sharedInstance].generalProps;
NSDictionary *dic = nil;
if (generalProps.count > 0) {
dic = generalProps;
}
[GrowingEventGenerator generateCustomEvent:eventName attributes:dic];
}];
}

- (void)trackCustomEvent:(NSString *)eventName withAttributes:(NSDictionary<NSString *, NSString *> *)attributes {
if ([GrowingArgumentChecker isIllegalEventName:eventName] ||
[GrowingArgumentChecker isIllegalAttributes:attributes]) {
return;
}
[GrowingEventGenerator generateCustomEvent:eventName attributes:attributes];
[GrowingDispatchManager dispatchInGrowingThread:^{
NSDictionary *generalProps = [GrowingEventManager sharedInstance].generalProps;
NSDictionary *dic = attributes.copy;
if (generalProps.count > 0) {
NSMutableDictionary *dicM = [NSMutableDictionary dictionaryWithDictionary:generalProps];
[dicM addEntriesFromDictionary:dic];
dic = dicM.copy;
}
[GrowingEventGenerator generateCustomEvent:eventName attributes:dic];
}];
}

- (void)setLoginUserAttributes:(NSDictionary<NSString *, NSString *> *)attributes {
Expand Down Expand Up @@ -197,6 +213,30 @@ - (void)clearTrackTimer {
[GrowingEventTimer clearAllTimers];
}

- (void)setGeneralProps:(NSDictionary<NSString *, NSString *> *)props {
if ([GrowingArgumentChecker isIllegalAttributes:props]) {
return;
}
[GrowingDispatchManager dispatchInGrowingThread:^{
[[GrowingEventManager sharedInstance] setGeneralProps:props];
}];
}

- (void)removeGeneralProps:(NSArray<NSString *> *)keys {
if ([GrowingArgumentChecker isIllegalKeys:keys]) {
return;
}
[GrowingDispatchManager dispatchInGrowingThread:^{
[[GrowingEventManager sharedInstance] removeGeneralProps:keys];
}];
}

- (void)clearGeneralProps {
[GrowingDispatchManager dispatchInGrowingThread:^{
[[GrowingEventManager sharedInstance] clearGeneralProps];
}];
}

- (void)setLoginUserId:(NSString *)userId {
[GrowingDispatchManager dispatchInGrowingThread:^{
[[GrowingSession currentSession] setLoginUserId:userId];
Expand Down
1 change: 1 addition & 0 deletions GrowingTrackerCore/Utils/GrowingArgumentChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@

+ (BOOL)isIllegalEventName:(NSString *)eventName;
+ (BOOL)isIllegalAttributes:(NSDictionary *)attributes;
+ (BOOL)isIllegalKeys:(NSArray *)keys;

@end
21 changes: 21 additions & 0 deletions GrowingTrackerCore/Utils/GrowingArgumentChecker.m
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,25 @@ + (BOOL)isIllegalAttributes:(NSDictionary *)attributes {
return NO;
}

+ (BOOL)isIllegalKeys:(NSArray *)keys {
if (keys == nil) {
GIOLogError(@"keys is NULL");
return YES;
}

if (![keys isKindOfClass:NSArray.class]) {
GIOLogError(@"keys is not kind of NSArray class");
return YES;
}

for (NSString *key in keys) {
if (![key isKindOfClass:NSString.class]) {
GIOLogError(@"Key %@ is not kind of NSString class", key);
return YES;
}
}

return NO;
}

@end
76 changes: 47 additions & 29 deletions Modules/Hybrid/GrowingHybridBridgeProvider.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#import "GrowingTrackerCore/Public/GrowingAnnotationCore.h"
#import "GrowingTrackerCore/Public/GrowingBaseEvent.h"
#import "GrowingTrackerCore/Thirdparty/Logger/GrowingLogger.h"
#import "GrowingTrackerCore/Thread/GrowingDispatchManager.h"
#import "GrowingTrackerCore/Utils/GrowingDeviceInfo.h"
#import "GrowingULTimeUtil.h"
#import "Modules/Hybrid/Events/GrowingHybridCustomEvent.h"
Expand Down Expand Up @@ -62,6 +63,7 @@
#define KEY_TEXT_VALUE "textValue"
#define KEY_XPATH "xpath"
#define KEY_XCONTENT "xcontent"
#define CUSTOM_EVENT_TYPE "customEventType"

@interface UIView (GrowingNode) <GrowingNode>
@end
Expand Down Expand Up @@ -207,35 +209,51 @@ - (void)parseEventJsonString:(NSString *)jsonString {
NSDictionary *evetDataDict = (NSDictionary *)dict;
NSString *type = evetDataDict[@"eventType"];

GrowingBaseBuilder *builder = nil;
if ([type isEqualToString:GrowingEventTypePage]) {
builder = GrowingHybridPageEvent.builder.setProtocolType(dict[@KEY_PROTOCOL_TYPE])
.setQuery(dict[@KEY_QUERY])
.setTitle(dict[@KEY_TITLE])
.setReferralPage(dict[@KEY_REFERRAL_PAGE])
.setPath(dict[@KEY_PATH])
.setTimestamp([dict growingHelper_longlongForKey:@KEY_TIMESTAMP
fallback:[GrowingULTimeUtil currentTimeMillis]])
.setAttributes([self safeAttributesFromDict:dict])
.setDomain([self getDomain:dict]);
} else if ([type isEqualToString:GrowingEventTypeViewClick]) {
builder = [self transformViewElementBuilder:dict].setEventType(type);
} else if ([type isEqualToString:GrowingEventTypeViewChange]) {
builder = [self transformViewElementBuilder:dict].setEventType(type);
} else if ([type isEqualToString:GrowingEventTypeFormSubmit]) {
builder = [self transformViewElementBuilder:dict].setEventType(type);
} else if ([type isEqualToString:GrowingEventTypeCustom]) {
builder = GrowingHybridCustomEvent.builder.setQuery(dict[@KEY_QUERY])
.setPath(dict[@KEY_PATH])
.setAttributes([self safeAttributesFromDict:dict])
.setEventName(dict[@KEY_EVENT_NAME])
.setDomain([self getDomain:dict]);
} else if ([type isEqualToString:GrowingEventTypeLoginUserAttributes]) {
builder = GrowingLoginUserAttributesEvent.builder.setAttributes([self safeAttributesFromDict:dict]);
}
if (builder) {
[[GrowingEventManager sharedInstance] postEventBuilder:builder];
}
[GrowingDispatchManager dispatchInGrowingThread:^{
GrowingBaseBuilder *builder = nil;
if ([type isEqualToString:GrowingEventTypePage]) {
builder = GrowingHybridPageEvent.builder.setProtocolType(dict[@KEY_PROTOCOL_TYPE])
.setQuery(dict[@KEY_QUERY])
.setTitle(dict[@KEY_TITLE])
.setReferralPage(dict[@KEY_REFERRAL_PAGE])
.setPath(dict[@KEY_PATH])
.setTimestamp([dict growingHelper_longlongForKey:@KEY_TIMESTAMP
fallback:[GrowingULTimeUtil currentTimeMillis]])
.setAttributes([self safeAttributesFromDict:dict])
.setDomain([self getDomain:dict]);
} else if ([type isEqualToString:GrowingEventTypeViewClick]) {
builder = [self transformViewElementBuilder:dict].setEventType(type);
} else if ([type isEqualToString:GrowingEventTypeViewChange]) {
builder = [self transformViewElementBuilder:dict].setEventType(type);
} else if ([type isEqualToString:GrowingEventTypeFormSubmit]) {
builder = [self transformViewElementBuilder:dict].setEventType(type);
} else if ([type isEqualToString:GrowingEventTypeCustom]) {
NSString *customEventType = dict[@CUSTOM_EVENT_TYPE];
if ([customEventType isKindOfClass:[NSNumber class]]) {
customEventType = ((NSNumber *)dict[@CUSTOM_EVENT_TYPE]).stringValue;
}
NSDictionary *mergedDic = [self safeAttributesFromDict:dict].copy;
if (customEventType == nil || [customEventType isEqualToString:@"1"]) {
// hybrid通过track接口调用
NSDictionary *generalProps = [GrowingEventManager sharedInstance].generalProps;
if (generalProps.count > 0) {
NSMutableDictionary *dicM = [NSMutableDictionary dictionaryWithDictionary:generalProps];
[dicM addEntriesFromDictionary:mergedDic];
mergedDic = dicM.copy;
}
}
builder = GrowingHybridCustomEvent.builder.setQuery(dict[@KEY_QUERY])
.setPath(dict[@KEY_PATH])
.setAttributes(mergedDic)
.setEventName(dict[@KEY_EVENT_NAME])
.setDomain([self getDomain:dict]);
} else if ([type isEqualToString:GrowingEventTypeLoginUserAttributes]) {
builder = GrowingLoginUserAttributesEvent.builder.setAttributes([self safeAttributesFromDict:dict]);
}
if (builder) {
[[GrowingEventManager sharedInstance] postEventBuilder:builder];
}
}];
}

- (GrowingBaseBuilder *)transformViewElementBuilder:(NSDictionary *)dict {
Expand Down

0 comments on commit e60f1fa

Please sign in to comment.