You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@weex.apache.org by 申远 <sh...@gmail.com> on 2019/04/16 08:21:51 UTC

[DISCUSS] Weex Log

Abstract

Currently, the C++ log support for Weex Android is poorly designed, and the
existing Android Log interface (both Java and C++) is hard to use, I'd like
to propose a solution for Weex Log.
Existing ProblemsConnect C++ and Java LogCurrent Problems

Currently, the Java and C++ log function are totally two different
interface without any connection despite their function signature is very
similar.

Java:

public class WXLogUtils {
    public static void d(String msg);
    public static void i(String msg);
    public static void v(String msg);
    public static void w(String msg);
    public static void e(String msg);
}

C++:

#define LOGE(...) 	__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

#ifdef DEBUG
#define LOGV(...) 	__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG,
__VA_ARGS__)
#define LOGD(...) 	((void)0)
#define LOGI(...) 	__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGW(...)   __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)

#else
#define LOGV(...) ((void) 0)
#define LOGD(...) ((void) 0)
#define LOGI(...) ((void) 0)
#define LOGW(...) ((void) 0)
#endif

If some developers decide to enable LOGD(*WXLogUtils.d*) on release
environment or implement uploading log to the server, he/she has no choice
but write the similar code twice in C++ and Java.
Proposed Solution

I think we can connect C++ and Java Log by define C++ macro as a JNI method
of WXLogUtils, such as

//Global initialization code
static jclass cls = env->FindClass("weex/WXLogUtils");
static jmethodID mid =  env->GetStaticMethodID(cls, "d", "()V");

//log_utils.h
#define LOGE(...) 	(*env)->CallStaticVoidMethod(env, cls, mid)

Runtime Log Level DeterminationCurrent Problems

Currently, whether or not display a specified log level of Weex is
determined at compiling time which means we can't change log level
dynamically, the related code is show below:

 public static void d(String msg){
     if(WXEnvironment.isApkDebugable()){
         writeConsoleLog("debug", tag + ":" + msg);
     }
     else{
         //Do Nothing
     }
 }

What if there is render error in a released App with Weex and developers
want the full log of Weex. Sadly, Weex just doesn't support it now.
Proposed Solution

Android provides a command line tool called setProp, and I think we could
make use of that to support runtime log level determination. Let's say
someone want to enable all d level log for an App using Weex. Here is what
he/she about to do:

//Type the command below in the terminal
adb shell setprop weexLogLevel.d true

//The implementation of LogUtils.d
public static void d(String msg){
     if("true".equals(readProp("weexLogLevel.d"))){
         writeConsoleLog("debug", tag + ":" + msg);
     }
     else{
         //Do Nothing
     }
 }

//Read Prop from System environment
private String readProp(String prop) {
    try {
        Process process = Runtime.getRuntime().exec("getprop " + prop);
        InputStreamReader ir = new InputStreamReader(process.getInputStream());
        BufferedReader input = new BufferedReader(ir);
        return input.readLine();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return 0;
}

We can even support server side instruction to enable log at runtime.
Log formatter and LintCurrent Problems

Currently, there is no log format support in Weex, developers must be very
careful with their log, otherwise performance issue would rise.

public void callNativeComponent(String instanceId, String
componentRef, String method, JSONArray arguments, Object options){
    //Some code
    WXLogUtils.d(instanceId+componentRef+arguments+options);
}

It seems there is no performance issue in release environment here as the
WXLogUtils.d only print log in debug environment. The tricky thing here is
that String concatenation is invoked no matter release or debug
environment, which could cause a problem issue. Actually, performance can
only be avoid if one adopt the following pattern:

public void callNativeComponent(String instanceId, String
componentRef, String method, JSONArray arguments, Object options){
    //Some code
    if(WXEnvironment.isApkDebugable()){
        WXLogUtils.d(instanceId+componentRef+arguments+options);
    }
}

Proposed Solution

The main reason that developers concat String by hand is there is no String
format utils in Weex Log. The terrible log pattern could be avoid if Weex
supports log formatter.

//WXLogUtils
public static void d(String msg, Object obj..);

//Invoke WXLogUtils.d
WXLogUtils.d("InstanceId is %s, componentRef is %s, method is %s,
arguments is %s", instanceId, componentRef, method, arguments);

Elegant code without terrible log pattern. What's more, we could add some
lint to avoid possible misuse.

XXX.java:100: Error: Using 'String#format' inside of 'WXLogUtils'
[StringFormatError]
    WXLogUtils.d(String.format("Hello, %s %s", firstName, lastName));

Bad log pattern would just become a compiling issue.
Pretty LogCurrent Problems

The current Weex log is a little hard for human to read. For example:

2019-04-16 15:59:56.214 23008-23068/com.alibaba.weex D/CLog:
WXStreamModule:{"success":true,"examples":[{"type":"component","name":{"zh":"组件","en":"Component"},"group":[{"type":"div","name":"div","title":{"zh":"<div>
组件","en":"<div>"},"desc":{"zh":"<div>
组件是用于包装其它组件的最基本容器。支持所有的通用样式、特性、flexbox 布局。其类似于 HTML 的 <div>
容器,但不能直接在里面添加文本(字符串),如果要展示文本,应该使用 <text> 组件。","en":"<div> is the most
fundamental component which is a contianer to wrap any other
components. It supports all the common styles, attributes and layout
of flexbox."},"docLink":{"en":"http://weex-project.io/references/components/div.html","zh":"http://weex-project.io/cn/references/components/div.html"},"examples":[{"hash":"fb2522e71268aa8fb573eb20129ac4eb","title":{"zh":"嵌套","en":"Nested"},"screenshot":"https://gw.alicdn.com/tfs/TB1uKLGbS_I8KJjy0FoXXaFnVXa-540-844.png"},{"hash":"3488279c3502d1234b437c2f718f3a55","title":{"zh":"重叠","en":"Overlap"},"screenshot":"https://gw.alicdn.com/tfs/TB1FPAzd3MPMeJjy1XdXXasrXXa-540-844.png"},{"hash":"7613db44f6c03a5849937fbbdeebf69d","title":{"zh":"文字节点","en":"Text
Node"},"screenshot":"https://gw.alicdn.com/tfs/TB1qlG2cwoQMeJjy1XaXXcSsFXa-540-844.png"}]},{"type":"text","name":"text","title":{"zh":"<text>
组件","en":"<text>"},"desc":{"zh":"<text> 是 Weex
内置的组件,用来将文本按照指定的样式渲染出来。<text> 只能包含文本值,不支持子组件,你可以使用 {{}}
标记插入变量值作为文本内容。","en":"The weex builtin component ‘text’ is used to
render text with specified style rule. tag can contain text value
only. You can use variable interpolation in the text content with the
mark {{}}."},
2019-04-16 15:59:56.325 23008-23008/com.alibaba.weex
D/CubicBezierInterpolator: CubicBezierInterpolator  mControlPoint1x =
0.23, mControlPoint1y = 0.06, mControlPoint2x = 0.09, mControlPoint2y
= 0.97
2019-04-16 15:59:56.397 23008-23008/com.alibaba.weex
D/BasicListComponent: trigger type is longpress
2019-04-16 15:59:56.397 23008-23008/com.alibaba.weex D/CLog:
BasicListComponent:trigger type is longpress
2019-04-16 15:59:56.407 23008-23008/com.alibaba.weex E/weex: WXUtils
parseFloat illegal value is null
2019-04-16 15:59:56.407 23008-23008/com.alibaba.weex D/CLog: WXUtils
parseFloat illegal value is null
2019-04-16 15:59:56.502 23008-23008/com.alibaba.weex
D/CubicBezierInterpolator: CubicBezierInterpolator  mControlPoint1x =
0.23, mControlPoint1y = 0.06, mControlPoint2x = 0.09, mControlPoint2y
= 0.97
2019-04-16 15:59:56.502 23008-23008/com.alibaba.weex
D/CubicBezierInterpolator: CubicBezierInterpolator  mControlPoint1x =
0.6, mControlPoint1y = 0.9, mControlPoint2x = 0.8, mControlPoint2y =
1.0

There are three issues for the log above:

   - The log is really raw without any format.
   - Log tag varys in many cases and makes it difficult to filter log by tag
   - There is no clue about which line of code prints the log.

Proposed Solution

We can make Weex Log much pretty by solving the above problems, I think it
would be great if Weex could print log like below.

Design Reference

The Weex log proposal above absorbed some design from the following two
library

   - Timber <https://github.com/JakeWharton/timber>
   - Logger <https://github.com/orhanobut/logger>

Schedule

I'd like to hear you advice about Weex Log Proposal.

And I will make a formal Github Project
<https://github.com/apache/incubator-weex/projects> when things are settled.
Best Regards,
YorkShen

申远