From e025e472e26670e89aaa2448007303e195cf7e81 Mon Sep 17 00:00:00 2001 From: zhongcang Date: Mon, 16 Jul 2018 20:41:19 +0800 Subject: [PATCH] [WEEX-552][iOS] apm for ios MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [iOS] more info use new protocol WXApmProtocol to record weex page performance record stage (download -> success/falied -> renderStart -> fsRenderTime -> interactionTime -> destroy) record property , such as wxInstanceType(page/embed) ,wxParentPage(for embed) ... record stats : wxBundleSize、wxMaxDeepVDomLayer、wxCellUnReUseCount reord event : gc、press home and so on (not impl now) deprecated WXMonitor more performance point add WXApmGeneratorImpl (WXApmProtocol impl case ) in demo --- .../WeexDemo.xcodeproj/project.pbxproj | 12 + ios/playground/WeexDemo/AppDelegate.m | 2 + .../extend/handler/WXApmGeneratorImpl.h | 6 + .../extend/handler/WXApmGeneratorImpl.m | 12 + .../WeexDemo/extend/handler/WXApmImpl.h | 6 + .../WeexDemo/extend/handler/WXApmImpl.m | 110 +++++++ .../extend/handler/WXImgLoaderDefaultImpl.m | 38 +++ ios/sdk/WeexSDK.xcodeproj/project.pbxproj | 36 +++ .../WeexSDK/Sources/Bridge/WXBridgeContext.m | 24 +- .../Sources/Component/WXCellComponent.mm | 7 + .../Sources/Component/WXImageComponent.m | 17 +- .../Sources/Component/WXScrollerComponent.mm | 4 + .../Sources/Component/WXVideoComponent.m | 5 +- .../Sources/Handler/WXNavigationDefaultImpl.m | 2 +- .../Sources/Layout/WXComponent+Layout.mm | 1 + .../WeexSDK/Sources/Manager/WXBridgeManager.m | 4 + .../Sources/Manager/WXComponentManager.mm | 2 + ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h | 9 +- ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m | 27 +- .../Sources/Model/WXSDKInstance_performance.h | 3 + .../WeexSDK/Sources/Module/WXTimerModule.m | 13 + ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h | 2 + .../Sources/Performance/WXApmForInstance.h | 103 +++++++ .../Sources/Performance/WXInstanceApm.m | 289 ++++++++++++++++++ .../WeexSDK/Sources/Protocol/WXApmProtocol.h | 85 ++++++ ios/sdk/WeexSDK/Sources/Utility/WXUtility.h | 2 + ios/sdk/WeexSDK/Sources/Utility/WXUtility.m | 6 + ios/sdk/WeexSDK/Sources/WeexSDK.h | 2 + 28 files changed, 810 insertions(+), 19 deletions(-) create mode 100644 ios/playground/WeexDemo/extend/handler/WXApmGeneratorImpl.h create mode 100644 ios/playground/WeexDemo/extend/handler/WXApmGeneratorImpl.m create mode 100644 ios/playground/WeexDemo/extend/handler/WXApmImpl.h create mode 100644 ios/playground/WeexDemo/extend/handler/WXApmImpl.m create mode 100644 ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.h create mode 100644 ios/sdk/WeexSDK/Sources/Performance/WXInstanceApm.m create mode 100644 ios/sdk/WeexSDK/Sources/Protocol/WXApmProtocol.h diff --git a/ios/playground/WeexDemo.xcodeproj/project.pbxproj b/ios/playground/WeexDemo.xcodeproj/project.pbxproj index 9721ca7c98..e3c9b31450 100644 --- a/ios/playground/WeexDemo.xcodeproj/project.pbxproj +++ b/ios/playground/WeexDemo.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 17036A5720FDF9AA0029AE3D /* WXApmGeneratorImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = 17036A5620FDF9AA0029AE3D /* WXApmGeneratorImpl.m */; }; + 17036A5A20FDF9DF0029AE3D /* WXApmImpl.m in Sources */ = {isa = PBXBuildFile; fileRef = 17036A5920FDF9DF0029AE3D /* WXApmImpl.m */; }; 17C1DB57206B675D000E0CEB /* DebugAnzlyzer.m in Sources */ = {isa = PBXBuildFile; fileRef = 17C1DB56206B675D000E0CEB /* DebugAnzlyzer.m */; }; 2AE88A2C1C8544E6003329DE /* WXScannerVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AE88A2B1C8544E6003329DE /* WXScannerVC.m */; }; 564B94671DD9C65000441C8D /* WeexUITestDemo-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 564B94661DD9C65000441C8D /* WeexUITestDemo-Info.plist */; }; @@ -67,6 +69,10 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 17036A5520FDF9AA0029AE3D /* WXApmGeneratorImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WXApmGeneratorImpl.h; path = extend/handler/WXApmGeneratorImpl.h; sourceTree = ""; }; + 17036A5620FDF9AA0029AE3D /* WXApmGeneratorImpl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = WXApmGeneratorImpl.m; path = extend/handler/WXApmGeneratorImpl.m; sourceTree = ""; }; + 17036A5820FDF9DF0029AE3D /* WXApmImpl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WXApmImpl.h; path = extend/handler/WXApmImpl.h; sourceTree = ""; }; + 17036A5920FDF9DF0029AE3D /* WXApmImpl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = WXApmImpl.m; path = extend/handler/WXApmImpl.m; sourceTree = ""; }; 17C1DB55206B6729000E0CEB /* DebugAnalyzer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DebugAnalyzer.h; path = debug/DebugAnalyzer.h; sourceTree = ""; }; 17C1DB56206B675D000E0CEB /* DebugAnzlyzer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = DebugAnzlyzer.m; path = debug/DebugAnzlyzer.m; sourceTree = ""; }; 1888E2C5769382461DEDC97D /* Pods-WeexUITestDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WeexUITestDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-WeexUITestDemo/Pods-WeexUITestDemo.release.xcconfig"; sourceTree = ""; }; @@ -336,6 +342,10 @@ DC20B8E51ECADA2500845F39 /* WXConfigCenterDefaultImpl.m */, DCABAFFC1D029753001C8592 /* WXImgLoaderDefaultImpl.h */, DCABAFFD1D029753001C8592 /* WXImgLoaderDefaultImpl.m */, + 17036A5520FDF9AA0029AE3D /* WXApmGeneratorImpl.h */, + 17036A5620FDF9AA0029AE3D /* WXApmGeneratorImpl.m */, + 17036A5820FDF9DF0029AE3D /* WXApmImpl.h */, + 17036A5920FDF9DF0029AE3D /* WXApmImpl.m */, ); name = handler; sourceTree = ""; @@ -625,6 +635,7 @@ DCABAFF31D029685001C8592 /* WXATLoggerPlugin.m in Sources */, DC15A3D0200E30FC009C8977 /* WXNavigationHandlerImpl.m in Sources */, 2AE88A2C1C8544E6003329DE /* WXScannerVC.m in Sources */, + 17036A5720FDF9AA0029AE3D /* WXApmGeneratorImpl.m in Sources */, 775BEE861C1E8ECC008D1629 /* WXDemoViewController.m in Sources */, DC5B53691E8CED9400E02125 /* WXScannerHistoryVC.m in Sources */, 74CC79EB1C2B9E4700829368 /* UIViewController+WXDemoNaviBar.m in Sources */, @@ -633,6 +644,7 @@ 775BEE831C1E8ECC008D1629 /* AppDelegate.m in Sources */, 847CAF311F39E3F100551725 /* WXExtModule.m in Sources */, DC15A3C7200C505C009C8977 /* WXTitleBarModule.m in Sources */, + 17036A5A20FDF9DF0029AE3D /* WXApmImpl.m in Sources */, DC20B8E61ECADA2500845F39 /* WXConfigCenterDefaultImpl.m in Sources */, DCABAFF41D029685001C8592 /* WXATViewHierarchyPlugin.m in Sources */, 775BEE801C1E8ECC008D1629 /* main.m in Sources */, diff --git a/ios/playground/WeexDemo/AppDelegate.m b/ios/playground/WeexDemo/AppDelegate.m index 7687f47a65..683d3b3e61 100644 --- a/ios/playground/WeexDemo/AppDelegate.m +++ b/ios/playground/WeexDemo/AppDelegate.m @@ -37,6 +37,7 @@ #import "WXConfigCenterDefaultImpl.h" #import "WXNavigationHandlerImpl.h" //#import "WXAnalyzerCenter.h" +#import "WXApmGeneratorImpl.h" #ifdef DEBUG @@ -123,6 +124,7 @@ - (void)initWeexSDK [WXSDKEngine registerHandler:[WXEventModule new] withProtocol:@protocol(WXEventModuleProtocol)]; [WXSDKEngine registerHandler:[WXConfigCenterDefaultImpl new] withProtocol:@protocol(WXConfigCenterProtocol)]; [WXSDKEngine registerHandler:[WXNavigationHandlerImpl new] withProtocol:@protocol(WXNavigationProtocol)]; + [WXSDKEngine registerHandler:[WXApmGeneratorImpl new] withProtocol:@protocol(WXApmGeneratorProtocol)]; [WXSDKEngine registerComponent:@"select" withClass:NSClassFromString(@"WXSelectComponent")]; [WXSDKEngine registerModule:@"event" withClass:[WXEventModule class]]; diff --git a/ios/playground/WeexDemo/extend/handler/WXApmGeneratorImpl.h b/ios/playground/WeexDemo/extend/handler/WXApmGeneratorImpl.h new file mode 100644 index 0000000000..f18c4c3814 --- /dev/null +++ b/ios/playground/WeexDemo/extend/handler/WXApmGeneratorImpl.h @@ -0,0 +1,6 @@ +#import +#import "WXApmProtocol.h" + +@interface WXApmGeneratorImpl : NSObject + +@end diff --git a/ios/playground/WeexDemo/extend/handler/WXApmGeneratorImpl.m b/ios/playground/WeexDemo/extend/handler/WXApmGeneratorImpl.m new file mode 100644 index 0000000000..fffd213310 --- /dev/null +++ b/ios/playground/WeexDemo/extend/handler/WXApmGeneratorImpl.m @@ -0,0 +1,12 @@ +#import "WXApmGeneratorImpl.h" +#import "WXApmImpl.h" + +@implementation WXApmGeneratorImpl + +- (id)gengratorApmInstance:(NSString *) type +{ + id instance = [[WXApmImpl alloc] init]; + return instance; +} + +@end diff --git a/ios/playground/WeexDemo/extend/handler/WXApmImpl.h b/ios/playground/WeexDemo/extend/handler/WXApmImpl.h new file mode 100644 index 0000000000..85003e6d6f --- /dev/null +++ b/ios/playground/WeexDemo/extend/handler/WXApmImpl.h @@ -0,0 +1,6 @@ +#import +#import "WXApmProtocol.h" + +@interface WXApmImpl : NSObject + +@end diff --git a/ios/playground/WeexDemo/extend/handler/WXApmImpl.m b/ios/playground/WeexDemo/extend/handler/WXApmImpl.m new file mode 100644 index 0000000000..4bb195d436 --- /dev/null +++ b/ios/playground/WeexDemo/extend/handler/WXApmImpl.m @@ -0,0 +1,110 @@ + +#import "WXApmImpl.h" +#import "WXUtility.h" + +@interface WXApmImpl() +@property(nonatomic,strong) NSMutableDictionary* stageMap; +@property(nonatomic,strong) NSMutableDictionary* propertyMap; +@property(nonatomic,strong) NSMutableDictionary* statisticMap; +@property(nonatomic,strong) NSMutableDictionary* eventMap; + +@end + +@implementation WXApmImpl + +- (instancetype)init +{ + self = [super init]; + if (self) { + _stageMap = [[NSMutableDictionary alloc] init]; + _propertyMap = [[NSMutableDictionary alloc] init]; + _statisticMap = [[NSMutableDictionary alloc] init]; + _eventMap = [[NSMutableDictionary alloc] init]; + } + return self; +} + + +- (void) onStart:(NSString *)instanceId topic:(NSString *)topic +{ + +} + +- (void) onEnd +{ + [self _printApmInfo]; +} + +- (void) onEvent:(NSString *)name withValue:(id)value +{ + [self.eventMap setObject:value forKey:name]; +} + +- (void) onStage:(NSString *)name withValue:(long)timestamp +{ + [self.stageMap setObject:[NSNumber numberWithLong:timestamp] forKey:name]; +} + +- (void) addProperty:(NSString *)name withValue:(id)value +{ + [self.propertyMap setObject:value forKey:name]; +} + +- (void) addStatistic:(NSString *)name withValue:(double)value +{ + [self.statisticMap setObject:[NSNumber numberWithDouble:value] forKey:name]; +} + +- (void) addBiz:(NSString *)bizID withValue:(NSDictionary *)properties +{ + +} + +- (void) addBizAbTest:(NSString *)bizID withValue:(NSDictionary *)abTest +{ + +} + +- (void) addBizStage:(NSString *)bizID withValue:(NSDictionary *)stage +{ + +} + +- (void) onSubProcedureBegin:(NSString *)subProcedureName +{ + +} + +- (void) onSubProcedureEndFailed:(NSString *)subProcedureName +{ + +} + +- (void) onSubProcedureEndSucceed:(NSString *)subProcedureName +{ + +} + +- (void)pauseApmRecord { + +} + + +- (void)resumeApmRecord { + +} + + +- (void) _printApmInfo +{ + NSDictionary* InfoMap = @{ + @"stage":self.stageMap, + @"property":self.propertyMap, + @"statistic":self.statisticMap, + @"event":self.eventMap + }; + NSString* jsonStr = [WXUtility JSONString:InfoMap]; + NSLog(@"wxApmForInstance :%@",jsonStr); +} + +@end diff --git a/ios/playground/WeexDemo/extend/handler/WXImgLoaderDefaultImpl.m b/ios/playground/WeexDemo/extend/handler/WXImgLoaderDefaultImpl.m index a085ddbfa9..b957cd74a7 100644 --- a/ios/playground/WeexDemo/extend/handler/WXImgLoaderDefaultImpl.m +++ b/ios/playground/WeexDemo/extend/handler/WXImgLoaderDefaultImpl.m @@ -19,6 +19,8 @@ #import "WXImgLoaderDefaultImpl.h" #import +#import "WXLog.h" +#import "WXSDKManager.h" #define MIN_IMAGE_WIDTH 36 #define MIN_IMAGE_HEIGHT 36 @@ -48,6 +50,7 @@ @implementation WXImgLoaderDefaultImpl - (id)downloadImageWithURL:(NSString *)url imageFrame:(CGRect)imageFrame userInfo:(NSDictionary *)userInfo completed:(void(^)(UIImage *image, NSError *error, BOOL finished))completedBlock { + [self _recoredImgLoad:url options:userInfo]; if ([url hasPrefix:@"//"]) { url = [@"http:" stringByAppendingString:url]; } @@ -57,11 +60,13 @@ @implementation WXImgLoaderDefaultImpl if (completedBlock) { completedBlock(image, error, finished); } + [self _recoredFinish:imageURL error:error loadOptions:userInfo]; }]; } - (void)setImageViewWithURL:(UIImageView *)imageView url:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(NSDictionary *)options progress:(void (^)(NSInteger, NSInteger))progressBlock completed:(void (^)(UIImage *, NSError *, WXImageLoaderCacheType, NSURL *))completedBlock { + [self _recoredImgLoad:url.absoluteString options:options]; SDWebImageOptions sdWebimageOption = SDWebImageRetryFailed; if (options && options[@"sdWebimageOption"]) { [options[@"sdWebimageOption"] intValue]; @@ -75,7 +80,40 @@ - (void)setImageViewWithURL:(UIImageView *)imageView url:(NSURL *)url placeholde if (completedBlock) { completedBlock(image, error, (WXImageLoaderCacheType)cacheType, imageURL); } + [self _recoredFinish:imageURL error:error loadOptions:options]; }]; } +- (void) _recoredImgLoad:(NSString *)url options:(NSDictionary *)options +{ + if (nil == url) { + return; + } + NSString* instanceId = [options objectForKey:@"instanceId"]; + if (nil == instanceId) { + WXLogWarning(@"please set instanceId in userInfo,for url %@:",url); + return; + } + WXSDKInstance* instance =[WXSDKManager instanceForID:instanceId]; + if (nil == instance) { + return; + } + [instance.apmInstance updateDiffStats:KEY_PAGE_STATS_IMG_LOAD_NUM withDiffValue:1]; +} + +- (void) _recoredFinish:(NSURL*)imgUrl error:(NSError*)error loadOptions:(NSDictionary*)options +{ + NSString* instanceId = [options objectForKey:@"instanceId"]; + if (nil == instanceId) { + WXLogWarning(@"please set instanceId in userInfo,for url %@:",imgUrl.absoluteString); + return; + } + WXSDKInstance* instance =[WXSDKManager instanceForID:instanceId]; + if (nil == instance) { + return; + } + bool loadSucceed = error == nil; + [instance.apmInstance actionImgLoadResult:loadSucceed withErrorCode:nil]; +} + @end diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj index 92753ed8f9..8a8ed3ba29 100644 --- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj +++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj @@ -8,6 +8,12 @@ /* Begin PBXBuildFile section */ 042013AD1E66CD6A001FC79C /* WXValidateProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 042013AC1E66CD6A001FC79C /* WXValidateProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 17036A4E20FDE72F0029AE3D /* WXApmForInstance.h in Headers */ = {isa = PBXBuildFile; fileRef = 17036A4C20FDE72F0029AE3D /* WXApmForInstance.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 17036A4F20FDE72F0029AE3D /* WXApmForInstance.h in Headers */ = {isa = PBXBuildFile; fileRef = 17036A4C20FDE72F0029AE3D /* WXApmForInstance.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 17036A5020FDE72F0029AE3D /* WXInstanceApm.m in Sources */ = {isa = PBXBuildFile; fileRef = 17036A4D20FDE72F0029AE3D /* WXInstanceApm.m */; }; + 17036A5120FDE72F0029AE3D /* WXInstanceApm.m in Sources */ = {isa = PBXBuildFile; fileRef = 17036A4D20FDE72F0029AE3D /* WXInstanceApm.m */; }; + 17036A5320FDE7490029AE3D /* WXApmProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 17036A5220FDE7490029AE3D /* WXApmProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 17036A5420FDE7490029AE3D /* WXApmProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 17036A5220FDE7490029AE3D /* WXApmProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 170B4664208733AF00562666 /* WXAnalyzerCenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 17C74F092072145000AB4CAB /* WXAnalyzerCenter.h */; settings = {ATTRIBUTES = (Public, ); }; }; 170B4665208733BF00562666 /* WXAnalyzerCenter+Transfer.h in Headers */ = {isa = PBXBuildFile; fileRef = 17C74F082072145000AB4CAB /* WXAnalyzerCenter+Transfer.h */; }; 170B4668208733E500562666 /* WXAnalyzerCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 17C74F0A2072145100AB4CAB /* WXAnalyzerCenter.m */; }; @@ -647,6 +653,9 @@ /* Begin PBXFileReference section */ 042013AC1E66CD6A001FC79C /* WXValidateProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXValidateProtocol.h; sourceTree = ""; }; 1746EA7220E9D253007E55BD /* WXComponent_performance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXComponent_performance.h; sourceTree = ""; }; + 17036A4C20FDE72F0029AE3D /* WXApmForInstance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXApmForInstance.h; sourceTree = ""; }; + 17036A4D20FDE72F0029AE3D /* WXInstanceApm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXInstanceApm.m; sourceTree = ""; }; + 17036A5220FDE7490029AE3D /* WXApmProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXApmProtocol.h; sourceTree = ""; }; 176BE43B209172330086B6AF /* WXComponent+Layout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "WXComponent+Layout.mm"; path = "Layout/WXComponent+Layout.mm"; sourceTree = ""; }; 17B1221F2090AA9300387E33 /* WXSDKInstance_performance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXSDKInstance_performance.m; sourceTree = ""; }; 17B122202090AA9300387E33 /* WXSDKInstance_performance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXSDKInstance_performance.h; sourceTree = ""; }; @@ -1022,6 +1031,25 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 17036A4B20FDE7090029AE3D /* Performance */ = { + isa = PBXGroup; + children = ( + 17036A4C20FDE72F0029AE3D /* WXApmForInstance.h */, + 17036A4D20FDE72F0029AE3D /* WXInstanceApm.m */, + ); + path = Performance; + sourceTree = ""; + }; + 17B12228209170CF00387E33 /* Recovered References */ = { + isa = PBXGroup; + children = ( + 8431F8DD1F9EFCC100C76E1E /* WXScrollerComponent+Layout.mm */, + 59D3CA461CFC3CC0008835DC /* WXSliderComponent.mm */, + 847E1DE01F9A1BCF00A48124 /* WXCoreStyle.h */, + ); + name = "Recovered References"; + sourceTree = ""; + }; 2A42AF861C23B33E00818EA6 /* WeexSDK_MTL */ = { isa = PBXGroup; children = ( @@ -1303,6 +1331,7 @@ 77D161181C02DCB90010B15B /* Sources */ = { isa = PBXGroup; children = ( + 17036A4B20FDE7090029AE3D /* Performance */, DCA446261EFA5DAF00D0CFA8 /* WeexSDK.h */, C4F012711E1502A6003378D0 /* WebSocket */, 2AF626C61C191E2200E71A38 /* Layout */, @@ -1405,6 +1434,7 @@ 77D1611C1C02DD3C0010B15B /* Protocol */ = { isa = PBXGroup; children = ( + 17036A5220FDE7490029AE3D /* WXApmProtocol.h */, 17C74F0E2072147A00AB4CAB /* WXAnalyzerProtocol.h */, 59A596171CB630E50012CD52 /* WXNavigationProtocol.h */, DCDFED001E68238F00C228D7 /* WXJSExceptionProtocol.h */, @@ -1637,6 +1667,7 @@ 775BEE711C1BD977008D1629 /* WXModuleProtocol.h in Headers */, 7469869F1C4E2C000054A57E /* NSArray+Weex.h in Headers */, 74CC7A201C2BF9DC00829368 /* WXListComponent.h in Headers */, + 17036A5320FDE7490029AE3D /* WXApmProtocol.h in Headers */, 7423EB511F4ADE30001662D1 /* WXComponent+DataBinding.h in Headers */, 74FD6E041C7C0E9600DBEB6D /* WXScrollerProtocol.h in Headers */, 74CFDD3D1F459400007A1A66 /* WXRecycleListDataManager.h in Headers */, @@ -1764,6 +1795,7 @@ 74A4BA851CAD453400195969 /* WXNetworkProtocol.h in Headers */, 7461F8A81CFC33A800F62D44 /* WXThreadSafeMutableArray.h in Headers */, D33451081D3E19480083598A /* WXCanvasComponent.h in Headers */, + 17036A4E20FDE72F0029AE3D /* WXApmForInstance.h in Headers */, 74B8BEFE1DC47B72004A6027 /* WXRootView.h in Headers */, 77E65A111C155EA8008B8775 /* WXImageComponent.h in Headers */, 745B2D6C1E5A8E1E0092D38A /* WXRecyclerDataController.h in Headers */, @@ -1844,6 +1876,7 @@ DCA445B11EFA576800D0CFA8 /* WXLog.h in Headers */, DCA4459D1EFA56DB00D0CFA8 /* WXValidateProtocol.h in Headers */, DCA445B81EFA579800D0CFA8 /* WXEventModuleProtocol.h in Headers */, + 17036A5420FDE7490029AE3D /* WXApmProtocol.h in Headers */, DCA445AE1EFA575700D0CFA8 /* WXMonitor.h in Headers */, DCA445BD1EFA57B500D0CFA8 /* WXConfigCenterProtocol.h in Headers */, DCA445A11EFA56FA00D0CFA8 /* WXScrollerProtocol.h in Headers */, @@ -1907,6 +1940,7 @@ 74B81AE31F73C3E300D3A61D /* WXRecycleListComponent.h in Headers */, DCA445DA1EFA59A600D0CFA8 /* WXMultiColumnLayout.h in Headers */, DCA445E01EFA59CD00D0CFA8 /* WXLoadingIndicator.h in Headers */, + 17036A4F20FDE72F0029AE3D /* WXApmForInstance.h in Headers */, DCA445E61EFA59E500D0CFA8 /* WXImageComponent.h in Headers */, DCA4461B1EFA5AA200D0CFA8 /* WXDatePickerManager.h in Headers */, DCA445D71EFA598D00D0CFA8 /* WXComponent+ViewManagement.h in Headers */, @@ -2290,6 +2324,7 @@ 74862F821E03A24500B7A041 /* WXComponentMethod.m in Sources */, 77E65A121C155EA8008B8775 /* WXImageComponent.m in Sources */, 74CFDD3E1F459400007A1A66 /* WXRecycleListDataManager.m in Sources */, + 17036A5020FDE72F0029AE3D /* WXInstanceApm.m in Sources */, 2A837AB31CD9DE9200AEDF03 /* WXLoadingComponent.mm in Sources */, 2AE5B7531CAB7DBD0082FDDB /* WXAComponent.m in Sources */, 176BE43C209172330086B6AF /* WXComponent+Layout.mm in Sources */, @@ -2380,6 +2415,7 @@ DCA445511EFA55B300D0CFA8 /* WXCycleSliderComponent.mm in Sources */, DCE2CF9D1F46D4370021BDC4 /* WXVoiceOverModule.m in Sources */, DCA445531EFA55B300D0CFA8 /* WXCellComponent.mm in Sources */, + 17036A5120FDE72F0029AE3D /* WXInstanceApm.m in Sources */, DCA445541EFA55B300D0CFA8 /* WXListComponent.mm in Sources */, DCA445551EFA55B300D0CFA8 /* WXIndicatorComponent.m in Sources */, 17E5ACDB2091F05700EE81F1 /* WXComponent+Layout.mm in Sources */, diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m index cb4903ace0..f19632288c 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m @@ -484,6 +484,11 @@ - (NSInteger)invokeNative:(NSString *)instanceId tasks:(NSArray *)tasks callback instance.performance.fsCallNativeNum++; instance.performance.fsCallNativeTime = instance.performance.fsCallNativeTime + diff; } + if (instance && !instance.apmInstance.isFSEnd) { + NSTimeInterval diff = CACurrentMediaTime()*1000 - startTime; + [instance.apmInstance updateFSDiffStats:KEY_PAGE_STATS_FS_CALL_NATIVE_NUM withDiffValue:1]; + [instance.apmInstance updateFSDiffStats:KEY_PAGE_STATS_FS_CALL_NATIVE_TIME withDiffValue:diff]; + } return 1; } @@ -504,6 +509,8 @@ - (void)createInstance:(NSString *)instanceIdString } } } + WXSDKInstance *sdkInstance = [WXSDKManager instanceForID:instanceIdString]; + [sdkInstance.apmInstance onStage:KEY_PAGE_STAGES_LOAD_BUNDLE_START]; //create a sendQueue bind to the current instance NSMutableArray *sendQueue = [NSMutableArray array]; @@ -519,6 +526,8 @@ - (void)createInstance:(NSString *)instanceIdString bundleType = [self _pareJSBundleType:instanceIdString jsBundleString:jsBundleString]; // bundleType can be Vue, Rax and the new framework. } if (bundleType&&shoudMultiContext) { + [sdkInstance.apmInstance setProperty:KEY_PAGE_PROPERTIES_USE_MULTI_CONTEXT withValue:[NSNumber numberWithBool:true]]; + [sdkInstance.apmInstance setProperty:KEY_PAGE_PROPERTIES_BUNDLE_TYPE withValue:bundleType]; NSMutableDictionary *newOptions = [options mutableCopy]; if (!options) { newOptions = [NSMutableDictionary new]; @@ -527,7 +536,6 @@ - (void)createInstance:(NSString *)instanceIdString newOptions[@"bundleType"] = bundleType; NSString *raxAPIScript = nil; NSString *raxAPIScriptPath = nil; - WXSDKInstance *sdkInstance = [WXSDKManager instanceForID:instanceIdString]; sdkInstance.bundleType = bundleType; if ([bundleType.lowercaseString isEqualToString:@"rax"]) { raxAPIScriptPath = [[NSBundle bundleForClass:[weakSelf class]] pathForResource:@"weex-rax-api" ofType:@"js"]; @@ -597,6 +605,8 @@ - (void)createInstance:(NSString *)instanceIdString } } else { + [sdkInstance.apmInstance setProperty:KEY_PAGE_PROPERTIES_USE_MULTI_CONTEXT withValue:[NSNumber numberWithBool:false]]; + [sdkInstance.apmInstance setProperty:KEY_PAGE_PROPERTIES_BUNDLE_TYPE withValue:@"singleContextUnkonwType"]; if (data){ args = @[instanceIdString, jsBundleString, options ?: @{}, data]; } else { @@ -605,6 +615,7 @@ - (void)createInstance:(NSString *)instanceIdString [self callJSMethod:@"createInstance" args:args]; } WX_MONITOR_INSTANCE_PERF_END(WXPTJSCreateInstance, [WXSDKManager instanceForID:instanceIdString]); + [sdkInstance.apmInstance onStage:KEY_PAGE_STAGES_LOAD_BUNDLE_END]; } - (NSString *)_pareJSBundleType:(NSString*)instanceIdString jsBundleString:(NSString*)jsBundleString @@ -950,10 +961,8 @@ - (void)_sendQueueLoop if ([tasks count] > 0 && execIns) { WXSDKInstance * execInstance = [WXSDKManager instanceForID:execIns]; - NSTimeInterval start = -1; - if (execInstance && !(execInstance.isJSCreateFinish)) { - start = CACurrentMediaTime()*1000; - } + NSTimeInterval start = CACurrentMediaTime()*1000; + if (execInstance.instanceJavaScriptContext && execInstance.bundleType) { [self callJSMethod:@"__WEEX_CALL_JAVASCRIPT__" args:@[execIns, tasks] onContext:execInstance.instanceJavaScriptContext completion:nil]; } else { @@ -964,6 +973,11 @@ - (void)_sendQueueLoop execInstance.performance.fsCallJsNum++; execInstance.performance.fsCallJsTime = execInstance.performance.fsCallJsTime+ diff; } + if (execInstance && !execInstance.apmInstance.isFSEnd) { + NSTimeInterval diff = CACurrentMediaTime()*1000 - start; + [execInstance.apmInstance updateFSDiffStats:KEY_PAGE_STATS_FS_CALL_JS_NUM withDiffValue:1]; + [execInstance.apmInstance updateFSDiffStats:KEY_PAGE_STATS_FS_CALL_JS_TIME withDiffValue:diff]; + } } if (hasTask) { diff --git a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.mm b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.mm index 36b82b3c0f..e6b6f725a5 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.mm +++ b/ios/sdk/WeexSDK/Sources/Component/WXCellComponent.mm @@ -54,6 +54,13 @@ - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDict if (attributes[@"zIndex"]) { _zIndex = [WXConvert NSString:attributes[@"zIndex"]]; } + if (!_isRecycle) { + [weexInstance.apmInstance updateDiffStats:KEY_PAGE_STATS_CELL_UN_RE_USE_NUM withDiffValue:1]; + //for protocol + //in iOS impl,cellReuse equal cellDataRecycle + //in Android, cellReuse is not equal cellDataRecycle + [weexInstance.apmInstance updateDiffStats:KEY_PAGE_STATS_CELL_DATA_UN_RECYCLE_NUM withDiffValue:1]; + } } return self; diff --git a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m index 7f177f3050..ef28440a45 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXImageComponent.m @@ -373,11 +373,12 @@ - (void)updateImage if (self.placeholdSrc) { newURL = [self.placeholdSrc copy]; WX_REWRITE_URL([self placeholdSrc], WXResourceTypeImage, self.weexInstance) - [[self imageLoader] setImageViewWithURL:(UIImageView*)self.view url:[NSURL URLWithString:newURL] placeholderImage:nil options:nil progress:nil completed:nil]; + NSDictionary* extInfo = @{@"instanceId":self.weexInstance.instanceId}; + [[self imageLoader] setImageViewWithURL:(UIImageView*)self.view url:[NSURL URLWithString:newURL] placeholderImage:nil options:extInfo progress:nil completed:nil]; } newURL = [[self imageSrc] copy]; WX_REWRITE_URL([self imageSrc], WXResourceTypeImage, self.weexInstance) - NSDictionary *userInfo = @{@"imageQuality":@(self.imageQuality), @"imageSharp":@(self.imageSharp), @"blurRadius":@(self.blurRadius)}; + NSDictionary *userInfo = @{@"imageQuality":@(self.imageQuality), @"imageSharp":@(self.imageSharp), @"blurRadius":@(self.blurRadius),@"instanceId":self.weexInstance.instanceId}; [[self imageLoader] setImageViewWithURL:(UIImageView*)self.view url:[NSURL URLWithString:newURL] placeholderImage:nil options:userInfo progress:^(NSInteger receivedSize, NSInteger expectedSize) { // progress when loading image } completed:^(UIImage *image, NSError *error, WXImageLoaderCacheType cacheType, NSURL *imageURL) { @@ -395,7 +396,7 @@ - (void)updateImage if (strongSelf.placeholdSrc) { NSString *newURL = [strongSelf.placeholdSrc copy]; WX_REWRITE_URL([strongSelf placeholdSrc], WXResourceTypeImage, strongSelf.weexInstance) - [[strongSelf imageLoader] setImageViewWithURL:(UIImageView*)strongSelf.view url:[NSURL URLWithString:newURL] placeholderImage:nil options:nil progress:nil completed:nil]; + [[strongSelf imageLoader] setImageViewWithURL:(UIImageView*)strongSelf.view url:[NSURL URLWithString:newURL] placeholderImage:nil options:@{@"instanceId":strongSelf.weexInstance.instanceId} progress:nil completed:nil]; return; } } @@ -419,8 +420,9 @@ - (void)updateImage if (!error && image && strongSelf.view) { double imageSize = image.size.width * image.scale * image.size.height * image.scale; double viewSize = strongSelf.view.frame.size.height * strongSelf.view.frame.size.width; - if (imageSize > viewSize) { + if (imageSize > viewSize+1) { self.weexInstance.performance.imgWrongSizeNum++; + [self.weexInstance.apmInstance updateDiffStats:KEY_PAGE_STATS_WRONG_IMG_SIZE_COUNT withDiffValue:1]; } } }]; @@ -465,7 +467,10 @@ - (void)updatePlaceHolderWithFailedBlock:(void(^)(NSString *, NSError *))downloa WX_REWRITE_URL(self.placeholdSrc, WXResourceTypeImage, self.weexInstance) __weak typeof(self) weakSelf = self; - self.placeholderOperation = [[self imageLoader] downloadImageWithURL:newURL imageFrame:self.calculatedFrame userInfo:nil completed:^(UIImage *image, NSError *error, BOOL finished) { + self.placeholderOperation = [[self imageLoader] downloadImageWithURL:newURL imageFrame:self.calculatedFrame + userInfo:@{@"instanceId":self.weexInstance.instanceId} + completed:^(UIImage *image, NSError *error, BOOL finished) + { dispatch_async(dispatch_get_main_queue(), ^{ __strong typeof(self) strongSelf = weakSelf; UIImage *viewImage = ((UIImageView *)strongSelf.view).image; @@ -502,7 +507,7 @@ - (void)updateContentImageWithFailedBlock:(void(^)(NSString *, NSError *))downlo } WXLogDebug(@"Updating image:%@, component:%@", self.imageSrc, self.ref); - NSDictionary *userInfo = @{@"imageQuality":@(self.imageQuality), @"imageSharp":@(self.imageSharp), @"blurRadius":@(self.blurRadius)}; + NSDictionary *userInfo = @{@"imageQuality":@(self.imageQuality), @"imageSharp":@(self.imageSharp), @"blurRadius":@(self.blurRadius),@"instanceId":self.weexInstance.instanceId}; NSString * newURL = [imageSrc copy]; WX_REWRITE_URL(imageSrc, WXResourceTypeImage, self.weexInstance) __weak typeof(self) weakSelf = self; diff --git a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.mm b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.mm index 056ca4ed16..4a876db8fc 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.mm +++ b/ios/sdk/WeexSDK/Sources/Component/WXScrollerComponent.mm @@ -173,6 +173,10 @@ -(instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDicti _shouldRemoveScrollerListener = shouldRemoveScrollerListener; } + //may be list + if ([@"scroller" isEqualToString:type]) { + [weexInstance.apmInstance updateDiffStats:KEY_PAGE_STATS_SCROLLER_NUM withDiffValue:1]; + } } return self; diff --git a/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m index 82b2be5d9b..cf3a5fc681 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXVideoComponent.m @@ -199,7 +199,10 @@ - (void)setPosterURL:(NSURL *)posterURL { [self cancelImage]; __weak typeof(self) weakSelf = self; - weakSelf.imageOperation = [[self imageLoader] downloadImageWithURL:posterURL.absoluteString imageFrame:self.posterImageView.frame userInfo:nil completed:^(UIImage *image, NSError *error, BOOL finished) { + weakSelf.imageOperation = [[self imageLoader] downloadImageWithURL:posterURL.absoluteString imageFrame:self.posterImageView.frame + userInfo:@{@"instanceId":self.weexSDKInstance.instanceId} + completed:^(UIImage *image, NSError *error, BOOL finished) + { dispatch_async(dispatch_get_main_queue(), ^{ __strong typeof(self) strongSelf = weakSelf; if (!error) { diff --git a/ios/sdk/WeexSDK/Sources/Handler/WXNavigationDefaultImpl.m b/ios/sdk/WeexSDK/Sources/Handler/WXNavigationDefaultImpl.m index d57bf8bb9b..5f3383510b 100644 --- a/ios/sdk/WeexSDK/Sources/Handler/WXNavigationDefaultImpl.m +++ b/ios/sdk/WeexSDK/Sources/Handler/WXNavigationDefaultImpl.m @@ -284,7 +284,7 @@ - (UIView *)barButton:(NSDictionary *)param position:(WXNavigationItemPosition)p button.position = position; [button addTarget:self action:@selector(onClickBarButton:) forControlEvents:UIControlEventTouchUpInside]; - [[self imageLoader] downloadImageWithURL:icon imageFrame:CGRectMake(0, 0, 25, 25) userInfo:nil completed:^(UIImage *image, NSError *error, BOOL finished) { + [[self imageLoader] downloadImageWithURL:icon imageFrame:CGRectMake(0, 0, 25, 25) userInfo:@{@"instanceId":self.weexInstance.instanceId} completed:^(UIImage *image, NSError *error, BOOL finished) { dispatch_async(dispatch_get_main_queue(), ^{ [button setBackgroundImage:image forState:UIControlStateNormal]; [button setBackgroundImage:image forState:UIControlStateHighlighted]; diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm index 1e4be38240..83c7986134 100644 --- a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm +++ b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.mm @@ -130,6 +130,7 @@ - (void)_frameDidCalculated:(BOOL)isChanged CGFloat mainScreenHeight = [[UIScreen mainScreen] bounds].size.height; if (mainScreenHeight/2 < _calculatedFrame.size.height && mainScreenWidth/2 < _calculatedFrame.size.width) { [self weexInstance].performance.cellExceedNum++; + [self.weexInstance.apmInstance updateFSDiffStats:KEY_PAGE_STATS_CELL_EXCEED_NUM withDiffValue:1]; } } diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m index 3a9e27e020..ebbc95c39b 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m @@ -351,6 +351,10 @@ - (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)ty { instance.performance.fsCallEventNum++; } + if (instance && !instance.apmInstance.isFSEnd) { + [instance.apmInstance updateFSDiffStats:KEY_PAGE_STATS_FS_CALL_EVENT_NUM withDiffValue:1]; + } + WXCallJSMethod *method = [[WXCallJSMethod alloc] initWithModuleName:nil methodName:@"fireEvent" arguments:args instance:instance]; [self callJsMethod:method]; } diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm index a3510a697b..43622dca68 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm +++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm @@ -296,6 +296,7 @@ - (void)_recursivelyAddComponent:(NSDictionary *)componentData toSupercomponent: [supercomponent _insertSubcomponent:component atIndex:index]; + [supercomponent.weexInstance.apmInstance updateMaxStats:KEY_PAGE_STATS_MAX_COMPONENT_NUM curMaxValue:[supercomponent.weexInstance numberOfComponents]]; // use _lazyCreateView to forbid component like cell's view creating if(supercomponent && component && supercomponent->_lazyCreateView) { component->_lazyCreateView = YES; @@ -396,6 +397,7 @@ - (void)recordMaximumVirtualDom:(WXComponent*) component maxDeep++; component = component.supercomponent; } + [self.weexInstance.apmInstance updateMaxStats:KEY_PAGE_STATS_MAX_DEEP_DOM curMaxValue:maxDeep]; if(maxDeep > [self weexInstance].performance.maxVdomDeep) { [self weexInstance].performance.maxVdomDeep = maxDeep; diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h index f987d89376..1e333c796b 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.h @@ -23,6 +23,7 @@ #import "WXResourceResponse.h" #import "WXResourceRequest.h" #import "WXBridgeProtocol.h" +#import "WXApmForInstance.h" extern NSString *const bundleUrlOptionKey; @@ -187,6 +188,7 @@ typedef NS_ENUM(NSInteger, WXErrorCode) {//error.code */ @property (nonatomic, copy) BOOL (^onRenderTerminateWhenJSDownloadedFinish)(WXResourceResponse *response,WXResourceRequest *request,NSData *data, NSError* error); +@property(nonatomic,strong) NSDictionary* continerInfo; /** * the frame of current instance. @@ -285,7 +287,6 @@ typedef NS_ENUM(NSInteger, WXErrorCode) {//error.code */ - (NSUInteger)numberOfComponents; - /** * check whether the module eventName is registered */ @@ -315,12 +316,18 @@ typedef NS_ENUM(NSInteger, WXErrorCode) {//error.code @property (nonatomic, strong) NSString *bizType; @property (nonatomic, strong) NSString *pageName; @property (nonatomic, weak) id pageObject; +//Deprecated, use @WXApmForInstance @property (nonatomic, strong) NSMutableDictionary *performanceDict; +@property (nonatomic ,strong) WXApmForInstance* apmInstance; + + /** * Deprecated */ + + @property (nonatomic, strong) NSDictionary *properties DEPRECATED_MSG_ATTRIBUTE(); @property (nonatomic, assign) NSTimeInterval networkTime DEPRECATED_MSG_ATTRIBUTE(); @property (nonatomic, copy) void (^updateFinish)(UIView *); diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m index db08941d67..7855f50acb 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m @@ -120,6 +120,7 @@ - (instancetype)init _performanceCommit = NO; _performance = [[WXPerformance alloc] init]; + _apmInstance = [[WXApmForInstance alloc] init]; id configCenter = [WXSDKEngine handlerForProtocol:@protocol(WXConfigCenterProtocol)]; if ([configCenter respondsToSelector:@selector(configForKey:defaultValue:isDefault:)]) { @@ -216,9 +217,9 @@ - (void)renderWithURL:(NSURL *)url options:(NSDictionary *)options data:(id)data WXLogError(@"Url must be passed if you use renderWithURL"); return; } + [self.apmInstance startRecord:self.instanceId]; self.needValidate = [[WXHandlerFactory handlerForProtocol:@protocol(WXValidateProtocol)] needValidate:url]; - WXResourceRequest *request = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeMainBundle referrer:@"" cachePolicy:NSURLRequestUseProtocolCachePolicy]; [self _renderWithRequest:request options:options data:data]; [WXTracingManager startTracingWithInstanceId:self.instanceId ref:nil className:nil name:WXTNetworkHanding phase:WXTracingBegin functionName:@"renderWithURL" options:@{@"bundleUrl":url?[url absoluteString]:@"",@"threadName":WXTMainThread}]; @@ -245,6 +246,7 @@ - (void)_renderWithMainBundleString:(NSString *)mainBundleString return; } self.performance.renderTimeOrigin = CACurrentMediaTime()*1000; + [self.apmInstance onStage:KEY_PAGE_STAGES_RENDER_ORGIGIN]; if (![WXUtility isBlankString:self.pageName]) { WXLog(@"Start rendering page:%@", self.pageName); @@ -299,10 +301,12 @@ - (void)_renderWithMainBundleString:(NSString *)mainBundleString _needDestroy = YES; _mainBundleString = mainBundleString; if ([self _handleConfigCenter]) { - NSError * error = [NSError errorWithDomain:WX_ERROR_DOMAIN code:9999 userInfo:nil]; + int wxErrorCode = 9999; + NSError * error = [NSError errorWithDomain:WX_ERROR_DOMAIN code:wxErrorCode userInfo:nil]; if (self.onFailed) { self.onFailed(error); } + [self.apmInstance setProperty:KEY_PROPERTIES_ERROR_CODE withValue:[@(wxErrorCode) stringValue]]; return; } @@ -380,8 +384,10 @@ - (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *) WX_MONITOR_INSTANCE_PERF_START(WXPTJSDownload, self); __weak typeof(self) weakSelf = self; _mainBundleLoader = [[WXResourceLoader alloc] initWithRequest:request];; + [self.apmInstance onStage:KEY_PAGE_STAGES_DOWN_BUNDLE_START]; _mainBundleLoader.onFinished = ^(WXResourceResponse *response, NSData *data) { __strong typeof(weakSelf) strongSelf = weakSelf; + [strongSelf.apmInstance onStage:KEY_PAGE_STAGES_DOWN_BUNDLE_END]; NSError *error = nil; if ([response isKindOfClass:[NSHTTPURLResponse class]] && ((NSHTTPURLResponse *)response).statusCode != 200) { error = [NSError errorWithDomain:WX_ERROR_DOMAIN @@ -399,6 +405,7 @@ - (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *) if (error) { WXJSExceptionInfo * jsExceptionInfo = [[WXJSExceptionInfo alloc] initWithInstanceId:@"" bundleUrl:[request.URL absoluteString] errorCode:[NSString stringWithFormat:@"%d", WX_KEY_EXCEPTION_JS_DOWNLOAD] functionName:@"_renderWithRequest:options:data:" exception:[error localizedDescription] userInfo:nil]; [WXExceptionUtils commitCriticalExceptionRT:jsExceptionInfo]; + [strongSelf.apmInstance setProperty:KEY_PROPERTIES_ERROR_CODE withValue:[@(WX_KEY_EXCEPTION_JS_DOWNLOAD) stringValue]]; return; } @@ -412,18 +419,24 @@ - (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *) if (strongSelf.onFailed) { strongSelf.onFailed(error); } + [strongSelf.apmInstance setProperty:KEY_PROPERTIES_ERROR_CODE withValue:[@(WX_KEY_EXCEPTION_JS_DOWNLOAD) stringValue]]; return; } NSString *jsBundleString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; if (!jsBundleString) { WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, WX_ERR_JSBUNDLE_STRING_CONVERT, @"data converting to string failed.", strongSelf.pageName) + [strongSelf.apmInstance setProperty:KEY_PROPERTIES_ERROR_CODE withValue:[@(WX_ERR_JSBUNDLE_STRING_CONVERT) stringValue]]; return; } if (!strongSelf.userInfo) { strongSelf.userInfo = [NSMutableDictionary new]; } - strongSelf.userInfo[@"jsMainBundleStringContentLength"] = @([jsBundleString length]); + + NSUInteger bundleSize = [jsBundleString length]; + [strongSelf.apmInstance updateDiffStats:KEY_PAGE_STATS_BUNDLE_SIZE withDiffValue:bundleSize]; + + strongSelf.userInfo[@"jsMainBundleStringContentLength"] = @(bundleSize); strongSelf.userInfo[@"jsMainBundleStringContentMd5"] = [WXUtility md5:jsBundleString]; WX_MONITOR_SUCCESS_ON_PAGE(WXMTJSDownload, strongSelf.pageName); @@ -442,13 +455,16 @@ - (void)_renderWithRequest:(WXResourceRequest *)request options:(NSDictionary *) }; _mainBundleLoader.onFailed = ^(NSError *loadError) { + [weakSelf.apmInstance onStage:KEY_PAGE_STAGES_DOWN_BUNDLE_END]; NSString *errorMessage = [NSString stringWithFormat:@"Request to %@ occurs an error:%@", request.URL, loadError.localizedDescription]; - - WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, [loadError.domain isEqualToString:NSURLErrorDomain] && loadError.code == NSURLErrorNotConnectedToInternet ? WX_ERR_NOT_CONNECTED_TO_INTERNET : WX_ERR_JSBUNDLE_DOWNLOAD, errorMessage, weakSelf.pageName); + long wxErrorCode = [loadError.domain isEqualToString:NSURLErrorDomain] && loadError.code == NSURLErrorNotConnectedToInternet ? WX_ERR_NOT_CONNECTED_TO_INTERNET : WX_ERR_JSBUNDLE_DOWNLOAD; + + WX_MONITOR_FAIL_ON_PAGE(WXMTJSDownload, wxErrorCode, errorMessage, weakSelf.pageName); if (weakSelf.onFailed) { weakSelf.onFailed(error); } + [weakSelf.apmInstance setProperty:KEY_PROPERTIES_ERROR_CODE withValue:[@(wxErrorCode) stringValue]]; }; [_mainBundleLoader start]; @@ -481,6 +497,7 @@ - (void)refreshInstance:(id)data - (void)destroyInstance { + [self.apmInstance endRecord]; NSString *url = @""; if([WXPrerenderManager isTaskExist:[self.scriptURL absoluteString]]) { url = [self.scriptURL absoluteString]; diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_performance.h b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_performance.h index 855997b958..c696fe7d8d 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_performance.h +++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_performance.h @@ -17,6 +17,8 @@ * under the License. */ +//Deprecated, use @WXApmForInstance + #import "WXSDKInstance.h" #import "WXImageComponent.h" @@ -71,6 +73,7 @@ @interface WXSDKInstance () @property (nonatomic, assign) BOOL isJSCreateFinish; +//Deprecated, use @WXApmForInstance @property (nonatomic,strong) WXPerformance* performance; @end diff --git a/ios/sdk/WeexSDK/Sources/Module/WXTimerModule.m b/ios/sdk/WeexSDK/Sources/Module/WXTimerModule.m index 0827b63bfc..be156baf3c 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXTimerModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXTimerModule.m @@ -57,6 +57,19 @@ - (void)trigger [[WXSDKManager bridgeMgr] callBack:_weexInstance.instanceId funcId:_callbackID params:nil keepAlive:_shouldRepeat]; } ++ (void) checkExcuteInBack:(NSString*) instanceId +{ + //todo,if instance is nil or instance has detroy ,can't record timer in back..... + WXSDKInstance* instance = [WXSDKManager instanceForID:instanceId]; + if (nil == instance) { + return; + } + if (instance.state == WeexInstanceBackground || instance.state == WeexInstanceDisappear + || instance.state == WeexInstanceDestroy) { + [instance.apmInstance updateDiffStats:KEY_PAGE_TIMER_BACK_NUM withDiffValue:1]; + } +} + @end @implementation WXTimerModule diff --git a/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h b/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h index c50d40d92f..395535d513 100644 --- a/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h +++ b/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.h @@ -17,6 +17,7 @@ * under the License. */ + #import #import "WXDefine.h" #import "WXSDKError.h" @@ -95,6 +96,7 @@ NSError *error = [NSError errorWithDomain:WX_ERROR_DOMAIN \ #define WX_MONITOR_INSTANCE_PERF_IS_RECORDED(tag, instance) [WXMonitor performancePoint:tag isRecordedWithInstance:instance] #define WX_MONITOR_INSTANCE_PERF_COMMIT(instance) [WXMonitor performanceFinish:instance] +//DEPRECATED_ATTRIBUTE @interface WXMonitor : NSObject + (void)performancePoint:(WXPerformanceTag)tag willStartWithInstance:(WXSDKInstance *)instance; diff --git a/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.h b/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.h new file mode 100644 index 0000000000..466079be22 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.h @@ -0,0 +1,103 @@ +#import + +#pragma mark - const static string + +extern NSString* const WEEX_PAGE_TOPIC; + +/************** properties *****************/ +extern NSString* const KEY_PROPERTIES_ERROR_CODE; +extern NSString* const KEY_PAGE_PROPERTIES_LAUNCH_ID; +extern NSString* const KEY_PAGE_PROPERTIES_BIZ_ID; +extern NSString* const KEY_PAGE_PROPERTIES_JSLIB_VERSION; +extern NSString* const KEY_PAGE_PROPERTIES_WEEX_VERSION; +extern NSString* const KEY_PAGE_PROPERTIES_REQUEST_TYPE; +extern NSString* const KEY_PAGE_PROPERTIES_REQUEST_TYPE; +extern NSString* const KEY_PAGE_PROPERTIES_NET_TYPE; +extern NSString* const KEY_PAGE_PROPERTIES_CACHE_TYPE; +extern NSString* const KEY_PAGE_PROPERTIES_USE_MULTI_CONTEXT; +extern NSString* const KEY_PAGE_PROPERTIES_BUNDLE_TYPE; + +///************** stages *****************/ +extern NSString* const KEY_PAGE_STAGES_START; +extern NSString* const KEY_PAGE_STAGES_DOWN_BUNDLE_START; +extern NSString* const KEY_PAGE_STAGES_DOWN_BUNDLE_END; +extern NSString* const KEY_PAGE_STAGES_RENDER_ORGIGIN; +extern NSString* const KEY_PAGE_STAGES_LOAD_BUNDLE_START; +extern NSString* const KEY_PAGE_STAGES_LOAD_BUNDLE_END; +extern NSString* const KEY_PAGE_STAGES_FSRENDER; +extern NSString* const KEY_PAGE_STAGES_INTERACTION; +extern NSString* const KEY_PAGE_STAGES_DESTROY; + +///************** stats *****************/ +extern NSString* const KEY_PAGE_STATS_BUNDLE_SIZE; +extern NSString* const KEY_PAGE_STATS_FS_CALL_JS_TIME; +extern NSString* const KEY_PAGE_STATS_FS_CALL_JS_NUM; +extern NSString* const KEY_PAGE_STATS_FS_TIMER_NUM; +extern NSString* const KEY_PAGE_STATS_FS_CALL_NATIVE_TIME; +extern NSString* const KEY_PAGE_STATS_FS_CALL_NATIVE_NUM; +extern NSString* const KEY_PAGE_STATS_FS_CALL_EVENT_NUM; +extern NSString* const KEY_PAGE_STATS_FS_REQUEST_NUM; + +extern NSString* const KEY_PAGE_STATS_SCROLLER_NUM; +extern NSString* const KEY_PAGE_STATS_CELL_EXCEED_NUM; +extern NSString* const KEY_PAGE_STATS_CELL_UN_RE_USE_NUM; +extern NSString* const KEY_PAGE_STATS_CELL_DATA_UN_RECYCLE_NUM; + +extern NSString* const KEY_PAGE_STATS_MAX_DEEP_VIEW; +extern NSString* const KEY_PAGE_STATS_MAX_DEEP_DOM; +extern NSString* const KEY_PAGE_STATS_MAX_COMPONENT_NUM; +extern NSString* const KEY_PAGE_STATS_WRONG_IMG_SIZE_COUNT; +extern NSString* const KEY_PAGE_STATS_IMG_UN_RECYCLE_NUM; + +extern NSString* const KEY_PAGE_STATS_I_SCREEN_VIEW_COUNT; +extern NSString* const KEY_PAGE_STATS_I_ALL_VIEW_COUNT; + +extern NSString* const KEY_PAGE_STATS_I_COMPONENT_CREATE_COUNT; +extern NSString* const KEY_PAGE_ANIM_BACK_NUM; +extern NSString* const KEY_PAGE_TIMER_BACK_NUM; +extern NSString* const KEY_PAGE_STATS_ACTUAL_DOWNLOAD_TIME; + +extern NSString* const KEY_PAGE_STATS_IMG_LOAD_NUM; +extern NSString* const KEY_PAGE_STATS_IMG_LOAD_SUCCESS_NUM; +extern NSString* const KEY_PAGE_STATS_IMG_LOAD_FAIL_NUM; +extern NSString* const KEY_PAGE_STATS_NET_NUM; +extern NSString* const KEY_PAGE_STATS_NET_SUCCESS_NUM; +extern NSString* const KEY_PAGE_STATS_NET_FAIL_NUM; + +///************** value *****************/ +extern NSString* const VALUE_ERROR_CODE_DEFAULT; + + + +@interface WXApmForInstance : NSObject + +@property (nonatomic, assign) bool isFSEnd; + +#pragma mark - basic method + +- (void) onEvent:(NSString *)name withValue:(id)value; +- (void) onStage:(NSString *)name; +- (void) setProperty:(NSString *)name withValue:(id)value; +- (void) setStatistic:(NSString *)name withValue:(double)value; + +#pragma mark - instance record + +- (void) startRecord:(NSString*) instanceId; +- (void) endRecord; +- (void) arriveFSRenderTime; +- (void) updateFSDiffStats:(NSString *)name withDiffValue:(double)diff; +- (void) updateDiffStats:(NSString *)name withDiffValue:(double)diff; +- (void) updateMaxStats:(NSString *)name curMaxValue:(double)maxValue; +- (void) updateExtInfo:(NSDictionary*) extInfo; + + +#pragma mark - called by IWXHttpAdapter implementer + +- (void) actionNetRequest; +- (void) actionNetRequestResult:(bool)succeed withErrorCode:(NSString*)errorCode; + +#pragma mark - called by IWXImgLoaderAdapter implementer +- (void) actionImgLoad; +- (void) actionImgLoadResult:(bool)succeed withErrorCode:(NSString*)errorCode; + +@end diff --git a/ios/sdk/WeexSDK/Sources/Performance/WXInstanceApm.m b/ios/sdk/WeexSDK/Sources/Performance/WXInstanceApm.m new file mode 100644 index 0000000000..ab3e914e03 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Performance/WXInstanceApm.m @@ -0,0 +1,289 @@ +#import "WXApmForInstance.h" +#import "WXApmProtocol.h" +#import "WXHandlerFactory.h" +#import "WXSDKManager.h" +#import "WXAppConfiguration.h" +#import "WXUtility.h" + + +#pragma mark - const static string + +NSString* const WEEX_PAGE_TOPIC = @"weex_page"; + +/************** properties *****************/ +NSString* const KEY_PROPERTIES_ERROR_CODE = @"wxErrorCode"; +NSString* const KEY_PAGE_PROPERTIES_LAUNCH_ID = @"wxLaunchId"; +NSString* const KEY_PAGE_PROPERTIES_BIZ_ID = @"wxBizID"; +NSString* const KEY_PAGE_PROPERTIES_JSLIB_VERSION = @"wxJSLibVersion"; +NSString* const KEY_PAGE_PROPERTIES_WEEX_VERSION = @"wxSDKVersion"; +NSString* const KEY_PAGE_PROPERTIES_REQUEST_TYPE = @"wxRequestType"; +NSString* const KEY_PAGE_PROPERTIES_NET_TYPE = @"wxNetType"; +NSString* const KEY_PAGE_PROPERTIES_CACHE_TYPE = @"wxCacheType"; +NSString* const KEY_PAGE_PROPERTIES_USE_MULTI_CONTEXT = @"wxUseMultiContext"; +NSString* const KEY_PAGE_PROPERTIES_BUNDLE_TYPE = @"wxBundleType"; + +///************** stages *****************/ +NSString* const KEY_PAGE_STAGES_START = @"wxRecordStart"; +NSString* const KEY_PAGE_STAGES_DOWN_BUNDLE_START = @"wxStartDownLoadBundle"; +NSString* const KEY_PAGE_STAGES_DOWN_BUNDLE_END = @"wxEndDownLoadBundle"; +NSString* const KEY_PAGE_STAGES_RENDER_ORGIGIN = @"wxRenderTimeOrigin"; +NSString* const KEY_PAGE_STAGES_LOAD_BUNDLE_START = @"wxStartLoadBundle"; +NSString* const KEY_PAGE_STAGES_LOAD_BUNDLE_END = @"wxEndLoadBundle"; +NSString* const KEY_PAGE_STAGES_FSRENDER = @"wxFsRender"; +NSString* const KEY_PAGE_STAGES_INTERACTION = @"wxInteraction"; +NSString* const KEY_PAGE_STAGES_DESTROY = @"wxDestroy"; + +///************** stats *****************/ +NSString* const KEY_PAGE_STATS_BUNDLE_SIZE = @"wxBundleSize"; +NSString* const KEY_PAGE_STATS_FS_CALL_JS_TIME = @"wxFSCallJsTotalTime"; +NSString* const KEY_PAGE_STATS_FS_CALL_JS_NUM = @"wxFSCallJsTotalNum"; +NSString* const KEY_PAGE_STATS_FS_TIMER_NUM = @"wxFSTimerCount"; +NSString* const KEY_PAGE_STATS_FS_CALL_NATIVE_TIME = @"wxFSCallNativeTotalTime"; +NSString* const KEY_PAGE_STATS_FS_CALL_NATIVE_NUM = @"wxFSCallNativeTotalNum"; +NSString* const KEY_PAGE_STATS_FS_CALL_EVENT_NUM = @"wxFSCallEventTotalNum"; +NSString* const KEY_PAGE_STATS_FS_REQUEST_NUM = @"wxFSRequestNum"; + +NSString* const KEY_PAGE_STATS_SCROLLER_NUM = @"wxScrollerCount"; +NSString* const KEY_PAGE_STATS_CELL_EXCEED_NUM = @"wxCellExceedNum"; +NSString* const KEY_PAGE_STATS_CELL_UN_RE_USE_NUM = @"wxCellUnReUseCount"; +NSString* const KEY_PAGE_STATS_CELL_DATA_UN_RECYCLE_NUM = @"wxCellDataUnRecycleCount"; + +NSString* const KEY_PAGE_STATS_MAX_DEEP_VIEW = @"wxMaxDeepViewLayer"; +NSString* const KEY_PAGE_STATS_MAX_DEEP_DOM = @"wxMaxDeepVDomLayer"; +NSString* const KEY_PAGE_STATS_MAX_COMPONENT_NUM = @"wxMaxComponentCount"; +NSString* const KEY_PAGE_STATS_WRONG_IMG_SIZE_COUNT = @"wxWrongImgSizeCount"; +NSString* const KEY_PAGE_STATS_IMG_UN_RECYCLE_NUM = @"wxImgUnRecycleCount"; + +NSString* const KEY_PAGE_STATS_I_SCREEN_VIEW_COUNT = @"wxInteractionScreenViewCount"; +NSString* const KEY_PAGE_STATS_I_ALL_VIEW_COUNT = @"wxInteractionAllViewCount"; + +NSString* const KEY_PAGE_STATS_I_COMPONENT_CREATE_COUNT = @"wxInteractionComponentCreateCount"; +NSString* const KEY_PAGE_ANIM_BACK_NUM = @"wxAnimationInBackCount"; +NSString* const KEY_PAGE_TIMER_BACK_NUM = @"wxTimerInBackCount"; +NSString* const KEY_PAGE_STATS_ACTUAL_DOWNLOAD_TIME = @"wxActualNetworkTime"; + +NSString* const KEY_PAGE_STATS_IMG_LOAD_NUM = @"wxImgLoadCount"; +NSString* const KEY_PAGE_STATS_IMG_LOAD_SUCCESS_NUM = @"wxImgLoadSuccessCount"; +NSString* const KEY_PAGE_STATS_IMG_LOAD_FAIL_NUM = @"wxImgLoadFailCount"; +NSString* const KEY_PAGE_STATS_NET_NUM = @"wxNetworkRequestCount"; +NSString* const KEY_PAGE_STATS_NET_SUCCESS_NUM = @"wxNetworkRequestSuccessCount"; +NSString* const KEY_PAGE_STATS_NET_FAIL_NUM = @"wxNetworkRequestFailCount"; + +///************** value *****************/ +NSString* const VALUE_ERROR_CODE_DEFAULT = @"0"; + +@interface WXApmForInstance () +@property (nonatomic,strong) id apmProtocolInstance; +@property (nonatomic,strong) NSString* instanceId; +@property (nonatomic,strong) NSMutableDictionary* recordStatsMap; +@end + +@implementation WXApmForInstance + + +- (instancetype) init +{ + self = [super init]; + if (self) { + id generater = [WXHandlerFactory handlerForProtocol:@protocol(WXApmGeneratorProtocol)]; + _apmProtocolInstance = [generater gengratorApmInstance:WEEX_PAGE_TOPIC]; + _recordStatsMap = [[NSMutableDictionary alloc] init]; + } + return self; +} + +- (void) onEvent:(NSString *)name withValue:(id)value +{ + if (nil == _apmProtocolInstance) { + return; + } + [self.apmProtocolInstance onEvent:name withValue:value]; +} + +- (void) onStage:(NSString *)name +{ + if (nil == _apmProtocolInstance) { + return; + } + [self.apmProtocolInstance onStage:name withValue:[WXUtility getUnixCurrentTimeMillis]]; +} + +- (void) setProperty:(NSString *)name withValue:(id)value +{ + if (nil == _apmProtocolInstance) { + return; + } + [self.apmProtocolInstance addProperty:name withValue:value]; +} + +- (void) setStatistic:(NSString *)name withValue:(double)value +{ + if (nil == _apmProtocolInstance) { + return; + } + [self.apmProtocolInstance addStatistic:name withValue:value]; +} + +#pragma mark - instance record + +- (void) startRecord:(NSString*) instanceId +{ + if (nil == _apmProtocolInstance) { + return; + } + _instanceId = instanceId; + + [self.apmProtocolInstance onStart:instanceId topic:WEEX_PAGE_TOPIC]; + [self onStage:KEY_PAGE_STAGES_START]; + WXSDKInstance* instance = [WXSDKManager instanceForID:instanceId]; + if (nil != instance) { + for (NSString* key in instance.continerInfo) { + id value = [instance.continerInfo objectForKey:key]; + [self setProperty:key withValue:value]; + } + } + NSString* pageUrl = instance.scriptURL.absoluteString; + pageUrl = nil == pageUrl || [@"" isEqualToString:pageUrl]?@"unKnowUrl":pageUrl; + + [self setProperty:KEY_PAGE_PROPERTIES_BIZ_ID withValue:pageUrl]; + [self setProperty:KEY_PROPERTIES_ERROR_CODE withValue:VALUE_ERROR_CODE_DEFAULT]; + [self setProperty:KEY_PAGE_PROPERTIES_JSLIB_VERSION withValue:[WXAppConfiguration JSFrameworkVersion]]; + [self setProperty:KEY_PAGE_PROPERTIES_WEEX_VERSION withValue:WX_SDK_VERSION]; + + //for apm protocl + //iOS/Android we default recycle img when imgView disapper form screen + //but in Android ,js can switch recycle or not + [self updateDiffStats:KEY_PAGE_STATS_IMG_UN_RECYCLE_NUM withDiffValue:0]; +} + +- (void) endRecord; +{ + if (nil == _apmProtocolInstance) { + return; + } + + [self onStage:KEY_PAGE_STAGES_DESTROY]; + [self.apmProtocolInstance onEnd]; +} + +- (void) arriveFSRenderTime +{ + if (nil == _apmProtocolInstance || self.isFSEnd) { + return; + } + self.isFSEnd = true; + [self onStage:KEY_PAGE_STAGES_FSRENDER]; +} + +- (void) updateFSDiffStats:(NSString *)name withDiffValue:(double)diff +{ + if (nil == _apmProtocolInstance || self.isFSEnd) { + return; + } + [self updateDiffStats:name withDiffValue:diff]; +} + +- (void) updateDiffStats:(NSString *)name withDiffValue:(double)diff +{ + if (nil == _apmProtocolInstance) { + return; + } + NSNumber* preNumber = [self.recordStatsMap objectForKey:name]; + double preVal = nil == preNumber?0:preNumber.doubleValue; + double currentVal = preVal + diff; + [self.recordStatsMap setObject:@(currentVal) forKey:name]; + [self setStatistic:name withValue:currentVal]; +} + +- (void) updateMaxStats:(NSString *)name curMaxValue:(double)currentValue +{ + if (nil == _apmProtocolInstance) { + return; + } + NSNumber* maxNumber = [self.recordStatsMap objectForKey:name]; + double maxVal = nil == maxNumber?0:maxNumber.doubleValue; + + if (maxVal < currentValue) { + maxVal = currentValue; + [self.recordStatsMap setObject:@(maxVal) forKey:name]; + [self setStatistic:name withValue:maxVal]; + } +} + +- (void) updateExtInfo:(NSDictionary*) extInfo +{ + if (nil == _apmProtocolInstance || nil == extInfo) { + return; + } + + id wxRequestType = [extInfo objectForKey:KEY_PAGE_PROPERTIES_REQUEST_TYPE]; + if (nil != wxRequestType && [wxRequestType isKindOfClass: NSString.class]) { + [self setProperty:KEY_PAGE_PROPERTIES_REQUEST_TYPE withValue:wxRequestType]; + } + + id wxNetType = [extInfo objectForKey:KEY_PAGE_PROPERTIES_NET_TYPE]; + if (nil != wxRequestType && [wxNetType isKindOfClass: NSString.class]) { + [self setProperty:KEY_PAGE_PROPERTIES_NET_TYPE withValue:wxRequestType]; + } + + id wxCacheType = [extInfo objectForKey:KEY_PAGE_PROPERTIES_CACHE_TYPE]; + if (nil != wxCacheType && [wxCacheType isKindOfClass: NSString.class]) { + [self setProperty:KEY_PAGE_PROPERTIES_CACHE_TYPE withValue:wxCacheType]; + } + + id wxNetLibDownBundleTime = [extInfo objectForKey:KEY_PAGE_STATS_ACTUAL_DOWNLOAD_TIME]; + if (nil != wxNetLibDownBundleTime && [wxNetLibDownBundleTime isKindOfClass: NSNumber.class]) { + double value = ((NSNumber *)wxNetLibDownBundleTime).doubleValue; + [self setStatistic:KEY_PAGE_PROPERTIES_CACHE_TYPE withValue:value]; + } +} + +#pragma mark - called by IWXHttpAdapter implementer + +- (void) actionNetRequest +{ + if (nil == _apmProtocolInstance) { + return; + } + if (!self.isFSEnd) { + [self updateFSDiffStats:KEY_PAGE_STATS_FS_REQUEST_NUM withDiffValue:1]; + } + [self updateDiffStats:KEY_PAGE_STATS_NET_NUM withDiffValue:1]; +} + +- (void) actionNetRequestResult:(bool)succeed withErrorCode:(NSString*)errorCode +{ + if (nil == _apmProtocolInstance) { + return; + } + if (succeed) { + [self updateDiffStats:KEY_PAGE_STATS_NET_SUCCESS_NUM withDiffValue:1]; + } else { + [self updateDiffStats:KEY_PAGE_STATS_NET_FAIL_NUM withDiffValue:1]; + } +} + +#pragma mark - called by IWXImgLoaderAdapter implementer + +- (void) actionImgLoad +{ + if (nil == _apmProtocolInstance) { + return; + } + [self updateDiffStats:KEY_PAGE_STATS_IMG_LOAD_NUM withDiffValue:1]; +} + +- (void) actionImgLoadResult:(bool)succeed withErrorCode:(NSString*)errorCode +{ + if (nil == _apmProtocolInstance) { + return; + } + if (succeed) { + [self updateDiffStats:KEY_PAGE_STATS_IMG_LOAD_SUCCESS_NUM withDiffValue:1]; + } else { + [self updateDiffStats:KEY_PAGE_STATS_IMG_LOAD_FAIL_NUM withDiffValue:1]; + } +} + +@end + diff --git a/ios/sdk/WeexSDK/Sources/Protocol/WXApmProtocol.h b/ios/sdk/WeexSDK/Sources/Protocol/WXApmProtocol.h new file mode 100644 index 0000000000..a461edbc9f --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Protocol/WXApmProtocol.h @@ -0,0 +1,85 @@ + +#import +#import "WXAppMonitorProtocol.h" + + +@protocol WXApmProtocol + +/** + * start record + * + * @param instanceId instanceId + */ +@required +- (void) onStart:(NSString*)instanceId topic:(NSString*)topic; + +/** + * pause apm record (apm ext mem / fps) + */ +@required +- (void) pauseApmRecord; + +/** + * resume apm record (apm ext mem / fps) + */ +@required +- (void) resumeApmRecord; + +/** + * end record + */ +@required +- (void) onEnd; + +/** + * record event + */ +@required +- (void) onEvent:(NSString *)name withValue:(id)value; + +/** + * record stage + */ +@required +- (void) onStage:(NSString *)name withValue:(long)timestamp; + +/** + * record property + */ +@required +- (void) addProperty:(NSString *)name withValue:(id)value; + +/** + * record statistic + */ +@required +- (void) addStatistic:(NSString *)name withValue:(double)value; + +@required +- (void) onSubProcedureBegin:(NSString*)subProcedureName; + +@required +- (void) onSubProcedureEndSucceed:(NSString*)subProcedureName; + +@required +- (void) onSubProcedureEndFailed:(NSString*)subProcedureName; + +/** + * record biz properties + */ +@required +- (void) addBiz:(NSString *)bizID withValue:(NSDictionary *)properties; + +/** + * record biz stage + */ +@required +- (void) addBizStage:(NSString *)bizID withValue:(NSDictionary *)stage; + +@end + +@protocol WXApmGeneratorProtocol + +@required +- (id)gengratorApmInstance:(NSString *) type; +@end diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h index 9babd18338..a7a7abf5dd 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h @@ -493,4 +493,6 @@ BOOL WXFloatGreaterThanWithPrecision(CGFloat a,CGFloat b,double precision); + (BOOL)listSectionRowThreadSafe; ++ (long) getUnixCurrentTimeMillis; + @end diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m index d9f543384b..e063395844 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m @@ -969,6 +969,12 @@ + (NSData *_Nonnull)base64DictToData:(NSDictionary *_Nullable)base64Dict } return nil; } + ++ (long) getUnixCurrentTimeMillis +{ + return [[NSDate date] timeIntervalSince1970] * 1000; +} + @end diff --git a/ios/sdk/WeexSDK/Sources/WeexSDK.h b/ios/sdk/WeexSDK/Sources/WeexSDK.h index 5c03635a1f..fa1648b6ca 100644 --- a/ios/sdk/WeexSDK/Sources/WeexSDK.h +++ b/ios/sdk/WeexSDK/Sources/WeexSDK.h @@ -72,6 +72,8 @@ #import "WXBaseViewController.h" #import "WXAppMonitorProtocol.h" #import "WXAppConfiguration.h" +#import "WXApmProtocol.h" +#import "WXApmForInstance.h" #import "WXAnalyzerProtocol.h" #import "WXAnalyzerCenter.h" #import "WXAComponent.h"