保存错误日志回传服务器之回传错误“信息”

近期领导交给我个任务,即已经上线的一个android产品出现Bug,但只是个别手机出现Bug,主流手机都没事,但是我们不可能把所有出现问题的手机都搜集过来测试开发(实际上出现问题的手机都比较难拿到机型,例如:红米定制版,索尼等),因此只能想个办法:在项目中加上保存错误日志,并将错误信息回传到服务器的方法,然后通过错误日志分析Bug,因此我在参考了网上的一些解决方案后,自己修改写了两种方式:一、直接将错误信息+手机信息发送到服务器  二、将错误信息+手机信息保存到一个文件,将文件上传到服务器。不过说实话,这些还没试验过,不知道能不能用,暂且先写出来,以后有问题再修改:

参考文章:

1.http://www.jb51.net/article/41112.htm

2.http://www.cnblogs.com/stay/archive/2011/07/21/2113167.html

3.http://onewayonelife.iteye.com/blog/1147533

4.http://chenkechao123.blog.163.com/blog/static/1383326482012924238251/

源码:

package com.demo.uploaderrorinfo.common;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections.map.CaseInsensitiveMap;
import org.apache.commons.lang.StringUtils;

import com.demo.uploaderrorinfo.Utils.HttpClientUpLoadTask;
import com.demo.uploaderrorinfo.Utils.JsonUtils;
import com.demo.uploaderrorinfo.Utils.PackageManagerUtils;

import android.content.Context;
//import android.content.pm.PackageInfo;
import android.text.format.DateFormat;
import android.util.Log;

/**
 * @author LHG<br/>
 * 在Application中统一捕获异常,并上传到服务器上
 * 自定义异常类实现UncaughtExceptionHandler接口,当某个页面出现
 * 异常就会调用uncaughtException这个方法,我们可以在这个方法中获取
 * 异常信息、时间等,然后将获取到的信息发送到我们指定的服务器
 */
public class CrashHandler implements UncaughtExceptionHandler {
    private static final String logTag = CrashHandler.class.getSimpleName();
//    private PackageInfo packageInfo;

    /** 系统默认的UncaughtException处理类 */
    private Thread.UncaughtExceptionHandler defaultHandler;

    /** CrashHandler实例 */
    private static CrashHandler INSTANCE;

    /** 程序的Context对象 */
    private Context context;

    /** 保证只有一个CrashHandler实例 */
    private CrashHandler() {}  

    /** 获取CrashHandler实例 ,单例模式*/
    public static CrashHandler getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new CrashHandler();
        }

        return INSTANCE;
    }  

    /**
     * 初始化,注册Context对象,
     * 获取系统默认的UncaughtException处理器,
     * 设置该CrashHandler为程序的默认处理器
     *
     * @param ctx
     */
    public void register(Context ctx) {
        this.context = ctx;  

        //获取默认的handler
        defaultHandler = Thread.getDefaultUncaughtExceptionHandler();

        //设置自己的handler
        Thread.setDefaultUncaughtExceptionHandler(this);
    }  

    /**
     * 当UncaughtException发生时会转入该函数来处理
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        Log.d(logTag, "Now enter CrashHandler. In somewhere occur error. I try to save the error.");
        boolean isProcessed = handleException(thread, ex);

        if (!isProcessed && defaultHandler != null) {
            //如果用户没有处理则让系统默认的异常处理器来处理
            defaultHandler.uncaughtException(thread, ex);
        } else {
            //如果自己处理了异常,则不会弹出错误对话框,则需要手动退出程序
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
            }
            //干掉自己
            android.os.Process.killProcess(android.os.Process.myPid());
            //退出程序
            System.exit(10);
        }
    }  

    /**
     * 自定义错误处理,收集错误信息
     * 发送错误报告等操作均在此完成.
     * true代表处理该异常,不再向上抛异常,
     * false代表不处理该异常(可以将该log信息存储起来)然后交给上层(这里就到了系统的异常处理)去处理,
     * 简单来说就是true不会弹出那个错误提示框,false就会弹出
     */
    private boolean handleException(final Thread thread, final Throwable ex) {
        if (ex == null) {
            Log.d(logTag, "no exception info.");
            return false;
        }
        //得到详细的错误信息
        final String errorInfo = this.getErrorInfo(ex);
        Log.d(logTag, errorInfo);

        if(StringUtils.isNotBlank(errorInfo)){
            Log.d(logTag, "error saved in file " + errorInfo);

            //服务器的接口
//            String url = URLFactory.getInstance(this.context).getServicesURL().getUploadErrorLogURL();
            String url = "http://192.168.18.126:8080/test/upload";
            //将保存的错误信息上传到服务器
            HttpClientUpLoadTask uploadFileTask = new HttpClientUpLoadTask();
            uploadFileTask.execute(url, errorInfo);

            String resultData;
            try {
                resultData = uploadFileTask.get();
                uploadFileCallBack(resultData);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        return false;
    }

    //获取详细的错误信息、应用程序的信息、手机型号版本
    private String getErrorInfo(Throwable ex) {
        List<String> errorContents = new ArrayList<String>();
        StackTraceElement[] sts = ex.getStackTrace();//获取错误代码的位置和信息
        if(null != sts){
            for(StackTraceElement st : sts){
                if(null != st && null != st.toString()){
                    errorContents.add(st.toString());
                }
            }
        }

        @SuppressWarnings("unchecked")
        Map<String,Object> errorInfoMap = new CaseInsensitiveMap();
        //发生错误的时间
        errorInfoMap.put("errortime", DateFormat.format("yyyy-MM-dd kk:mm:ss", new Date(System.currentTimeMillis())));
        //手机型号
        errorInfoMap.put("phonetype", android.os.Build.MODEL);
        errorInfoMap.put("androidsdkversion", android.os.Build.VERSION.SDK);
        errorInfoMap.put("androidreleaseversion", android.os.Build.VERSION.RELEASE);
        String localVersion =PackageManagerUtils.getInstance(this.context).getVersionName();
        errorInfoMap.put("appversion", localVersion);
        errorInfoMap.put("errormessage", ex.getMessage());
        errorInfoMap.put("errorcontent", errorContents); //上面得到的错误信息 (String)

        return JsonUtils.toJson(errorInfoMap);
    }

    private final void uploadFileCallBack(String resultData){
        if(StringUtils.isBlank(resultData) ){
            Log.d(logTag, "uploadFileCallBack occur error.");
            return;
        }
        Log.d(logTag, "uploadFileCallBack receive resultData: "+ resultData);
        Map resultMap = JsonUtils.fromJsonToCaseInsensitiveMap(resultData);
        int resultCode = MapUtils.getIntValue(resultMap, "resultCode", -1);
        if(0 == resultCode){
            Log.d(logTag, "successful. ");
        }else{
            Log.d(logTag, "false ");
        }

}
}

这些是主要的源码,一些辅助性的代码和项目文件等我学会怎么上传博客中后,就直接放项目了!

下面一篇文章是介绍怎么把 “错误信息和手机信息保存成文件上传服务器”的源码

时间: 2024-08-07 21:32:52

保存错误日志回传服务器之回传错误“信息”的相关文章

Nginx错误日志(error_log)配置及信息详解

Nginx状态信息(status)配置及信息详解 nginx与php-fpm一样内建了一个状态页,对于想了解nginx的状态以及监控nginx非常有帮助.为了后续的zabbix监控,我们需要先了解一下nginx的状态页. Nginx状态信息(status)介绍 Nginx软件在编译时又一个with-http_stub_status_module模块,这个模块功能是记录Nginx的基本访问状态信息,让使用者了解Nginx的工作状态.要想使用状态模块,在编译时必须增加--with-http_stub

MySQL 错误日志(Error Log)

同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分.MySQL有几种不同的日志文件,通常包括错误日志文件,二进制日志,通用日志,慢查询日志,等等.这些日志可以帮助我们定义mysqld内部发生的事情,数据库性能故障,记录数据的变更历史,用户恢复数据库等等.本文主要描述错误日志文件. 1.MySQL日志文件系统的组成   a.错误日志:记录启动.运行或停止mysqld时出现的问题.   b.通用日志:记录建立的客户端连接和执行的语句.   c.更新日志:记录更改数据的语句.该日志在M

第五篇 SQL Server代理理解代理错误日志

本篇文章是SQL Server代理系列的第五篇,详细内容请参考原文. 正如这一系列的前几篇所述,SQL Server代理作业是由一系列的作业步骤组成,每个步骤由一个独立的类型去执行.在第四篇中我们看到,SQL Server代理可以通过数据库邮件发送通知.如果有什么不正确的,你必须查看数据库邮件日志.在这一篇,你将学习如何理解和查看所有相关的SQL Server代理错误日志.你将回顾最常见的错误信息,掌握哪些信息需要你采取行动,哪些信息只是单纯的信息而已.一旦你理解错误日志,在处理SQL Serv

SQL Server代理(5/12):理解SQL代理错误日志

SQL Server代理是所有实时数据库的核心.代理有很多不明显的用法,因此系统的知识,对于开发人员还是DBA都是有用的.这系列文章会通俗介绍它的很多用法. 如我们在这个系列的前几篇文章所见,SQL Server代理是由一系列的作业步骤组成,每个步骤是不同类型将要进行的工作.如果你在第4篇所见,SQL Server代理也提供使用数据库邮件发送提醒的能力.如果出现问题,不管怎样, 你必须去查看下数据库邮件错误日志.在这篇文章里,你会学到如何理解和查看SQL Server错误日志的所有相关知识.你会

SQL Server 日志和代理的错误日志

本文介绍的日志不是事务日志,而是SQL Server 日志和代理的错误日志,按照主体把错误日志分为SQL Server.SQL Server Agent.Database Mail,以及 Windows NT.SQL Server使用日志记录数据库引擎启动和运行过程中产生的信息,这些信息不一定是“错误”的消息,按照消息的严重程度,分为三个级别,分别是:信息(Information),警告(Warning)和错误(Error),SQL Server日志会按照消息发生的时间顺序记录消息.SQL Se

nginx php-fpm 输出php错误日志

nginx是一个web服务器,因此nginx的access日志只有对访问页面的记录,不会有php 的 error log信息. nginx把对php的请求发给php-fpm fastcgi进程来处理,默认的php-fpm只会输出php-fpm的错误信息,在php-fpm的errors log里也看不到php的errorlog. 原因是php-fpm的配置文件php-fpm.conf中默认是关闭worker进程的错误输出,直接把他们重定向到/dev/null,所以我们在nginx的error lo

nginx的php-fpm 输出php错误日志

1.概述 2.解决办法(解决nginx下php-fpm不记录php错误日志) 1. 概述 nginx是一个web服务器,因此nginx的access日志只有对访问页面的记录,不会有php 的 error log信息. nginx把对php的请求发给php-fpm fastcgi进程来处理,默认的php-fpm只会输出php-fpm的错误信息,在php-fpm的errors log里也看不到php的errorlog 原因是php-fpm的配置文件php-fpm.conf中默认是关闭worker进程

Apache错误日志时时查看

做项目的时候,有时候会需要查看一下apache的错误日志,然后就需要很繁琐的打开那个目录下面,看信息,只有当错误的时候我才会去打开那个文件. 但是最近我发现在开发的时候,自己忽略掉了很多错误,虽然不会导致出错,但是搞不好哪天就会爆发. 我不高兴每次打开那个文件,然后自己又要手动的刷新,太麻烦,所以就自己做了个网页版的,能够时时查看错误日志. 这个小工具比较简陋,就是简单的将文件内容打印到页面中,并在有新错误的时候做个title的闪动小提示. 当有新消息的时候标签就变成 用到了三个文件,jquer

nginx日志-错误日志(error_log)

错误日志错误日志主要记录客户端访问Nginx出错时的日志,格式不支持自定义.通过错误日志,你可以得到系统某个服务或server的性能瓶颈等. 错误日志由指令error_log来指定,具体格式如下: error_log path(存放路径) level(日志等级) path含义同access_log,level表示日志等级,具体如下: [ debug | info | notice | warn | error | crit ] 从左至右,日志详细程度逐级递减,即debug最详细,crit最少.