精华内容
下载资源
问答
  • RK 6.0 使用脚本添加系统日志收集器功能0001-add-System-log-collector-function
  • android自定义异常日志收集器

    android自定义异常日志收集器


          为什么要掌握自定义异常日志收集器:


          android开发中,经常会app闪退,报异常,通常是通过编辑器捕获异常日志,

         分析异常日志定位问提,并解决。


          如果测试人员或者用户安装app后,出现闪退,需要捕获异常日志,提供给程序员,

          分析解决问题。


          需要实现的效果:

          app安装到手机上后,在使用App的过程中出现了异常报错,

          将会把报错的异常日志记录到手机的本地存储中。


          实现思路:

          1.用自定义的异常处理器替换安卓系统自带的异常处理器

          2.重写异常处理方法 uncaughtException ,

            使用Toast友好提示用户程序异常。

            重新逻辑为捕获异常信息,并写入手机的本地文件。

            留出写入到服务器的扩展口。

         

    实现代码:

      

      应用层调用:

    // 异常处理,不需要处理时注释掉这两句即可!
            CrashHandler crashHandler = CrashHandler.getInstance();
            // 注册crashHandler
            crashHandler.init(getApplicationContext());


    自定义的异常日志收集器:

    CrashHandler.java:

    public class CrashHandler implements UncaughtExceptionHandler {
    
        public static final String TAG = "CrashHandler";
    
        // 系统默认的UncaughtException处理类
        private UncaughtExceptionHandler mDefaultHandler;
        // CrashHandler实例
        private static CrashHandler INSTANCE = new CrashHandler();
        // 程序的Context对象
        private Context mContext;
        // 用来存储设备信息和异常信息
    	private Map<String, Object> infos = new HashMap<String, Object>();
    
        // 用于格式化日期,作为日志文件名的一部分
        @SuppressLint("SimpleDateFormat")
    	private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
    
        /** 保证只有一个CrashHandler实例 */
        private CrashHandler() {
        }
    
        /** 获取CrashHandler实例 ,单例模式 */
        public static CrashHandler getInstance() {
            if (INSTANCE == null) {
                INSTANCE = new CrashHandler();
            }
            return INSTANCE;
        }
    
        /**
         * 初始化,注册Context对象,
         * 获取系统默认的UncaughtException处理器,
         * 设置该CrashHandler为程序的默认处理器
         *
         * @param context
         */
        public void init(Context context) {
            mContext = context;
            // 获取系统默认的UncaughtException处理器
            mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
            // 设置该CrashHandler为程序的默认处理器
            Thread.setDefaultUncaughtExceptionHandler(this);
        }
    
        /**
        * 当UncaughtException发生时会转入该函数来处理
        */
        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
    
    //      ScreenManager.getScreenManager().popActivity(Pay.activity);
    //      arg0.stop();
    //      arg0.destroy();
    
            if (!handleException(ex) && mDefaultHandler != null) {
                // 如果用户没有处理则让系统默认的异常处理器来处理
                mDefaultHandler.uncaughtException(thread, ex);
            } else {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    Log.e(TAG, "error : ", e);
                }
    //            MyApplication.getApplication().exit(true);
                System.exit(10);
            }
        }
    
        /**
        * 自定义错误处理,收集错误信息
        * 发送错误报告等操作均在此完成.
        * 开发者可以根据自己的情况来自定义异常处理逻辑
        * @param ex
        * @return true:如果处理了该异常信息; 否则返回false
        */
        private boolean handleException(Throwable ex) {
            if (ex == null) {
                return false;
            }
    
    //        final String msg = ex.getLocalizedMessage();
    //        if (msg == null) {
    //            return false;
    //        }
            final Throwable exfinal=ex;
            // 使用Toast来显示异常信息
            new Thread() {
                @Override
                public void run() {
                    Looper.prepare();
                    Toast.makeText(mContext, "很抱歉,程序累了,休息一下马上回来...",
                            Toast.LENGTH_SHORT).show();
    
    //                Toast.makeText(mContext, exfinal.toString(),
    //                            Toast.LENGTH_LONG).show();
                    // MsgPrompt.showMsg(mContext, "程序出错啦", msg+"\n点确认退出");
    
                    Looper.loop();
                }
            }.start();
            // 收集设备参数信息
            //collectDeviceInfo(mContext);
    
            // 保存日志文件
            saveCrashInfo2File(ex);
    
            // 发送错误报告到服务器
            //sendCrashReportsToServer(mContext);
    
            return true;
        }
    
    
        /**
         * 在程序启动时候, 可以调用该函数来发送以前没有发送的报告
         */
        public void sendPreviousReportsToServer() {
            sendCrashReportsToServer(mContext);
        }
    
        /**
         * 把错误报告发送给服务器,包含新产生的和以前没发送的.
         *
         * @param context
         */
        private void sendCrashReportsToServer(Context context) {
            String[] crFiles = getCrashReportFiles(context);
            if (crFiles != null && crFiles.length > 0) {
                TreeSet<String> sortedFiles = new TreeSet<String>();
                sortedFiles.addAll(Arrays.asList(crFiles));
                for (String fileName : sortedFiles) {
                    File carshReport = new File(context.getFilesDir(), fileName);
                    postReport(carshReport);
                    carshReport.delete();// 删除已发送的报告
                }
            }
        }
    
        private void postReport(File file) {
            // TODO 发送错误报告到服务器
        }
    
        /**
         * 获取错误报告文件名
         *
         * @param context
         * @return
         */
        private String[] getCrashReportFiles(Context context) {
            File filesDir = context.getFilesDir();
            FilenameFilter filter = new FilenameFilter() {
                public boolean accept(File dir, String name) {
                    return name.endsWith(".txt");
                }
            };
            return filesDir.list(filter);
        }
    
        public void collectDeviceInfo(Context ctx) {
            try {
                PackageManager pm = ctx.getPackageManager();
                PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(),
                        PackageManager.GET_ACTIVITIES);
                if (pi != null) {
                    String versionName = pi.versionName == null ? "null"
                            : pi.versionName;
                    String versionCode = pi.versionCode + "";
                    infos.put("versionName", versionName);
                    infos.put("versionCode", versionCode);
                }
            } catch (NameNotFoundException e) {
                Log.e(TAG, "an error occured when collect package info", e);
            }
            Field[] fields = Build.class.getDeclaredFields();
            for (Field field : fields) {
                try {
                    field.setAccessible(true);
                    infos.put(field.getName(), field.get(null).toString());
                    Log.d(TAG, field.getName() + " : " + field.get(null));
                } catch (Exception e) {
                    Log.e(TAG, "an error occured when collect crash info", e);
                }
            }
        }
    
        /**
        * 保存错误信息到文件中
        * @param ex
        * @return
        */
        private String saveCrashInfo2File(Throwable ex) {
    
            StringBuffer sb = new StringBuffer();
    
            // for (Map.Entry entry : infos.entrySet()) {
            // String key = entry.getKey();
            // String value = entry.getValue();
            // sb.append(key + "=" + value + "\n");
            // }
    
            Writer writer = new StringWriter();
            PrintWriter printWriter = new PrintWriter(writer);
            ex.printStackTrace(printWriter);
            Throwable cause = ex.getCause();
            while (cause != null) {
                cause.printStackTrace(printWriter);
                cause = cause.getCause();
            }
            printWriter.close();
            String result = writer.toString();
            sb.append(result);
    
             infos.put("EXEPTION", ex.getLocalizedMessage());
             infos.put("STACK_TRACE", result);
    
            try {
    
                // Time t = new Time("GMT+8");
                // t.setToNow(); // 取得系统时间
                // int date = t.year * 10000 + t.month * 100 + t.monthDay;
                // int time = t.hour * 10000 + t.minute * 100 + t.second;
    
                long timestamp = System.currentTimeMillis();
                String time = formatter.format(new Date());
                String fileName = "crash-" + time + "-" + timestamp + ".txt";
                if (Environment.getExternalStorageState().equals(
                        Environment.MEDIA_MOUNTED)) {
                    String path =  Environment.getExternalStorageDirectory().getPath()+"/我的安卓/crash/";
                    File dir = new File(path);
                    if (!dir.exists()) {
                        dir.mkdirs();
                    }
                    FileOutputStream fos = new FileOutputStream(path + fileName);
                    fos.write(sb.toString().getBytes());
                    fos.close();
    
                    // FileOutputStream trace = mContext.openFileOutput(fileName,
                    // Context.MODE_PRIVATE);
                    // mDeviceCrashInfo.store(trace, "");
                    // trace.flush();
                    // trace.close();
    
                }
                return fileName;
            } catch (Exception e) {
                Log.e(TAG, "an error occured while writing file...", e);
            }
            return null;
        }
    }



    当安装在手机的app出现闪退时,就会在本地存储的内部存储中我的安卓文件夹里写人txt的日志文件


         

    展开全文
  • 我开源的Android日志收集器
                   

    Github地址:https://github.com/licong/log

    csdn code地址:

    https://code.csdn.net/forlong401/android_log_collector


    Log Collector

    Collect the normal or crash log in Android, then save them into files or upload into server.

    1. How using the libs?

    1.1 step1:

    Add the below permission into your manifest xml.<uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

    1.2 step2:

    Add output\log.jar into your libs folder in your project.

    1.3 step3:

    Register or unregister the crash handler in your application

    /**

    • Log application.
    • @author Li Cong
    • @date 2014-3-23 */

    public class LogApp extends Application {

    @Overridepublic void onCreate() {    super.onCreate();    LogManager.getManager(getApplicationContext()).registerCrashHandler();}@Overridepublic void onTerminate() {    super.onTerminate();    LogManager.getManager(getApplicationContext()).unregisterCrashHandler();}

    }

    1.4 step4(Collect carsh log done.):

    Register the activity in the onCreate() of Activity.Unregister the activity in the onDestroy() of Activity. You should register and unregister for all activities in your manifest xml.

    public class MainActivity extends Activity { private static final String TAG = "MainActivity";

    @Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    LogManager.getManager(getApplicationContext()).registerActivity(this);    LogManager.getManager(getApplicationContext()).log(TAG, "onCreate",            LogUtils.LOG_TYPE_2_FILE_AND_LOGCAT);    String crashNullException = null;    crashNullException.charAt(1);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {    // Inflate the menu; this adds items to the action bar if it is present.    getMenuInflater().inflate(R.menu.main, menu);    return true;}@Overrideprotected void onDestroy() {    LogManager.getManager(getApplicationContext()).unregisterActivity(this);}

    }

    1.5 step5(optional):

    If you need collect the normal log into files or server, you just should call the below method.LogManager.getManager(getApplicationContext()).log(TAG, "onCreate", LogUtils.LOG_TYPE_2_FILE_AND_LOGCAT);

    Enable or disable the log:

    public static boolean DEBUG = true;public static boolean CRASH_SAVE_2_FILE = true;public static boolean CRASH_UPLOAD_2_NETWORK = false;    

    Find the log files:

    SD card dir + package name + log/crash + files. Such as:sd dir/com_forlong401_log/log/log_timestamp.txt       -->normal logsd dir/com_forlong401_log/crash/crash_timestamp.txt   -->crash log

    Advance skills-1:

    Encrypt your data:

    public final class Utils {

    public static String encrypt(String str) {

        // TODO: encrypt data.    return str;

    }

    }

    Advance skills-2:

    Implement your upload method using your server log API:

    /**

    • Handle log task.
    • @author Li Cong
    • @date 2014-3-23 */

    public class LogTask implements Runnable {

    private void log2Network(String tag, String msg) {    // TODO: Server API for upload message.    // TODO: Encode and encrypt the message.}    

    }

    Copyright, license and contact:

    /*

    • Copyright (C) 2014 Li Cong, forlong401@163.com http://www.360qihoo.com
    • Licensed under the Apache License, Version 2.0 (the "License");
    • you may not use this file except in compliance with the License.
    • You may obtain a copy of the License at *
    • http://www.apache.org/licenses/LICENSE-2.0 *
    • Unless required by applicable law or agreed to in writing, software
    • distributed under the License is distributed on an "AS IS" BASIS,
    • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    • See the License for the specific language governing permissions and
    • limitations under the License. */

    日志收集器

    记录普通或者crash的日志到文件或网络服务器。

    1. 如何使用这个库?

    1.1 步骤一:

    添加这些permission到你的manifest文件中。<uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

    1.2 步骤二:

    添加output目录下的log.jar到你工程的libs目录下,刷新。

    1.3 步骤三:

    在Application中Register 或 unregister crash handler。

    /**

    • Log application.
    • @author Li Cong
    • @date 2014-3-23 */

    public class LogApp extends Application {

    @Overridepublic void onCreate() {    super.onCreate();    LogManager.getManager(getApplicationContext()).registerCrashHandler();}@Overridepublic void onTerminate() {    super.onTerminate();    LogManager.getManager(getApplicationContext()).unregisterCrashHandler();}

    }

    1.4 步骤四(如果只收集crash,这步骤搞完就ok了):

    在每个Activity的onCreate()中Register,onDestroy()中unregister.所有的Activity都要添加。

    public class MainActivity extends Activity { private static final String TAG = "MainActivity";

    @Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    LogManager.getManager(getApplicationContext()).registerActivity(this);    LogManager.getManager(getApplicationContext()).log(TAG, "onCreate",            LogUtils.LOG_TYPE_2_FILE_AND_LOGCAT);    String crashNullException = null;    crashNullException.charAt(1);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {    // Inflate the menu; this adds items to the action bar if it is present.    getMenuInflater().inflate(R.menu.main, menu);    return true;}@Overrideprotected void onDestroy() {    LogManager.getManager(getApplicationContext()).unregisterActivity(this);}

    }

    1.5 步骤五(打log):

    如果你要收集普通的日志到文件或者服务器,那么调用下面的方法即可。LogManager.getManager(getApplicationContext()).log(TAG, "onCreate", LogUtils.LOG_TYPE_2_FILE_AND_LOGCAT);

    打开或关闭log:

    public static boolean DEBUG = true; // 关闭或打开普通日志public static boolean CRASH_SAVE_2_FILE = true;// 关闭或打开crash日志写入文件。public static boolean CRASH_UPLOAD_2_NETWORK = false;// 关闭或打开crash日志上传服务器。

    去哪里找到你的日志文件:

    SD card 目录下的包名中点替换为下划线的文件夹下的 + log/crash + 日志文件. 例如:sd dir/com_forlong401_log/log/log_timestamp.txt       -->普通日志sd dir/com_forlong401_log/crash/crash_timestamp.txt   -->crash日志

    高级技能-1:

    加密你的数据:

    public final class Utils {

    public static String encrypt(String str) {

        // TODO: encrypt data.    return str;

    }

    }

    高级技能-2:

    实现你上传日志的代码:

    /**

    • Handle log task.
    • @author Li Cong
    • @date 2014-3-23 */

    public class LogTask implements Runnable {

    private void log2Network(String tag, String msg) {    // TODO: Server API for upload message.    // TODO: Encode and encrypt the message.}    

    }

    版权, 授权协议和联系方式:

    /*

    • Copyright (C) 2014 Li Cong, forlong401@163.com http://www.360qihoo.com
    • Licensed under the Apache License, Version 2.0 (the "License");
    • you may not use this file except in compliance with the License.
    • You may obtain a copy of the License at *
    • http://www.apache.org/licenses/LICENSE-2.0 *
    • Unless required by applicable law or agreed to in writing, software
    • distributed under the License is distributed on an "AS IS" BASIS,
    • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    • See the License for the specific language governing permissions and
    • limitations under the License. */
               
    展开全文
  • # ========================== # @time:2019/11/3 14:41 # @Author:coco # @File:01日志.py # @software:PyCharm # ============================ """ 日志模块:logging()python中的官方...# 创建日志收集器,如果...
    # ==========================
    # @time:2019/11/3 14:41
    # @Author:coco
    # @File:01日志.py
    # @software:PyCharm
    # ============================
    
    """
    日志模块:logging()python中的官方库
    
    """
    
    import logging
    
    # 创建日志收集器,如果没有传参数,则返回默认的日志收集器(root)
    my_log = logging.getLogger("my_log")
    
    # 设置日志收集器的收集等级
    my_log.setLevel("INFO")
    
    # 日志输出
    # 创建一个输出到控制台的日志输出渠道
    sh = logging.StreamHandler()
    sh.setLevel("INFO")
    
    # 将输出渠道添加到日志收集器中
    my_log.addHandler(sh)
    
    # 创建一个输出到文件的渠道
    fh = logging.FileHandler(filename="test.log", encoding='utf8')
    sh.setLevel('ERROR')
    my_log.addHandler(fh)
    
    my_log.debug('这个是debug等级的日志')
    my_log.info('这个是info等级的日志')
    my_log.warning('这个是warning等级的日志')
    my_log.error('这个是error等级的日志')
    
    logger = logging.getLogger('py23')  # 创建log对象
    logger.setLevel('DEBUG')  # 指定logger对象手机的logging信息等级
    
    format = '%(asctime)s-[%(fileame)s-->line:%(lineno)d]-%(levalname)s:%(message)s'
    
    
    展开全文
  • # ========================== # @time:2019/11/3 14:41 # @Author:coco # @File:01日志.py # @software:PyCharm # ============================ ...logging模块中默认的日志收集器:root 默认收集等级位:w...
    # ==========================
    # @time:2019/11/3 14:41
    # @Author:coco
    # @File:01日志.py
    # @software:PyCharm
    # ============================
    
    """
    日志模块:logging()python中的官方库
    
    logging模块中默认的日志收集器:root
    默认收集等级位:warning以上
    
    """
    
    import logging
    
    # 创建日志收集器,如果没有传参数,则返回默认的日志收集器(root)
    my = logging.getLogger()
    my.setLevel('DEBUG')
    
    a = 100
    print('调试数据', a)
    
    logging.debug('这是debug输出的调试信息a:{}'.format(a))
    print('调试数据')
    # 开始使用log功能
    logging.debug('这是debug等级的信息')
    logging.info('这是info等级的信息')
    logging.warning('这是warning等级的信息')
    logging.error('这是error级的信息')
    logging.critical('这是critical等级的信息')
    
    

    运行结果:
    在这里插入图片描述

    展开全文
  • 自动化测试框架之log调试日志收集器封装,关于下面长篇的大论,其实只要三行代码就可以完事了。不信请看最后面: # -*- coding: utf-8 -*- """ @author: qguan """ import os import config import logging import...
  • 本文概述普通产品和优质产品之间的区别是伐木。了解为什么会这样, 以及如何将它们结合在一起。就像安全性一样, 日志记录是Web...在开始集中式日志记录之前, 让我们首先了解为什么日志记录如此重要。两种类型(级别)...
  • 日志收集器Filebeat详解

    千次阅读 2017-11-22 13:38:28
    一、简介 1、Beats是elastic公司的...2)filebeat(用于监听日志数据,可以替代logstash-input-file) 3)topbeat(用于搜集进程的信息、负载、内存、磁盘等数据) 4)winlogbeat(用于搜集windows事件日志) 注:社区还
  • Filebeat的配置文件是/etc/filebeat/filebeat.yml,遵循YAML语法。具体可以配置如下几个项目: Filebeat Output Shipper Logging(可选) Run Options(可选) ...Filebea...
  • 下载:...   配置Filebeat 编辑filebeat.yml 修改监控日志配置   filebeat: prospectors: - paths: - /var/log/*.log input_type: log 把elasticse...
  • 1.General description 我们知道,使用日志系统是...Scribe就是这样一个日志收集服务器,使用它可以对大型的系统进行监控。它是Facebook的一个开源组件,使用的是Facebook另一个框架—Thrift。Thrift 在我的理解就是
  • 2019独角兽企业重金招聘Python工程师标准>>> ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,618
精华内容 647
关键字:

日志收集器