日志模块封封装:单例模式+策略模式+构建者模式+bugly

news2024/10/7 6:37:40

日志模块封封装:单例模式+策略模式+构建者模式+bugly

  • 一.单例模式+策略模式+构建者模式
  • 二.日志模块封装
    • 1.日志等级:LoggerLevel枚举类
    • 2.日志输出类型:LoggerType枚举类
    • 3.ILogger接口
    • 4.LogCatLogger/FileLogger/NetWorkLogger/EmailLogger
    • 5.使用构建者模式创建对应的logger对象
    • 6.最后使用
  • 三.bugly的使用
    • 1.什么是Bugly
    • 2.集成Bugly
    • 3.如何创建Bugly产品
    • 4.面试问题难点:如果项目混淆后如何准确定位到错误的信息

一.单例模式+策略模式+构建者模式

设计模式传送门

二.日志模块封装

在这里插入图片描述
默认情况下我们的日志只能打印输出,没有永久保存,这里我们的日志不仅能log输出还要能上传到网络,邮件或者本地存储,下面我们进行简单的封装,这里涉及到kotlin基础以及单例模式/策略模式/构建者模式
在这里插入图片描述

1.日志等级:LoggerLevel枚举类

/**
 * @Author : ytx
 * @Time : On 2023/5/21 15:23
 * @Description : LoggerLevel 日志等级
 */
enum class LoggerLevel(var value: Int) {
    Verbose(1),
    Debug(2),
    Info(3),
    Warn(4),
    Error(5)
}

2.日志输出类型:LoggerType枚举类

/**
 * @Author : ytx
 * @Time : On 2023/5/21 15:36
 * @Description : LoggerType 日志输出类型:logcat/文件/邮件/网络
 */
enum class LoggerType {
    LOGCAT,FILE,EMAIL,NET
}

3.ILogger接口

/**
 * @Author : ytx
 * @Time : On 2023/5/21 15:18
 * @Description : ILogger:所有logger顶层接口
 */
interface ILogger {
    fun d(tag:String,log:String)
    fun v(tag:String,log:String)
    fun i(tag:String,log:String)
    fun w(tag:String,log:String)
    fun e(tag:String,log:String)
    /**
     * 是否Debug,开发阶段为true,上线阶段为false
     */
    fun setDebug(isDeug:Boolean)

    /**
     * 默认TAG
     */
    fun setLogTAG(TAG:String)
    /**
     * 默认日志等级
     */
    fun setLoggerLevel(level:LoggerLevel)
    /**
     * Log存储位置,可以是本地路径 可以是网络路径 可以是Email地址
     */
    fun setSaveUrl(url:String)
}

4.LogCatLogger/FileLogger/NetWorkLogger/EmailLogger

创建logger包,下面分别对应4种不同方式,以LogCatLogger为案例

/**
 * @Author : ytx
 * @Time : On 2023/5/21 15:26
 * @Description : LogcatLogger:打印输出log
 */
class LogcatLogger: ILogger {
    private var isDebug = true
    private var TAG = ""
    private var level = LoggerLevel.Debug
    private var loggerFormat = "(:=>$TAG %s -->%s"
    private var url = ""
    override fun d(tag: String, log: String) {
        if(isDebug && level.ordinal >= LoggerLevel.Debug.ordinal){
            Log.d(TAG,String.format(loggerFormat,tag,log))
        }
    }

    override fun v(tag: String, log: String) {
        if(isDebug && level.ordinal >= LoggerLevel.Verbose.ordinal){
            Log.v(TAG,String.format(loggerFormat,tag,log))
        }
    }

    override fun i(tag: String, log: String) {
        if(isDebug && level.ordinal >= LoggerLevel.Info.ordinal){
            Log.i(TAG,String.format(loggerFormat,tag,log))
        }
    }

    override fun w(tag: String, log: String) {
        if(isDebug && level.ordinal >= LoggerLevel.Warn.ordinal){
            Log.w(TAG,String.format(loggerFormat,tag,log))
        }
    }

    override fun e(tag: String, log: String) {
        if(isDebug && level.ordinal >= LoggerLevel.Error.ordinal){
            Log.e(TAG,String.format(loggerFormat,tag,log))
        }
    }

    override fun setDebug(isDebug: Boolean) {
        this.isDebug = isDebug
    }

    override fun setLogTAG(TAG: String) {
       this.TAG = TAG
    }

    override fun setLoggerLevel(level: LoggerLevel) {
        this.level = level
    }

    override fun setSaveUrl(url: String) {
        this.url = url
    }
}

5.使用构建者模式创建对应的logger对象

/**
 * @Author : ytx
 * @Time : On 2023/5/21 15:37
 * @Description : Logger创建对应的logger对象
 */
class Logger private constructor (private val TAG:String, private val level:LoggerLevel,private val loggerType: LoggerType, private val isDebug:Boolean, private val saveUrl:String) {
    private var logger:ILogger
    init {
        logger = getLogger()
    }

    /**
     * 创建Logger
     */
    fun getLogger():ILogger{
        when(loggerType){
            LoggerType.EMAIL -> throw IllegalArgumentException("该方案未实现")
            LoggerType.FILE -> throw IllegalArgumentException("该方案未实现")
            LoggerType.NET -> throw IllegalArgumentException("该方案未实现")
            LoggerType.LOGCAT -> logger = LogcatLogger()
        }
        logger.setLoggerLevel(level)
        logger.setLogTAG(TAG)
        logger.setDebug(isDebug)
        logger.setSaveUrl(saveUrl)
        return logger
    }

    /**
     * 输出Debug log
     */
    fun d(Tag:String,log:String){
        logger.d(Tag,log)
    }

    /**
     * 输出Warn log
     */
    fun w(Tag:String,log:String){
        logger.w(Tag,log)
    }

    /**
     * 输出Verbose log
     */
    fun v(Tag:String,log:String){
        logger.v(Tag,log)
    }

    /**
     * 输出Error log
     */
    fun e(Tag:String,log:String){
        logger.e(Tag,log)
    }
    /**
     * 输出Info log
     */
    fun i(Tag:String,log:String){
        logger.i(Tag,log)
    }



    class Builder(private var TAG:String = "", var level:LoggerLevel = LoggerLevel.Debug, private var loggerType: LoggerType = LoggerType.LOGCAT, var isDebug:Boolean = true, private var saveUrl:String = "" ){


        fun setTAG(TAG:String):Builder{
                this.TAG = TAG
                return this
            }
            fun setLevel(level:LoggerLevel):Builder{
                this.level = level
                return this
            }

            fun setLoggerType(loggerType: LoggerType):Builder{
                this.loggerType = loggerType
                return this
            }

            fun isDebug(isDebug: Boolean):Builder{
                this.isDebug = isDebug
                return this
            }


            fun setSaveUrl(saveUrl: String):Builder{
                this.saveUrl = saveUrl
                return this
            }

            fun build():Logger{
                return Logger(
                    TAG,
                    level,
                    loggerType,
                    isDebug,
                    saveUrl
                )
            }
        }
}

6.最后使用

  var logger = Logger.Builder()
            .setLevel(LoggerLevel.Error)
            .setLoggerType(LoggerType.LOGCAT)
            .isDebug(false)//true打印 false不打印
            .setTAG("2010")
            .build()
        logger.e("MainActivity","hahaha")

在这里插入图片描述
可以使用单例模式对log日志的进一步封装

三.bugly的使用

1.什么是Bugly

腾讯Bugly,为移动开发者提供专业的异常上报和运营统计,帮助开发者快速发现并
解决异常,同时掌握产品运营动态,及时跟进用户反馈。

2.集成Bugly

https://bugly.qq.com/docs/user-guide/instruction-manual-android/?v=1.0.0

3.如何创建Bugly产品

https://bugly.qq.com/v2/workbench/apps

4.面试问题难点:如果项目混淆后如何准确定位到错误的信息

使用mapping和符号表上传工具

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

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

相关文章

相同格式相同分辨率图片不同大小分析

1、问题 有三张图片,如下: 这三张图片均为jpg格式,分辨率均为1851*580,肉眼看不出区别。但是大小不同。 2号为217KB,4号为1.15MB,5号为1.06MB。 我们看下常规信息,先看2号: 可以…

初识Linux:第五篇

初识Linux:第五篇 初识Linux:第五篇1.Linux下的用户2.Linux权限管理2.1文件权限管理2.2文件权限的更改2.21改变文件访问权限属性2.22改变文件的身份 3.三个问题 总结 初识Linux:第五篇 😁本篇主要介绍Linux权限的相关知识&#x1…

vue+elementui+nodejs高校校园在线打印预约系统

在线提交文档进行打印 首页简单介绍系统 语言 node.js 框架:Express 前端:Vue.js 数据库:mysql 数据库工具:Navicat 开发软件:VScode 顶部或主页按钮转到打印 用户可以登录 查看历史打印记录 用户分学生和非学生 学生可以享有优惠…

基于.NetCore开源的Windows的GIF录屏工具

推荐一个Github上Start超过20K的超火、好用的屏幕截图转换为 GIF 动图开源项目。 项目简介 这是基于.Net Core WPF 开发的、开源项目,可将屏幕截图转为 GIF 动画。它的核心功能是能够简单、快速地截取整个屏幕或者选定区域,并将其转为 GIF动画&#x…

编写 ROS 消息发布订阅器(五)

执行命令,指定目录添加cpp文件 cd ~/catkin_ws/src/beginner_tutorials如果没有src目录, 就自己创建一个目录叫src cd src/ vim talker.cpp 复制代码粘贴: #include "ros/ros.h" #include "std_msgs/String.h" int m…

C++/R 期末冲刺3h

C 1. 基础程序 #include "iostream" // C头文件 #include "stdio.h" // C 头文件 //using namespace std; // 命名空间// main() 是程序开始执行的地方int main() {std::cout << "Hello, World!" << "\n";return 0; …

【数据结构】线性结构 之 顺序表

&#x1f331;博客主页&#xff1a;大寄一场. &#x1f331;系列专栏&#xff1a;数据结构与算法 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 目录 前言 顺序表概念及结构 静态代码实现&#xff1a; 动态代码实现&#xff1a; SeqList.h文件 SeqLi…

使用VitePress和Github搭建个人博客网站,可以自动构建和发布

之前我们写过一篇关于如何自动构建和发布个人博客的文章&#xff0c;当时是使用VuePress和GitLab。GitLab持续集成部署CI/CD初探&#xff1a;如何自动构建和发布个人前端博客 现在换了Vue3和Vite&#xff0c;使用VitePress在Github上又搭建了一个博客。博客地址&#xff1a; …

博弈Ai官网ChatGPT能力真实测评

链接&#xff1a;https://chat.bo-e.com/&#xff08;基于ChatGPT4和3.5研发的智能聊天机器人国产镜像&#xff09; 一&#xff0c;博弈Ai的UI设计样式 1、博弈Ai&#xff08;ChatGPT&#xff09;白天模式 2、博弈Ai&#xff08;ChatGPT&#xff09;黑天模式 3、博弈Ai&#x…

五、c++学习(加餐1:汇编基础学习)

经过前面几节课的学习&#xff0c;我们在一些地方都会使用汇编来分析&#xff0c;我们学习汇编&#xff0c;只是学习一些基础&#xff0c;主要是在我们需要深入分析语法的时候&#xff0c;使用汇编分析&#xff0c;这样会让我们更熟悉c编译器和语法。 从这节课开始&#xff0c…

【003hive基础】hive的数据类型

文章目录 一.数据类型1. 基础数据类型2. 复杂数据类型 二. 显式转换与隐式转换三. hive的读时模式 一.数据类型 1. 基础数据类型 2. 复杂数据类型 array: 有序相同数据类型的集合。 arrays(1, 2)map : key必须是基本数据类型&#xff0c;value不限。 map(‘a’, 1, ‘b’, 2)s…

线性回归、正规方程和梯度下降法

一、线性回归简介 1.定义与公式 线性回归是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。 特点&#xff1a;只有一个自变量的情况称为单变量回归&#xff0c;多余一个自变量情况的叫做多元回归 通用公式&#xff1a; y …

javascript基础三:谈谈 JavaScript 中的类型转换机制

一、概述 JS中有六种简单数据类型&#xff1a;undefined、null、boolean、string、number、symbol&#xff0c;以及引用类型&#xff1a;object 但是我们在声明的时候只有一种数据类型&#xff0c;只有到运行期间才会确定当前类型 let name y?allen:1上面代码中&#xff0c…

2023年NOC大赛创客智慧编程赛项Python 复赛模拟题(二)

题目来自:NOC 大赛创客智慧编程赛项Python 复赛模拟题(二) NOC大赛创客智慧编程赛项Python 复赛模拟题(二) 第一题: 编写一个成绩评价系统,当输入语文、数学和英语三门课程成绩时,输出三门课程总成绩及其等级。 (1)程序提示用户输入三个数字,数字分别表示语文、数学、…

ChatGPT-4 镜像网站推荐

文章目录 1. TomChat2. Ai Doge3. 二狗问答4. 小莓用AI5. Ora6. 未知名字7. VIVI-AI8. ATALK9. ChatGPT Web10 AIchatOS 什么是ChatGPT? ChatGPT&#xff0c;全称&#xff1a;聊天生成预训练转换器&#xff08;英语&#xff1a;Chat Generative Pre-trained Transformer&#…

抓取领域相关论文及摘要

抓取规划问题是指确定物体与手指间的一系列接触位置&#xff0c;使得手指能抵抗任意外力且灵活操作物体的能力。传统的基于分析的抓取规划需要根据已知的被抓物体模型根据力闭合的条件判断抓取的好&#xff0c;这种方法只适合对已知的物体进行抓取。 然而日常生活中有很多相似…

MyBatis 中的动态 SQL 是什么?它的作用是什么?

MyBatis 中的动态 SQL 是一种允许在 SQL 语句中根据不同的条件动态生成 SQL 语句的技术。它可以根据不同的条件生成不同的 SQL 语句&#xff0c;从而达到灵活构建 SQL 语句的目的。动态 SQL 可以减少代码的重复度&#xff0c;提高代码的可维护性和可读性。 动态 SQL 使用 OGNL…

如何在MyBatis中处理复杂结果集映射关系

文章目录 前言一、 准备工作二、resultMap处理字段和属性的映射关系三、多对一映射0、级联方式处理映射关系1、使用association处理映射关系2、分步查询解决多对一关系(1) 查询员工信息(2) 根据员工所对应的部门id查询部门信息延迟加载 三、一对多的关系处理0、使用collection来…

6.1 SpringBoot解决跨域,我推荐这2种超实用方案

文章目录 前言一、验证跨域1. 添加index.html2. 增加/auth/test/cors接口3. IDEA启动多个springboot项目4. 验证POST方法5. 验证OPTIONS方法 二、拦截器方案定义拦截器注册拦截器&#xff0c;并指定拦截规则 三、过滤器方案总结最后 前言 在文章【2-2】中&#xff0c;我和你介…

获取企业服务超市企业信息

地址&#xff1a; 服务机构-苏州工业园区企业服务超市 import os from datetime import datetime from urllib import request import pandas as pd import re import requests from lxml import etree from bs4 import BeautifulSoup import csv import codecs# 20230521 根据…