You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by cx...@apache.org on 2018/11/29 08:09:34 UTC

[incubator-weex] branch master updated: [WEEX-661][iOS] update for weex dev-tool (#1751)

This is an automated email from the ASF dual-hosted git repository.

cxfeng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-weex.git


The following commit(s) were added to refs/heads/master by this push:
     new 943ec40  [WEEX-661][iOS] update for weex dev-tool (#1751)
943ec40 is described below

commit 943ec40e3c3cdb02c5ad1907e6168f8ff445bd71
Author: chen <lu...@users.noreply.github.com>
AuthorDate: Thu Nov 29 16:09:30 2018 +0800

    [WEEX-661][iOS] update for weex dev-tool (#1751)
    
    - transfer peformance info to devtool
     - show interactionView
     - add log switch of jsengin/jsfm/weexcore ,to analyze interactionTime
---
 ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h      |   1 +
 ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm     |   5 +
 ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm   |   6 +-
 ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m    |  10 +
 .../WeexSDK/Sources/Manager/WXComponentManager.mm  |   9 +
 ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m      |   2 +-
 .../Sources/Model/WXSDKInstance_performance.m      |  12 +-
 .../Sources/Monitor/WXAnalyzerCenter+Transfer.h    |   6 +-
 ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter.h |   3 +
 ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter.m | 238 +++++++++------------
 ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.m        |   7 +-
 .../WeexSDK/Sources/Performance/WXApmForInstance.h |   2 +-
 .../WeexSDK/Sources/Performance/WXApmForInstance.m |  91 +++++---
 13 files changed, 201 insertions(+), 191 deletions(-)

diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
index 1e05c2c..90b7fd1 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
@@ -202,6 +202,7 @@ namespace WeexCore
 + (void)registerComponentAffineType:(NSString *)type asType:(NSString *)baseType;
 
 + (BOOL)isComponentAffineType:(NSString *)type asType:(NSString *)baseType;
++ (void)registerCoreEnv:(NSString*)key withValue:(NSString*)value;
 
 @end
 
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
index 78d4b4d..a0ad6de 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
@@ -1217,4 +1217,9 @@ static void _convertToCString(id _Nonnull obj, void (^callback)(const char*))
     WeexCore::WeexCoreManager::Instance()->script_bridge()->core_side()->UpdateFinish([pageId UTF8String] ?: "", nullptr, 0, nullptr, 0);
 }
 
++ (void)registerCoreEnv:(NSString*)key withValue:(NSString*)value
+{
+    WeexCore::WeexCoreManager::Instance()->getPlatformBridge()->core_side()->RegisterCoreEnv([key UTF8String]?:"", [value UTF8String]?:"");
+}
+
 @end
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
index f6c5436..3652a0d 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXJSCoreBridge.mm
@@ -38,6 +38,7 @@
 #import "WXAppMonitorProtocol.h"
 #import "JSContext+Weex.h"
 #import "WXCoreBridge.h"
+#import "WXAnalyzerCenter.h"
 
 #import <dlfcn.h>
 
@@ -163,8 +164,9 @@
         NSDictionary *componentData = [element toDictionary];
         NSString *parentRef = [ref toString];
         NSInteger insertIndex = [[index toNumber] integerValue];
-        WXLogDebug(@"callAddElement...%@, %@, %@, %ld", instanceIdString, parentRef, componentData, (long)insertIndex);
-        
+        if (WXAnalyzerCenter.isInteractionLogOpen) {
+            WXLogDebug(@"wxInteractionAnalyzer : [jsengin][addElementStart],%@,%@",instanceIdString,componentData[@"ref"]);
+        }
         return [JSValue valueWithInt32:(int32_t)callAddElement(instanceIdString, parentRef, componentData, insertIndex) inContext:[JSContext currentContext]];
     };
     
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m b/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m
index 8827849..6877a9a 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXModuleMethod.m
@@ -27,6 +27,7 @@
 #import "WXSDKInstance_private.h"
 #import "WXHandlerFactory.h"
 #import "WXValidateProtocol.h"
+#import "WXAnalyzerCenter.h"
 
 @implementation WXModuleMethod
 
@@ -46,6 +47,9 @@
 
 - (NSInvocation *)invoke
 {
+    if ([WXAnalyzerCenter isInteractionLogOpen]) {
+        WXLogDebug(@"wxInteractionAnalyzer : [client][callnativemodulestart],%@,%@,%@",self.instance.instanceId,self.moduleName,self.methodName);
+    }
     if (self.instance.needValidate) {
         id<WXValidateProtocol> validateHandler = [WXHandlerFactory handlerForProtocol:@protocol(WXValidateProtocol)];
         if (validateHandler) {
@@ -103,6 +107,9 @@
     
     if (isSync) {
         [invocation invoke];
+        if ([WXAnalyzerCenter isInteractionLogOpen]) {
+            WXLogDebug(@"wxInteractionAnalyzer : [client][callnativemoduleEnd],%@,%@,%@",self.instance.instanceId,self.moduleName,self.methodName);
+        }
         return invocation;
     } else {
         [self _dispatchInvocation:invocation moduleInstance:moduleInstance];
@@ -130,6 +137,9 @@
     // dispatch to user specified queue or thread, default is main thread
     dispatch_block_t dispatchBlock = ^ (){
         [invocation invoke];
+        if ([WXAnalyzerCenter isInteractionLogOpen]) {
+            WXLogDebug(@"wxInteractionAnalyzer : [client][callnativemoduleEnd],%@,%@,%@",self.instance.instanceId,self.moduleName,self.methodName);
+        }
     };
     
     NSThread *targetThread = nil;
diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm
index 434ef36..53f2157 100644
--- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm
+++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.mm
@@ -41,6 +41,7 @@
 #import "WXComponent+Layout.h"
 #import "WXCoreBridge.h"
 #import "WXComponent_performance.h"
+#import "WXAnalyzerCenter.h"
 
 static NSThread *WXComponentThread;
 
@@ -272,6 +273,10 @@ static NSThread *WXComponentThread;
         WXLogWarning(@"addComponent,superRef from js never exit ! check JS action, supRef:%@", parentRef);
         return;
     }
+    if([WXAnalyzerCenter isInteractionLogOpen]){
+         WXLogDebug(@"wxInteractionAnalyzer: [client][addElementStart]%@,%@,%@",supercomponent.weexInstance.instanceId,type,ref);
+    }
+    
     supercomponent.weexInstance.apmInstance.hasAddView = YES;
     
     WXComponent *component = [self _buildComponent:ref type:type supercomponent:supercomponent styles:styles attributes:attributes events:events renderObject:renderObject];
@@ -314,6 +319,7 @@ static NSThread *WXComponentThread;
     }
     
     [self recordMaximumVirtualDom:component];
+    [component.weexInstance.apmInstance updateMaxStats:KEY_PAGE_STATS_MAX_COMPONENT_NUM curMaxValue:[_indexDict count]];
     
     if (!component->_isTemplate) {
         __weak typeof(self) weakSelf = self;
@@ -328,6 +334,9 @@ static NSThread *WXComponentThread;
             [WXTracingManager startTracingWithInstanceId:strongSelf.weexInstance.instanceId ref:ref className:nil name:type phase:WXTracingEnd functionName:@"addElement" options:@{@"threadName":WXTUIThread}];
         }];
     }
+    if([WXAnalyzerCenter isInteractionLogOpen]){
+        WXLogDebug(@"wxInteractionAnalyzer: [client][addElementEnd]%@,%@,%@",supercomponent.weexInstance.instanceId,type,ref);
+    }
 }
 
 - (void)moveComponent:(NSString *)ref toSuper:(NSString *)superRef atIndex:(NSInteger)index
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
index 2baee25..e455650 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance.m
@@ -191,7 +191,7 @@ typedef enum : NSUInteger {
         CGFloat screenHeight =  [[UIScreen mainScreen] bounds].size.height;
         if (screenHeight>0) {
             CGFloat pageRatio = frame.size.height/screenHeight *100;
-            self.apmInstance.wxPageRatio = pageRatio>100?100:pageRatio;
+            self.apmInstance.pageRatio = pageRatio>100?100:pageRatio;
         }
         WXPerformBlockOnMainThread(^{
             if (_rootView) {
diff --git a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_performance.m b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_performance.m
index a8002b9..db33597 100644
--- a/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_performance.m
+++ b/ios/sdk/WeexSDK/Sources/Model/WXSDKInstance_performance.m
@@ -27,6 +27,7 @@
 #import "WXCellComponent.h"
 #import "WXImageComponent.h"
 #import "WXUtility.h"
+#import "WXAnalyzerCenter+Transfer.h"
 
 @interface WXPerformance()
 @property (nonatomic, assign) bool hasRecordFsRenderTimeByPosition;
@@ -112,21 +113,16 @@
         return;
     }
     
-#ifdef DEBUG
-    WXLogDebug(@"onElementChange _-> size, count :%f,inScreen:%d, type:%@,attr:%@",
-          self.interactionAddCountRecord,
-          inScreen,
-          targetComponent.type,
-          targetComponent.attributes
-          );
-#endif
     if (!targetComponent.weexInstance.apmInstance.hasRecordFirstInterationView) {
         targetComponent.weexInstance.apmInstance.hasRecordFirstInterationView = YES;
         [targetComponent.weexInstance.apmInstance onStage:KEY_PAGE_STAGES_FIRST_INTERACTION_VIEW];
     }
+    [WXAnalyzerCenter transferInteractionInfo:targetComponent];
     [targetComponent.weexInstance.apmInstance onStage:KEY_PAGE_STAGES_INTERACTION];
     self.interactionLimitAddOpCount++;
     self.interactionAddCount = self.interactionAddCountRecord;
+    [targetComponent.weexInstance.apmInstance updateMaxStats:KEY_PAGE_STATS_I_SCREEN_VIEW_COUNT curMaxValue:self.interactionLimitAddOpCount];
+    [targetComponent.weexInstance.apmInstance updateMaxStats:KEY_PAGE_STATS_I_ALL_VIEW_COUNT curMaxValue:self.interactionAddCount];
     self.interactionTime = self.interactionTime < diff ? diff :self.interactionTime;
 }
 
diff --git a/ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter+Transfer.h b/ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter+Transfer.h
index c32ba6e..65b0fbe 100644
--- a/ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter+Transfer.h
+++ b/ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter+Transfer.h
@@ -24,10 +24,8 @@
 
 @interface WXAnalyzerCenter (Transfer)
 
-+(void) transDataOnState:(CommitState) timeState withInstaneId:(NSString *)instanceId data:(NSDictionary *)data ;
-
++ (void) transferPerformance:(NSString*)instanceId withType:(NSString*) type andKey:(NSString*) key andValue:(id)value;
++ (void) transferInteractionInfo:(WXComponent*)targetComponent;
 + (void) transErrorInfo:(WXJSExceptionInfo *)errorInfo;
 
-+ (BOOL) needTransfer;
-
 @end
diff --git a/ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter.h b/ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter.h
index 1e496a8..4b5a61b 100644
--- a/ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter.h
+++ b/ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter.h
@@ -31,4 +31,7 @@
 +(void) setOpen:(BOOL)isOpen;
 +(BOOL) isOpen;
 
++(void) switchInteractionLog:(BOOL) isOpen;
++(BOOL) isInteractionLogOpen;
+
 @end
diff --git a/ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter.m b/ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter.m
index 3e90096..186f774 100644
--- a/ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter.m
+++ b/ios/sdk/WeexSDK/Sources/Monitor/WXAnalyzerCenter.m
@@ -27,8 +27,18 @@
 #import "WXAnalyzerCenter.h"
 #import "WXAnalyzerCenter+Transfer.h"
 #import "WXUtility.h"
+#import "WXSDKInstance_performance.h"
+#import "WXCoreBridge.h"
+#import "WXBridgeManager.h"
+#import "WXBridgeContext.h"
+
+
+#define MODULE_WX_APM  @"wxapm"
 
 @interface WXAnalyzerCenter ()
+{
+    BOOL _interactionLogSwitch;
+}
 @property (nonatomic, strong) NSMutableArray<WXAnalyzerProtocol> *analyzerList;
 @property (nonatomic, assign) BOOL anzlyzerSwitch;
 @end
@@ -43,173 +53,105 @@
     dispatch_once(&once, ^{
         instance = [[WXAnalyzerCenter alloc] init];
         instance.analyzerList= [NSMutableArray<WXAnalyzerProtocol> new];
-        instance.anzlyzerSwitch = FALSE;
+        instance.anzlyzerSwitch = NO;
     });
 
     return instance;
 }
 
-+ (void) transDataOnState:(CommitState) timeState withInstaneId:(NSString *)instanceId data:(NSDictionary *)data
++ (void) transferPerformance:(NSString*)instanceId withType:(NSString*) type andKey:(NSString*) key andValue:(id)value
 {
     if (![self isOpen]) {
         return;
     }
-    if (!instanceId) {
-        return;
-    }
-    WXSDKInstance * instance = [WXSDKManager instanceForID:instanceId];
-    if (!instance) {
-        return;
-    }
 
-    NSDictionary *commitDimenKeys = [self getKeys:TRUE];
-    NSDictionary *commitMeasureKeys = [self getKeys:FALSE];
-    for(id key in data){
-       if([self checkDataWithSate:timeState checkKey:key limitDic:commitMeasureKeys]){
-           [self _transMeasureValue:instance key:key withVal:[data valueForKey:key]];
-       }else if([self checkDataWithSate:timeState checkKey:key limitDic:commitDimenKeys]){
-           [self _transDimenValue:instance key:key withVal:[data valueForKey:key]];
-       }else{
-           WXLogDebug(@"WXAnalyzerDataTransfer -> unKnowPerformanceKey :%@",key);
-       }
+    if ([self isInteractionLogOpen] && [type isEqualToString:@"stage"]) {
+        WXLogDebug(@"wxInteractionAnalyzer : [client][stage],%@,%@,%@",instanceId,key,value);
     }
-}
 
-+(BOOL) checkDataWithSate:(CommitState)timeState checkKey:(id)key limitDic:(NSDictionary *)limitDic
-{
-    if (!key || ![key isKindOfClass:[NSString class]]) {
-        return FALSE;
-    }
-   
-    if (![limitDic objectForKey:key]) {
-        return FALSE;
+    NSMutableArray* analyzerList = [self getAnalyzerList];
+    if (nil == analyzerList) {
+        return;
     }
-    CommitState limitSate = [[limitDic objectForKey:key] intValue];
-    return timeState == limitSate;
-}
-
-+ (NSDictionary *) getKeys:(BOOL) measureOrDimen
-{
-    static NSDictionary *commitDimenKeys;
-    static NSDictionary *commitMeasureKeys;
-    static dispatch_once_t onceToken;
     
-    dispatch_once(&onceToken, ^{
-        // non-standard perf commit names, remove this hopefully.
-        
-        commitDimenKeys =@{
-                           BIZTYPE:             [NSNumber numberWithInt:DebugAfterFSFinish],
-                           PAGENAME:            [NSNumber numberWithInt:DebugAfterRequest],
-                           WXSDKVERSION:        [NSNumber numberWithInt:DebugAfterRequest],
-                           JSLIBVERSION:        [NSNumber numberWithInt:DebugAfterRequest],
-                           JSLIBSIZE:           [NSNumber numberWithInt:DebugAfterRequest],
-                           WXREQUESTTYPE:       [NSNumber numberWithInt:DebugAfterRequest],
-                           WXCONNECTIONTYPE:    [NSNumber numberWithInt:DebugAfterRequest],
-                           NETWORKTYPE:         [NSNumber numberWithInt:DebugAfterRequest],
-                           CACHETYPE:           [NSNumber numberWithInt:DebugAfterRequest],
-                           WXCUSTOMMONITORINFO: [NSNumber numberWithInt:DebugAfterRequest]
-        };
-        commitMeasureKeys =@{
-                             SDKINITTIME:                   [NSNumber numberWithInt:DebugAfterFSFinish],
-                             SDKINITINVOKETIME:             [NSNumber numberWithInt:DebugAfterFSFinish],
-                             JSLIBINITTIME:                 [NSNumber numberWithInt:DebugAfterFSFinish],
-                             JSTEMPLATESIZE:                [NSNumber numberWithInt:DebugAfterRequest],
-                             NETWORKTIME:                   [NSNumber numberWithInt:DebugAfterRequest],
-                             COMMUNICATETIME:               [NSNumber numberWithInt:DebugAfterExist],
-                             SCREENRENDERTIME:              [NSNumber numberWithInt:DebugAfterExist],
-                             TOTALTIME:                     [NSNumber numberWithInt:DebugAfterExist],
-                             FIRSETSCREENJSFEXECUTETIME:    [NSNumber numberWithInt:DebugAfterFSFinish],
-                             CALLCREATEINSTANCETIME:        [NSNumber numberWithInt:DebugAfterFSFinish],
-                             COMMUNICATETOTALTIME:          [NSNumber numberWithInt:DebugAfterExist],
-                             FSRENDERTIME:                  [NSNumber numberWithInt:DebugAfterExist],
-                             CACHEPROCESSTIME:              [NSNumber numberWithInt:DebugAfterRequest],
-                             CACHERATIO:                    [NSNumber numberWithInt:DebugAfterRequest],
-                             M_FS_CALL_JS_TIME:             [NSNumber numberWithInt:DebugAfterFSFinish],
-                             M_FS_CALL_JS_NUM:              [NSNumber numberWithInt:DebugAfterFSFinish],
-                             M_FS_CALL_NATIVE_TIME:         [NSNumber numberWithInt:DebugAfterFSFinish],
-                             M_FS_CALL_NATIVE_NUM:          [NSNumber numberWithInt:DebugAfterFSFinish],
-                             M_FS_CALL_EVENT_NUM:           [NSNumber numberWithInt:DebugAfterFSFinish],
-                             M_CELL_EXCEED_NUM:             [NSNumber numberWithInt:DebugAfterFSFinish],
-                             M_MAX_DEEP_VDOM:               [NSNumber numberWithInt:DebugAfterExist],
-                             M_IMG_WRONG_SIZE_NUM:          [NSNumber numberWithInt:DebugAfterExist],
-                             M_TIMER_NUM:                   [NSNumber numberWithInt:DebugAfterFSFinish],
-                             M_INTERACTION_TIME:            [NSNumber numberWithInt:DebugAfterExist],
-                             M_INTERACTION_ADD_COUNT:       @(DebugAfterFSFinish),
-                             M_INTERACTION_LIMIT_ADD_COUNT: @(DebugAfterFSFinish),
-                             COMPONENTCOUNT:                @(DebugAfterExist),
-                             M_COMPONENT_TIME:              @(DebugAfterExist),
-                             M_NEW_FS_RENDER_TIME:                  @(DebugAfterExist),
-                             };
-        
-    });
-    return measureOrDimen?commitMeasureKeys:commitDimenKeys;
-}
-
-+ (void) _transMeasureValue:(WXSDKInstance *)instance key:(NSString *)commitKey withVal:(id)commitVal
-{
-    [self _transDataToAnaylzer:instance
-                        withModule:MODULE_PERFORMANCE
-                        withType:TYPE_MEASURE_REAL
-                        withData:@{commitKey:commitVal}
-     ];
-}
-
-+ (void) _transDimenValue:(WXSDKInstance *)instance key:(NSString *)commitKey withVal:(id)commitVal
-{
-    [self _transDataToAnaylzer:instance
-                        withModule:MODULE_PERFORMANCE
-                        withType:TYPE_DIMEN_REAL
-                        withData:@{commitKey:commitVal}
-     ];
+    NSDictionary* dic =  @{
+                            @"group":MODULE_WX_APM,
+                            @"module":instanceId,
+                            @"type":type,
+                            @"data":@{key:value}
+                            };
+    for (id analyzer in analyzerList) {
+        if ([analyzer respondsToSelector:(@selector(transfer:))]){
+            [analyzer performSelector:@selector(transfer:) withObject:dic];
+        }
+    }
 }
 
-+(void) _transDataToAnaylzer:(WXSDKInstance *)instance withModule:(NSString *)module  withType:(NSString *)type withData:(NSDictionary *)data
++ (void) transferInteractionInfo:(WXComponent*)targetComponent
 {
+    if (![self isOpen]) {
+        return;
+    }
     NSMutableArray* analyzerList = [self getAnalyzerList];
     if (nil == analyzerList) {
         return;
     }
     
-    NSMutableDictionary *wrapDic = [data mutableCopy];
-    [wrapDic setObject:instance.instanceId forKey:@"instanceId"];
-    [wrapDic setObject:[instance.scriptURL absoluteString]?:@"unSetscriptURL" forKey:@"url"];
-    [wrapDic setValue:GROUP_ANALYZER forKey:@"group"];
-    [wrapDic setValue:module forKey:@"module"];
-    [wrapDic setValue:type forKey:@"type"];
-
+    long renderOriginDiffTime = [WXUtility getUnixFixTimeMillis] - targetComponent.weexInstance.performance.renderUnixTimeOrigin;
     
-    if ([self needTransfer]) {
-        for (id analyzer in analyzerList) {
-            if ( [analyzer respondsToSelector:(@selector(transfer:))])
-            {
-                [analyzer performSelector:@selector(transfer:) withObject:wrapDic];
-            }
+    NSDictionary* dic =  @{
+                           @"group":MODULE_WX_APM,
+                           @"module":targetComponent.weexInstance.instanceId,
+                           @"type":@"wxinteraction",
+                           @"data":@{
+                                   @"renderOriginDiffTime":@(renderOriginDiffTime),
+                                   @"type":targetComponent.type,
+                                   @"ref":targetComponent.ref,
+                                   @"style":targetComponent.styles,
+                                   @"attrs":targetComponent.attributes
+                                   }
+                           };
+    for (id analyzer in analyzerList) {
+        if ([analyzer respondsToSelector:(@selector(transfer:))]){
+            [analyzer performSelector:@selector(transfer:) withObject:dic];
         }
     }
-    
-    
+    if ([self isInteractionLogOpen]) {
+        WXLogDebug(@"wxInteractionAnalyzer : [client][wxinteraction]%@",dic);
+    }
 }
 
 +(void)transErrorInfo:(WXJSExceptionInfo *)errorInfo
 {
-    if (!errorInfo) {
+    if (![self isOpen] || !errorInfo) {
         return;
     }
+
     WXSDKInstance *instance = [WXSDKManager instanceForID:errorInfo.instanceId];
     if (!instance) {
         return;
     }
+    NSMutableArray* analyzerList = [self getAnalyzerList];
+    if (nil == analyzerList) {
+        return;
+    }
+
     NSDictionary *dic= @{
                          @"errorCode":errorInfo.errorCode?:@"-1",
                          @"errorGroup":@"",
-                         @"errorMsg":errorInfo.exception?:@"unSetException"
-                         };
+                         @"errorMsg":errorInfo.exception?:@"unSetException",
+                         @"instanceId":instance.instanceId,
+                         @"url":[instance.scriptURL absoluteString]?:@"unSetscriptURL",
+                         @"group":GROUP_ANALYZER,
+                         @"module":MODULE_ERROR,
+                         @"type":TYPE_JS_ERROR
+                        };
     
-    [self _transDataToAnaylzer:instance
-                    withModule:MODULE_ERROR
-                      withType:TYPE_JS_ERROR
-                      withData:dic
-     ];
+    for (id analyzer in analyzerList) {
+        if ([analyzer respondsToSelector:(@selector(transfer:))]){
+            [analyzer performSelector:@selector(transfer:) withObject:dic];
+        }
+    }
 }
 
 + (void) addWxAnalyzer:(id<WXAnalyzerProtocol>)handler
@@ -233,17 +175,6 @@
     return [WXAnalyzerCenter sharedInstance].analyzerList;
 }
 
-+(BOOL) needTransfer
-{
-    if(![self isOpen]){
-        return FALSE;
-    }
-    NSMutableArray* analyzerList = [self getAnalyzerList];
-    if (nil == analyzerList || analyzerList.count <= 0) {
-        return FALSE;
-    }
-    return TRUE;
-}
 
 + (void)setOpen:(BOOL)isOpen
 {
@@ -255,4 +186,33 @@
      return [WXAnalyzerCenter sharedInstance].anzlyzerSwitch;
 }
 
++(void) switchInteractionLog:(BOOL) isOpen
+{
+    if ([WXAnalyzerCenter sharedInstance]->_interactionLogSwitch == isOpen) {
+        return;
+    }
+    [WXAnalyzerCenter sharedInstance]->_interactionLogSwitch = isOpen;
+    [WXCoreBridge registerCoreEnv:@"switchInteractionLog" withValue:isOpen?@"true":@"false"];
+#ifdef DEBUG
+    [WXLog setLogLevel: isOpen?WXLogLevelDebug:WXLogLevelLog];
+#else
+     [WXLog setLogLevel: isOpen?WXLogLevelDebug:WXLogLevelWarning];
+#endif
+
+    if ([WXSDKManager.bridgeMgr respondsToSelector:@selector(bridgeCtx)]) {
+        id bridgeCtx = [WXSDKManager.bridgeMgr performSelector:@selector(bridgeCtx) withObject:nil];
+        if (nil != bridgeCtx && [bridgeCtx respondsToSelector:@selector(callJSMethod:args:)]) {
+            WXPerformBlockOnBridgeThread(^(){
+                NSArray* args = @[isOpen?@(1):@(0)];
+                [bridgeCtx performSelector:@selector(callJSMethod:args:) withObject:@"switchInteractionLog" withObject:args];
+            });
+        }
+    }
+}
+
++(BOOL) isInteractionLogOpen
+{
+    return [WXAnalyzerCenter sharedInstance]->_interactionLogSwitch;
+}
+
 @end
diff --git a/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.m b/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.m
index d7fafd7..ccd1885 100644
--- a/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.m
+++ b/ios/sdk/WeexSDK/Sources/Monitor/WXMonitor.m
@@ -67,6 +67,7 @@ static WXThreadSafeMutableDictionary *globalPerformanceDict;
     dict[kEndKey] = @(CACurrentMediaTime() * 1000);
     if (tag == WXPTFirstScreenRender) {
         [instance.apmInstance onStage:KEY_PAGE_STAGES_FSRENDER];
+        instance.apmInstance.isFSEnd = YES;
     }
 
 //    if (tag == WXPTAllRender) {
@@ -241,12 +242,6 @@ static WXThreadSafeMutableDictionary *globalPerformanceDict;
         [self printPerformance:commitDict];
         [WXTracingManager commitTracingSummaryInfo:commitDict withInstanceId:instance.instanceId];
     }
-    if ([WXAnalyzerCenter isOpen]) {
-        if (state == MonitorCommit) {
-            state = DebugAfterExist;
-        }
-        [WXAnalyzerCenter transDataOnState:state withInstaneId:instance.instanceId data:commitDict];
-    }
 }
 
 + (NSMutableDictionary *)performanceDictForInstance:(WXSDKInstance *)instance
diff --git a/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.h b/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.h
index 68890a4..a816246 100644
--- a/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.h
+++ b/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.h
@@ -108,7 +108,7 @@ extern NSString* const VALUE_ERROR_CODE_DEFAULT;
 @property (nonatomic, assign) BOOL isStartRender;
 @property (nonatomic,assign)  BOOL  hasRecordFirstInterationView;
 @property (nonatomic, assign) BOOL isDownLoadFailed;
-@property (nonatomic,assign) double wxPageRatio;
+@property (nonatomic,assign) double pageRatio;
 
 #pragma mark - basic method
 
diff --git a/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.m b/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.m
index 04d6abf..d44effd 100644
--- a/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.m
+++ b/ios/sdk/WeexSDK/Sources/Performance/WXApmForInstance.m
@@ -29,6 +29,7 @@
 #import "WXSDKError.h"
 #import "WXExceptionUtils.h"
 #import "WXSDKInstance_performance.h"
+#import "WXAnalyzerCenter+Transfer.h"
 
 
 #pragma mark - const static string
@@ -147,7 +148,7 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
 
 - (void) onEvent:(NSString *)name withValue:(id)value
 {
-    if (nil == _apmProtocolInstance) {
+    if (nil == _apmProtocolInstance || _isEnd) {
         return;
     }
     [self.apmProtocolInstance onEvent:name withValue:value];
@@ -155,7 +156,7 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
 
 - (void) onStage:(NSString *)name
 {
-    if (nil == _apmProtocolInstance || _isEnd) {
+    if(_isEnd){
         return;
     }
     [self onStageWithTime:name time:[WXUtility getUnixFixTimeMillis]];
@@ -163,7 +164,14 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
 
 - (void) onStageWithTime:(NSString*)name time:(long)unixTime
 {
-    if (nil == _apmProtocolInstance || _isEnd) {
+    if(_isEnd){
+        return;
+    }
+    if ([WXAnalyzerCenter isOpen]) {
+        [WXAnalyzerCenter transferPerformance:self.instanceId withType:@"stage" andKey:name andValue:@(unixTime)];
+    }
+
+    if (nil == _apmProtocolInstance) {
         return;
     }
     if ([KEY_PAGE_STAGES_DOWN_BUNDLE_START isEqualToString:name]) {
@@ -194,17 +202,33 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
 
 - (void) setProperty:(NSString *)name withValue:(id)value
 {
-    if (nil == _apmProtocolInstance || _isEnd) {
+    if(_isEnd){
+        return;
+    }
+    
+    if ([WXAnalyzerCenter isOpen]) {
+        [WXAnalyzerCenter transferPerformance:self.instanceId withType:@"properties" andKey:name andValue:value];
+    }
+    
+    if (nil == _apmProtocolInstance) {
         return;
     }
+   
     [self.apmProtocolInstance addProperty:name withValue:value];
 }
 
 - (void) setStatistic:(NSString *)name withValue:(double)value
 {
-    if (nil == _apmProtocolInstance || _isEnd) {
+    if(_isEnd){
         return;
     }
+    if ([WXAnalyzerCenter isOpen]) {
+        [WXAnalyzerCenter transferPerformance:self.instanceId withType:@"stats" andKey:name andValue:@(value)];
+    }
+    if (nil == _apmProtocolInstance) {
+        return;
+    }
+  
     [self.apmProtocolInstance addStatistic:name withValue:value];
 }
 
@@ -212,18 +236,22 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
 
 - (void) startRecord:(NSString*) instanceId
 {
-    if (nil == _apmProtocolInstance || _isRecord) {
+    if (_isRecord || ![self _shouldRecordInfo]) {
         return;
     }
+  
+    _isRecord = YES;
+    _instanceId = instanceId;
+    
+    if (nil != _apmProtocolInstance) {
+        [self.apmProtocolInstance onStart:instanceId topic:WEEX_PAGE_TOPIC];
+    }
+    [self onStage:KEY_PAGE_STAGES_START];
     WXSDKInstance* instance = [WXSDKManager instanceForID:instanceId];
     if (nil == instance) {
         return;
     }
-    
-    _isRecord = YES;
 
-    
-    [self.apmProtocolInstance onStart:instance.instanceId topic:WEEX_PAGE_TOPIC];
     for (NSString* key in instance.continerInfo) {
         id value = [instance.continerInfo objectForKey:key];
         [self setProperty:key withValue:value];
@@ -236,7 +264,9 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
     [self setProperty:KEY_PROPERTIES_ERROR_CODE withValue:VALUE_ERROR_CODE_DEFAULT];
     [self setProperty:KEY_PAGE_PROPERTIES_JSLIB_VERSION withValue:[WXAppConfiguration JSFrameworkVersion]?:@"unknownJSFrameworkVersion"];
     [self setProperty:KEY_PAGE_PROPERTIES_WEEX_VERSION withValue:WX_SDK_VERSION];
-    [self setStatistic:KEY_PAGE_STATS_BODY_RATIO withValue:self.wxPageRatio];
+    if (self.pageRatio >0) {
+        [self setStatistic:KEY_PAGE_STATS_BODY_RATIO withValue:self.pageRatio];
+    }
     
     //for apm protocl
     //iOS/Android we default recycle img when imgView disapper form screen
@@ -246,32 +276,24 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
 
 - (void) endRecord;
 {
-    if (nil == _apmProtocolInstance || _isEnd) {
+    if (_isEnd) {
         return;
     }
     _isEnd = YES;
-    WXSDKInstance* instance = [WXSDKManager instanceForID:self.instanceId];
-    if (!_hasRecordInteractionTime && nil!= instance.performance && instance.performance.lastRealInteractionTime > 0) {
-        [self onStageWithTime:KEY_PAGE_STAGES_INTERACTION time:instance.performance.lastRealInteractionTime];
-        _hasRecordInteractionTime = YES;
-    }
-    
     [self onStage:KEY_PAGE_STAGES_DESTROY];
-    [self.apmProtocolInstance onEnd];
-    [self _checkScreenEmptyAndReport];
+    if (nil != _apmProtocolInstance) {
+         [self.apmProtocolInstance onEnd];
+    }
 }
 
 - (void) updateFSDiffStats:(NSString *)name withDiffValue:(double)diff
 {
-    if (nil == _apmProtocolInstance || _isFSEnd) {
-        return;
-    }
     [self updateDiffStats:name withDiffValue:diff];
 }
 
 - (void) updateDiffStats:(NSString *)name withDiffValue:(double)diff
 {
-    if (nil == _apmProtocolInstance) {
+    if (![self _shouldRecordInfo]) {
         return;
     }
     __weak typeof(self) weakSelf = self;
@@ -286,7 +308,7 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
 
 - (void) updateMaxStats:(NSString *)name curMaxValue:(double)currentValue
 {
-    if (nil == _apmProtocolInstance) {
+    if (![self _shouldRecordInfo]) {
         return;
     }
     __weak typeof(self) weakSelf = self;
@@ -305,7 +327,8 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
 - (void) updateExtInfoFromResponseHeader:(NSDictionary*) extInfo
 {
     _responseHeader = extInfo;
-    if (nil == _apmProtocolInstance || nil == extInfo) {
+    
+    if (![self _shouldRecordInfo] || nil == extInfo) {
         return;
     }
     
@@ -330,7 +353,7 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
 
 - (void) actionNetRequest
 {
-    if (nil == _apmProtocolInstance) {
+    if (![self _shouldRecordInfo]) {
         return;
     }
     if (!self.isFSEnd) {
@@ -341,7 +364,7 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
 
 - (void) actionNetRequestResult:(bool)succeed withErrorCode:(NSString*)errorCode
 {
-    if (nil == _apmProtocolInstance) {
+    if (![self _shouldRecordInfo]) {
         return;
     }
     if (succeed) {
@@ -355,7 +378,7 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
 
 - (void) actionImgLoad
 {
-    if (nil == _apmProtocolInstance) {
+    if (![self _shouldRecordInfo]) {
         return;
     }
     [self updateDiffStats:KEY_PAGE_STATS_IMG_LOAD_NUM withDiffValue:1];
@@ -363,7 +386,7 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
 
 - (void) actionImgLoadResult:(bool)succeed withErrorCode:(NSString*)errorCode
 {
-    if (nil == _apmProtocolInstance) {
+    if (![self _shouldRecordInfo]) {
         return;
     }
     if (succeed) {
@@ -373,6 +396,14 @@ NSString* const VALUE_ERROR_CODE_DEFAULT = @"0";
     }
 }
 
+- (BOOL) _shouldRecordInfo
+{
+    if (_isEnd) {
+        return NO;
+    }
+    return self.apmProtocolInstance != nil || [WXAnalyzerCenter isOpen];
+}
+
 - (void) recordErrorMsg:(WXJSExceptionInfo *)exception
 {
     if (nil == exception || !self.isOpenApm) {