YorkShen closed pull request #1454: [WEEX-578][Android] edit performance point
URL: https://github.com/apache/incubator-weex/pull/1454
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git
a/android/playground/app/src/main/java/com/alibaba/weex/WXPageActivity.java
b/android/playground/app/src/main/java/com/alibaba/weex/WXPageActivity.java
index d0048932ea..65c0f69758 100644
--- a/android/playground/app/src/main/java/com/alibaba/weex/WXPageActivity.java
+++ b/android/playground/app/src/main/java/com/alibaba/weex/WXPageActivity.java
@@ -186,7 +186,7 @@ public void run() {
ctx.getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect);
mConfigMap.put("bundleUrl", mUri.toString());
String path = "file".equals(mUri.getScheme()) ? assembleFilePath(mUri)
: mUri.toString();
- mInstance.render(TAG, WXFileUtils.loadAsset(path, WXPageActivity.this),
+ mInstance.render(path, WXFileUtils.loadAsset(path,
WXPageActivity.this),
mConfigMap, null,
WXRenderStrategy.APPEND_ASYNC);
}
diff --git a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
index 35eb693a82..1c43a331bc 100644
--- a/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
+++ b/android/sdk/src/main/java/com/taobao/weex/WXSDKInstance.java
@@ -585,6 +585,11 @@ private void renderInternal(String pageName,
return;
}
+ //some case ,from render(template),but not render (url)
+ if (!mApmForInstance.hasInit()){
+ mApmForInstance.doInit();
+ }
+ mApmForInstance.setPageName(pageName);
mApmForInstance.onStage(WXInstanceApm.KEY_PAGE_STAGES_RENDER_ORGIGIN);
mWXPerformance.pageName = (TextUtils.isEmpty(pageName) ?
"defaultBundleUrl":pageName);
@@ -650,7 +655,7 @@ private void renderByUrlInternal(String pageName,
renderOptions.put(BUNDLE_URL, url);
}
- mApmForInstance.onStart();
+ mApmForInstance.doInit();
Uri uri = Uri.parse(url);
if (uri != null && TextUtils.equals(uri.getScheme(), "file")) {
diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
index e6292a6e68..072117dddf 100644
--- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
@@ -33,6 +33,7 @@
import com.taobao.weex.performance.WXInstanceApm;
import com.taobao.weex.utils.WXExceptionUtils;
import com.taobao.weex.utils.WXLogUtils;
+import com.taobao.weex.utils.WXUtils;
import com.taobao.weex.utils.WXWsonJSONSwitch;
import java.io.Serializable;
@@ -195,14 +196,6 @@ private int callNative(String instanceId, JSONArray tasks,
String callback){
WXLogUtils.e(TAG, "callNative throw exception:" + e.getMessage());
}
- if (null != instance){
-
instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_NATIVE_NUM,1);
- instance.getApmForInstance().updateFSDiffStats(
- WXInstanceApm.KEY_PAGE_STATS_FS_CALL_NATIVE_TIME,
- System.currentTimeMillis()-start
- );
- }
-
if (WXEnvironment.isApkDebugable()) {
if (errorCode == IWXBridge.DESTROY_INSTANCE) {
WXLogUtils.w("destroyInstance :" + instanceId + " JSF must stop
callNative");
@@ -230,6 +223,7 @@ public void reportJSException(String instanceId, String
func, String exception)
@Override
public Object callNativeModule(String instanceId, String module, String
method, byte[] arguments, byte[] options) {
try {
+ long start = WXUtils.getFixUnixTime();
JSONArray argArray = null;
if (arguments != null)
argArray = (JSONArray) WXWsonJSONSwitch.parseWsonOrJSON(arguments);
@@ -253,7 +247,17 @@ public Object callNativeModule(String instanceId, String
module, String method,
}
}
+
Object object =
WXBridgeManager.getInstance().callNativeModule(instanceId, module, method,
argArray, optionsObj);
+
+ WXSDKInstance instance =
WXSDKManager.getInstance().getSDKInstance(instanceId);
+ if (null != instance){
+
instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_NATIVE_NUM,1);
+ instance.getApmForInstance().updateFSDiffStats(
+ WXInstanceApm.KEY_PAGE_STATS_FS_CALL_NATIVE_TIME,
+ WXUtils.getFixUnixTime()-start
+ );
+ }
return WXWsonJSONSwitch.toWsonOrJsonWXJSObject(object);
}catch (Exception e){
WXLogUtils.e(TAG, e);
diff --git
a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
index e3cc4c9da9..db4d359635 100644
--- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
@@ -1211,8 +1211,6 @@ public void run() {
invokeCreateInstance(instance, template, options, data);
long end = System.currentTimeMillis();
instance.getWXPerformance().callCreateInstanceTime = end - start;
-
instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_END);
-
instance.getWXPerformance().communicateTime =
instance.getWXPerformance().callCreateInstanceTime;
}
}, instanceId);
@@ -1266,6 +1264,7 @@ private void invokeCreateInstance(@NonNull WXSDKInstance
instance, String templa
} else {
options.put(BUNDLE_TYPE, "Others");
}
+
instance.getApmForInstance().addProperty(WXInstanceApm.KEY_PAGE_PROPERTIES_BUNDLE_TYPE,
options.get(BUNDLE_TYPE));
}
if (options.get("env") == null) {
options.put("env", mInitParams);
@@ -1315,6 +1314,8 @@ private void invokeCreateInstance(@NonNull WXSDKInstance
instance, String templa
instance.setTemplate(template);
+
instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_END);
+
// if { "framework": "Vue" } or { "framework": "Rax" } will use
invokeCreateInstanceContext
// others will use invokeExecJS
if (!isSandBoxContext) {
diff --git
a/android/sdk/src/main/java/com/taobao/weex/performance/WXInstanceApm.java
b/android/sdk/src/main/java/com/taobao/weex/performance/WXInstanceApm.java
index cb42b4c127..20fd2345fd 100644
--- a/android/sdk/src/main/java/com/taobao/weex/performance/WXInstanceApm.java
+++ b/android/sdk/src/main/java/com/taobao/weex/performance/WXInstanceApm.java
@@ -21,6 +21,7 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import android.text.TextUtils;
import com.taobao.weex.WXEnvironment;
import com.taobao.weex.WXSDKInstance;
import com.taobao.weex.WXSDKManager;
@@ -36,6 +37,7 @@
public static final String KEY_PROPERTIES_ERROR_CODE = "wxErrorCode";
//public static final String KEY_PAGE_PROPERTIES_LAUNCH_ID = "wxLaunchId";
public static final String KEY_PAGE_PROPERTIES_BIZ_ID = "wxBizID";
+ public static final String KEY_PAGE_PROPERTIES_BUBDLE_URL = "wxBundleUrl";
public static final String KEY_PAGE_PROPERTIES_JSLIB_VERSION =
"wxJSLibVersion";
public static final String KEY_PAGE_PROPERTIES_WEEX_VERSION =
"wxSDKVersion";
public static final String KEY_PAGE_PROPERTIES_REQUEST_TYPE =
"wxRequestType";
@@ -45,6 +47,7 @@
public static final String KEY_PAGE_PROPERTIES_CONTAINER_NAME =
"wxContainerName";
public static final String KEY_PAGE_PROPERTIES_INSTANCE_TYPE =
"wxInstanceType";
public static final String KEY_PAGE_PROPERTIES_PARENT_PAGE =
"wxParentPage";
+ public static final String KEY_PAGE_PROPERTIES_BUNDLE_TYPE =
"wxBundleType";
/************** stages *****************/
public static final String KEY_PAGE_STAGES_DOWN_BUNDLE_START =
"wxStartDownLoadBundle";
@@ -52,6 +55,7 @@
public static final String KEY_PAGE_STAGES_RENDER_ORGIGIN =
"wxRenderTimeOrigin";
public static final String KEY_PAGE_STAGES_LOAD_BUNDLE_START =
"wxStartLoadBundle";
public static final String KEY_PAGE_STAGES_LOAD_BUNDLE_END =
"wxEndLoadBundle";
+ public static final String KEY_PAGE_STAGES_CREATE_FINISH=
"wxJSBundleCreateFinish";
public static final String KEY_PAGE_STAGES_FSRENDER = "wxFsRender";
public static final String KEY_PAGE_STAGES_NEW_FSRENDER = "wxNewFsRender";
public static final String KEY_PAGE_STAGES_INTERACTION = "wxInteraction";
@@ -71,6 +75,8 @@
public static final String KEY_PAGE_STATS_MAX_DEEP_DOM =
"wxMaxDeepVDomLayer";
public static final String KEY_PAGE_STATS_MAX_COMPONENT_NUM =
"wxMaxComponentCount";
public static final String KEY_PAGE_STATS_WRONG_IMG_SIZE_COUNT =
"wxWrongImgSizeCount";
+ public static final String KEY_PAGE_STATS_EMBED_COUNT = "wxEmbedCount";
+ public static final String KEY_PAGE_STATS_LARGE_IMG_COUNT =
"wxLargeImgMaxCount";
public static final String KEY_PAGE_STATS_SCROLLER_NUM = "wxScrollerCount";
public static final String KEY_PAGE_STATS_CELL_DATA_UN_RECYCLE_NUM =
"wxCellDataUnRecycleCount";
@@ -99,6 +105,7 @@
private IWXApmMonitorAdapter apmInstance;
private Map<String, Double> recordStatsMap;
private boolean isFSEnd;
+ private boolean mHasInit = false;
public WXInstanceApm(String instanceId) {
mInstanceId = instanceId;
@@ -123,8 +130,17 @@ public void onEvent(String name, Object value) {
* record stage
*/
public void onStage(String name) {
- WXSDKInstance instance =
WXSDKManager.getInstance().getSDKInstance(mInstanceId);
long time = WXUtils.getFixUnixTime();
+ onStageWithTime(name,time);
+ }
+
+ /**
+ *
+ * @param name stage
+ * @param time unixTime ,plz use WXUtils.getFixUnixTime
+ */
+ public void onStageWithTime(String name,long time){
+ WXSDKInstance instance =
WXSDKManager.getInstance().getSDKInstance(mInstanceId);
if (null != instance){
instance.getExceptionRecorder().recordStage(name, time);
}
@@ -134,6 +150,7 @@ public void onStage(String name) {
apmInstance.onStage(name, time);
}
+
/**
* record property
*/
@@ -154,17 +171,26 @@ public void addStats(String key, double value) {
apmInstance.addStats(key, value);
}
+
+ public boolean hasInit(){
+ return mHasInit;
+ }
+
/**
* start record
*/
- public void onStart() {
+ public void doInit() {
+ if (mHasInit){
+ return;
+ }
+ mHasInit = true;
if (null == apmInstance) {
return;
}
apmInstance.onStart(mInstanceId);
WXSDKInstance instance =
WXSDKManager.getInstance().getAllInstanceMap().get(mInstanceId);
String url = null == instance ? "unKnowUrl" : instance.getBundleUrl();
- addProperty(KEY_PAGE_PROPERTIES_BIZ_ID, url);
+ addProperty(KEY_PAGE_PROPERTIES_BUBDLE_URL, url);
addProperty(KEY_PROPERTIES_ERROR_CODE, VALUE_ERROR_CODE_DEFAULT);
addProperty(KEY_PAGE_PROPERTIES_JSLIB_VERSION,
WXEnvironment.JS_LIB_SDK_VERSION);
addProperty(KEY_PAGE_PROPERTIES_WEEX_VERSION,
WXEnvironment.WXSDK_VERSION);
@@ -175,6 +201,11 @@ public void onStart() {
}
}
+ public void setPageName(String pageName){
+ String fixPageName =
TextUtils.isEmpty(pageName)?"emptyPageName":pageName;
+ addProperty(KEY_PAGE_PROPERTIES_BIZ_ID, fixPageName);
+ }
+
public void onAppear(){
if (null == apmInstance) {
return;
@@ -282,7 +313,7 @@ public void updateExtInfo(Map<String, Object> extParams) {
return;
}
- addPropeyFromExtParms("requestType", KEY_PAGE_PROPERTIES_REQUEST_TYPE,
extParams);
+ addPropeyFromExtParms(KEY_PAGE_PROPERTIES_REQUEST_TYPE,
KEY_PAGE_PROPERTIES_REQUEST_TYPE, extParams);
addPropeyFromExtParms("cacheType", KEY_PAGE_PROPERTIES_CACHE_TYPE,
extParams);
addPropeyFromExtParms("zCacheInfo", KEY_PAGE_PROPERTIES_CACHE_INFO,
extParams);
diff --git
a/android/sdk/src/main/java/com/taobao/weex/performance/WXInstanceExceptionRecord.java
b/android/sdk/src/main/java/com/taobao/weex/performance/WXInstanceExceptionRecord.java
index 0b14969b97..cdac68fa31 100644
---
a/android/sdk/src/main/java/com/taobao/weex/performance/WXInstanceExceptionRecord.java
+++
b/android/sdk/src/main/java/com/taobao/weex/performance/WXInstanceExceptionRecord.java
@@ -77,11 +77,15 @@ public void recordStage(String stage, long time) {
|| WXInstanceApm.KEY_PAGE_STAGES_DOWN_BUNDLE_START.equals(stage)
|| WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_START.equals(stage)
) {
- mBeginRender = true;
+ setBeginRender(true);
}
stageList.add(stage + " :" + time);
}
+ public void setBeginRender(boolean isBegin){
+ mBeginRender = true;
+ }
+
public String convertStageToStr() {
if (stageList.isEmpty()) {
return "empty";
diff --git
a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionCreateBody.java
b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionCreateBody.java
index b3dacd43e7..2286057033 100644
---
a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionCreateBody.java
+++
b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionCreateBody.java
@@ -56,6 +56,7 @@ public GraphicActionCreateBody(@NonNull WXSDKInstance
instance, String ref,
if (instance.getContext() == null) {
return;
}
+ instance.getExceptionRecorder().setBeginRender(true);
BasicComponentData basicComponentData = new BasicComponentData(getRef(),
mComponentType, null);
component = createComponent(instance, null, basicComponentData);
diff --git
a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionCreateFinish.java
b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionCreateFinish.java
index 06491fe391..0f8ccf1bb1 100644
---
a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionCreateFinish.java
+++
b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionCreateFinish.java
@@ -23,6 +23,7 @@
import com.taobao.weex.WXSDKInstance;
import com.taobao.weex.WXSDKManager;
import com.taobao.weex.common.WXRenderStrategy;
+import com.taobao.weex.performance.WXInstanceApm;
import com.taobao.weex.ui.component.WXComponent;
/**
@@ -40,6 +41,7 @@ public GraphicActionCreateFinish(@NonNull WXSDKInstance
instance) {
this.mLayoutWidth = (int) component.getLayoutWidth();
this.mLayoutHeight = (int) component.getLayoutHeight();
}
+
instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_CREATE_FINISH);
// todo add LayoutFinishListener
// final LayoutFinishListener listener;
diff --git
a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXEmbed.java
b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXEmbed.java
index bc34dabade..2970d1e992 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXEmbed.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXEmbed.java
@@ -208,6 +208,7 @@ public WXEmbed(WXSDKInstance instance, WXVContainer parent,
BasicComponentData b
}
this.priority = WXUtils.getString(getAttrs().get(Constants.Name.PRIORITY),
PRIORITY_NORMAL);
this.strategy = WXUtils.getString(getAttrs().get(Constants.Name.STRATEGY),
STRATEGY_NONE);
+
instance.getApmForInstance().updateDiffStats(WXInstanceApm.KEY_PAGE_STATS_EMBED_COUNT,1);
}
@Override
@@ -291,10 +292,6 @@ public void setPriority(String priority) {
*/
protected void loadContent(){
mNestedInstance = createInstance();
- if (null != mNestedInstance){
-
mNestedInstance.setContainerInfo(WXInstanceApm.KEY_PAGE_PROPERTIES_INSTANCE_TYPE,"embed");
-
mNestedInstance.setContainerInfo(WXInstanceApm.KEY_PAGE_PROPERTIES_PARENT_PAGE,getInstance().getBundleUrl());
- }
if(mListener != null && mListener.mEventListener != null){
if(!mListener.mEventListener.onPreCreate(this,src)){
//cancel render
@@ -338,8 +335,10 @@ private WXSDKInstance createInstance() {
);
return sdkInstance;
}
+
sdkInstance.setContainerInfo(WXInstanceApm.KEY_PAGE_PROPERTIES_INSTANCE_TYPE,"embed");
+
sdkInstance.setContainerInfo(WXInstanceApm.KEY_PAGE_PROPERTIES_PARENT_PAGE,getInstance().getWXPerformance().pageName);
- sdkInstance.renderByUrl(WXPerformance.DEFAULT,
+ sdkInstance.renderByUrl(url,
url,
null, null,
WXRenderStrategy.APPEND_ASYNC);
diff --git
a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java
b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java
index 7001d3275b..f54fe8b17c 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXImage.java
@@ -296,7 +296,7 @@ public void autoRecoverImage() {
}
}
- private void setRemoteSrc(Uri rewrited,int blurRadius) {
+ private void setRemoteSrc(Uri rewrited, int blurRadius) {
WXImageStrategy imageStrategy = new WXImageStrategy(getInstanceId());
imageStrategy.isClipping = true;
@@ -307,6 +307,7 @@ private void setRemoteSrc(Uri rewrited,int blurRadius) {
imageStrategy.blurRadius = Math.max(0, blurRadius);
this.mBlurRadius = blurRadius;
+ final String rewritedStr = rewrited.toString();
imageStrategy.setImageListener(new WXImageStrategy.ImageListener() {
@Override
public void onImageFinish(String url, ImageView imageView, boolean
result, Map extra) {
@@ -327,7 +328,7 @@ public void onImageFinish(String url, ImageView imageView,
boolean result, Map e
fireEvent(Constants.Event.ONLOAD, params);
}
}
- monitorImgSize(imageView);
+ monitorImgSize(imageView,rewritedStr);
}
});
@@ -344,7 +345,7 @@ public void onImageFinish(String url, ImageView imageView,
boolean result, Map e
imageStrategy.instanceId = getInstanceId();
IWXImgLoaderAdapter imgLoaderAdapter = getInstance().getImgLoaderAdapter();
if (imgLoaderAdapter != null) {
- imgLoaderAdapter.setImage(rewrited.toString(), getHostView(),
+ imgLoaderAdapter.setImage(rewritedStr, getHostView(),
getImageQuality(), imageStrategy);
}
}
@@ -454,7 +455,8 @@ public void onSaveFailed(String errorDesc) {
});
}
- private void monitorImgSize(ImageView imageView){
+ private String preImgUrlStr = "";
+ private void monitorImgSize(ImageView imageView,String currentImgUrlStr){
if (null == imageView){
return;
}
@@ -467,9 +469,16 @@ private void monitorImgSize(ImageView imageView){
if (null == params || null ==img){
return;
}
+ int imgHeight = img.getIntrinsicHeight();
+ int imgWidth = img.getIntrinsicWidth();
+ if (!preImgUrlStr.equals(currentImgUrlStr) && imgHeight > 1920 && imgWidth
> 1080){
+ preImgUrlStr = currentImgUrlStr;
+
instance.getApmForInstance().updateDiffStats(WXInstanceApm.KEY_PAGE_STATS_LARGE_IMG_COUNT,1);
+ }
+
- if (img.getIntrinsicHeight() * img.getIntrinsicWidth() >
imageView.getMeasuredHeight() *
- imageView.getMeasuredWidth()){
+ if (imgHeight * imgHeight > imageView.getMeasuredHeight() *
+ imageView.getMeasuredWidth() +10){
instance.getWXPerformance().wrongImgSizeCount++;
instance.getApmForInstance().updateDiffStats(WXInstanceApm.KEY_PAGE_STATS_WRONG_IMG_SIZE_COUNT,1);
}
diff --git
a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java
b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java
index e983d9b8bf..c9880b5754 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/WXVContainer.java
@@ -312,8 +312,8 @@ public void addSubView(View child, int index) {
getRealView().addView(child, index);
}
WXSDKInstance instance = getInstance();
- if (null != instance &&
instance.getExceptionRecorder().hasAddView.compareAndSet(false,true)){
- instance.getExceptionRecorder().errorList.clear();
+ if (null != instance){
+ instance.getExceptionRecorder().hasAddView.set(true);
}
}
diff --git
a/android/sdk/src/main/java/com/taobao/weex/utils/WXExceptionUtils.java
b/android/sdk/src/main/java/com/taobao/weex/utils/WXExceptionUtils.java
index de70999b86..a99c36c5b0 100644
--- a/android/sdk/src/main/java/com/taobao/weex/utils/WXExceptionUtils.java
+++ b/android/sdk/src/main/java/com/taobao/weex/utils/WXExceptionUtils.java
@@ -86,6 +86,8 @@ public static void commitCriticalExceptionRT(@Nullable final
String instanceId,
commitMap.put(entry.getKey(),entry.getValue());
}
commitMap.put(WXInstanceExceptionRecord.KEY_EXP_STAGE_LIST,instance.getExceptionRecorder().convertStageToStr());
+ String bundleTemplate = instance.getTemplate();
+ commitMap.put("wxTemplateOfBundle",null ==
bundleTemplate ?"has recycle by gc":bundleTemplate);
}
} else {//instance is null for instance id is null
if (!TextUtils.isEmpty(WXSDKInstance.requestUrl)) {
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
With regards,
Apache Git Services