03-Android App logger策略

news2024/11/6 17:22:42

背景

经常会为log定位而烦恼。比如:同一个类,一样的log输出,无法定位到Log输出的行。

方案

1.java StackTraceElement

通过java StackTraceElement获取类名,以及log输出行

2. 具体实现

  @NonNull
  private static String getSourcePoint()
  {
    final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
    assert stackTrace.length > CALL_STACK_INDEX : "Synthetic stacktrace doesn't have enough elements";

    final StackTraceElement st = stackTrace[CALL_STACK_INDEX];
    StringBuilder sb = new StringBuilder(80);
    final String fileName = st.getFileName();
    if (fileName != null)
    {
      sb.append(fileName);
      final int lineNumber = st.getLineNumber();
      if (lineNumber >= 0)
        sb.append(':').append(lineNumber);
      sb.append(' ');
    }
    sb.append(st.getMethodName()).append("()");
    return sb.toString();
  }
3. logger.java实现
package com.app.test.util.log;

import android.util.Log;

import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.app.test.BuildConfig;
import net.jcip.annotations.ThreadSafe;


@ThreadSafe
public final class Logger
{
  private static final String TAG = Logger.class.getSimpleName();
  private static final String CORE_TAG = "APP";
  private static final String FILENAME = "app.log";

  public static void v(String tag)
  {
    log(Log.VERBOSE, tag, "", null);
  }

  public static void v(String tag, String msg)
  {
    log(Log.VERBOSE, tag, msg, null);
  }

  public static void v(String tag, String msg, Throwable tr)
  {
    log(Log.VERBOSE, tag, msg, tr);
  }

  public static void d(String tag)
  {
    log(Log.DEBUG, tag, "", null);
  }

  public static void d(String tag, String msg)
  {
    log(Log.DEBUG, tag, msg, null);
  }

  public static void d(String tag, String msg, Throwable tr)
  {
    log(Log.DEBUG, tag, msg, tr);
  }

  public static void i(String tag)
  {
    log(Log.INFO, tag, "", null);
  }

  public static void i(String tag, String msg)
  {
    log(Log.INFO, tag, msg, null);
  }

  public static void i(String tag, String msg, Throwable tr)
  {
    log(Log.INFO, tag, msg, tr);
  }

  public static void w(String tag, String msg)
  {
    log(Log.WARN, tag, msg, null);
  }

  public static void w(String tag, String msg, Throwable tr)
  {
    log(Log.WARN, tag, msg, tr);
  }

  public static void e(String tag, String msg)
  {
    log(Log.ERROR, tag, msg, null);
  }

  public static void e(String tag, String msg, Throwable tr)
  {
    log(Log.ERROR, tag, msg, tr);
  }

  // Index of stacktrace depth where the original log method call resides.
  private static final int CALL_STACK_INDEX = 3;

  @NonNull
  private static String getSourcePoint()
  {
    final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
    assert stackTrace.length > CALL_STACK_INDEX : "Synthetic stacktrace doesn't have enough elements";

    final StackTraceElement st = stackTrace[CALL_STACK_INDEX];
    StringBuilder sb = new StringBuilder(80);
    final String fileName = st.getFileName();
    if (fileName != null)
    {
      sb.append(fileName);
      final int lineNumber = st.getLineNumber();
      if (lineNumber >= 0)
        sb.append(':').append(lineNumber);
      sb.append(' ');
    }
    sb.append(st.getMethodName()).append("()");
    return sb.toString();
  }

  // Also called from JNI to proxy native code logging (with tag == null).
  @Keep
  private static void log(int level, @Nullable String tag, @NonNull String msg, @Nullable Throwable tr)
  {

    if (BuildConfig.DEBUG || level >= Log.INFO)
    {
      final StringBuilder sb = new StringBuilder(180);
      // Add source point info for file logging, debug builds and ERRORs if its not from core.
      if (tag != null && (BuildConfig.DEBUG || level == Log.ERROR))
        sb.append(getSourcePoint()).append(": ");
      sb.append(msg);
      if (tr != null)
        sb.append('\n').append(Log.getStackTraceString(tr));
      if (tag == null)
        tag = CORE_TAG;

      if (logsFolder == null || BuildConfig.DEBUG)
        Log.println(level, tag, sb.toString());

    }
  }

  private static char getLevelChar(int level)
  {
    switch (level)
    {
      case Log.VERBOSE:
        return 'V';
      case Log.DEBUG:
        return 'D';
      case Log.INFO:
        return 'I';
      case Log.WARN:
        return 'W';
      case Log.ERROR:
        return 'E';
    }
    assert false : "Unknown log level " + level;
    return '_';
  }
}
4. 结果:

如上图,可以看到log输出java的类名,以及行。 

总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1115168.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于金枪鱼群优化的BP神经网络(分类应用) - 附代码

基于金枪鱼群优化的BP神经网络(分类应用) - 附代码 文章目录 基于金枪鱼群优化的BP神经网络(分类应用) - 附代码1.鸢尾花iris数据介绍2.数据集整理3.金枪鱼群优化BP神经网络3.1 BP神经网络参数设置3.2 金枪鱼群算法应用 4.测试结果…

FreeRTOS入门教程(互斥锁的概念和函数使用)

文章目录 前言一、互斥锁的概念二、互斥锁相关函数三、使用互斥锁完成同步四、FreeRTOS中互斥锁存在的问题五、优先级反转和优先级继承六、死锁七、递归锁总结 前言 本篇文章带大家学习什么是互斥锁,并且学习一下互斥锁中一些函数的使用方法。 一、互斥锁的概念 …

修改java项目启动后在jps展示的名称

文章目录 问题在服务器上启动jar包的时候,通过jps查看java进程只展示个 jar解决,指定jar包的全路径jps查看maven打包修改jar名称 问题在服务器上启动jar包的时候,通过jps查看java进程只展示个 jar 解决,指定jar包的全路径 java -jar /root/test/aaa.jarjps查看 494976 aaa.ja…

OpenCV实现物体尺寸的测量

一 ,项目分析 物体尺寸测量的思路是找一个确定尺寸的物体作为参照物,根据已知的计算未知物体尺寸。 如下图所示,绿色的板子尺寸为220*300(单位:毫米),通过程序计算白色纸片的长度。 主要是通过…

DatenLord前沿技术分享 No.38

达坦科技专注于打造新一代开源跨云存储平台DatenLord,通过软硬件深度融合的方式打通云云壁垒,致力于解决多云架构、多数据中心场景下异构存储、数据统一管理需求等问题,以满足不同行业客户对海量数据跨云、跨数据中心高性能访问的需求。在本周…

WebGIS面试(第二期)

一、简介 近期看到好多小伙伴在寻找WebGIS方面的面试题,正好本人之前也因自己面试分享过一些面试题,秋招目前逐步也快结束了,所以我现在慢慢整理一些包括自己面试以及网上公开的一些我认为有用的面试题,仅供参考,大多…

吃鸡游戏出现msvcp140.dll缺失的四个解决方法

首先,让我们了解一下什么是MSVCP140.dll。MSVCP140.dll是Microsoft Visual C 2015 Redistributable Package的一部分,它是一组C库文件,用于支持使用Visual Studio 2015开发的应用程序。如果你的程序需要这些库文件来正常运行,那么…

结构体内存对齐规则

✨前言✨ 📘 博客主页:to Keep博客主页 🙆欢迎关注,👍点赞,📝留言评论 ⏳首发时间:2023年10月20日 📨 博主码云地址:博主码云地址 📕参考书籍&…

【量化交易笔记】10.建立最简单的交易策略

概述 量化说得简单一些用策略进行股票交易,在实施交易之前,需要制定策略,并回测试共效果 为了把交易说明清楚,将这个过程,能简单,就简单,总之,简单,简单再简单。 以下主…

NodeJS的初使用,以及引入第三方插件和安装淘宝镜像的教程

NodeJs 命令 npm init -y 生成package.json文件npm i jquery --save–dev 开发依赖(jQuery后面还可以跟模块,可以有多个)npm i jquery --save 生产依赖npm i jquery --D 开发依赖npm uninstall jquery 卸载删除npm i 把删掉的模块,全部重新加载回来 1.介绍 1.什么是NodeJs?…

SystemVerilog Assertions应用指南 Chapter 1.16“ended”结构

1.16“ended”结构 到目前为止,定义的序列都只是用了简单的连接( concatenation)的机制。换句话说,就是将多个序列以序列的起始点作为同步点,来组合成时间上连续的检查。SVA还提供了另种使用序列的结束点作为同步点的连接机制。这种机制通过给序列名字追加上关键词“ ended”来…

python二次开发Solidworks:修改实体尺寸

立方体原始尺寸:100mm100mm100mm 修改后尺寸:10mm100mm100mm import win32com.client as win32 import pythoncomdef bin_width(width):myDimension Part.Parameter("D1草图1")myDimension.SystemValue width def bin_length(length):myDime…

OpenGL —— 2.6、绘制一个正方体并贴图(附源码,glfw+glad)

源码效果 C源码 纹理图片 需下载stb_image.h这个解码图片的库,该库只有一个头文件。 具体代码: vertexShader.glsl #version 330 corelayout(location 0) in vec3 aPos; layout(location 1) in vec2 aUV;out vec2 outUV;uniform mat4 _viewMatrix; u…

手帐怎么做?推荐这10款手帐达人都在用的好用软件!

手帐是一种强大的可视化方式,可以记录你的观察、日常的思考,并随时间的推移来衡量你的进步。在各种手帐软件的帮助下,创建并完全自定义你的手帐变得比以往任何时候都更容易。 有无数的手帐软件可供选择,满足各种需求。但在众多的…

基于Java的勤工助学管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding) 代码参考数据库参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

京东数据分析:2023年9月京东洗烘套装品牌销量排行榜!

鲸参谋监测的京东平台9月份洗烘套装市场销售数据已出炉! 根据鲸参谋平台的数据显示,今年9月份,京东平台洗烘套装的销量为7100,环比下降约37%,同比增长约87%;销售额为6000万,环比下降约48%&#…

使用Spyder进行动态网页爬取:实战指南

导语 知乎数据的攀爬价值在于获取用户观点、知识和需求,进行市场调查、用户画像分析,以及发现热门话题和可能的新兴领域。同时,知乎上的问题并回答也是宝贵的学习资源,用于知识图谱构建和自然语言处理研究。爬取知乎数据为决策和…

如何在3DMAX中使用tyFlow粒子模拟插件创建样条线网格模型

3DMAX粒子模拟插件tyFlow是3dMAX上一款粒子模拟插件,3dMax的粒子流的非官方替代品,类似于Particle Flow插件,但是功能上更加强大,模拟粒子流动、汇聚破碎等各种效果。 tyFlow不仅仅是对粒子流的升级——相反,它是从头…

介绍drawio和图表使用场景

图表介绍 drawio是一个基于Web技术的草图、简图和图表的解决方案。 drawio支持在线编辑器,app.diagram.net.并支持不同的操作系统的桌面版离线安装版本。如:windows, linux, macOS。 对于个人或者团队,把图表绘制的安全放到第一位&#xff…

【马蹄集】—— 概率论专题:第二类斯特林数

概率论专题:第二类斯特林数 目录 MT2224 矩阵乘法MT2231 越狱MT2232 找朋友MT2233 盒子与球MT2234 点餐 MT2224 矩阵乘法 难度:黄金    时间限制:5秒    占用内存:128M 题目描述 输入两个矩阵,第一个矩阵尺寸为 l…