前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >iOS开发——自主设计日志系统

iOS开发——自主设计日志系统

作者头像
Originalee
发布于 2018-08-30 02:57:17
发布于 2018-08-30 02:57:17
1.4K00
代码可运行
举报
文章被收录于专栏:编程之旅编程之旅
运行总次数:0
代码可运行

好像很久没有写有关iOS的文章了,其实iOS的开发一直都是在进行的,但是最近有需求拓宽知识的宽度,所以一直在接触别的知识,当然啦,移动端开发并不能丢下。

我平时开发的项目监测bug和崩溃的模块都是集成了鹅厂的Bugly系统,毕竟是谁用谁说好的第三方系统。而Bugly主要还是返回的还是崩溃之后的日志,所以如果想在平时的运行中,就能拿到客户手机中的日志怎么办呢。在这个需求的驱使下,便开始着手设计一个日志系统。

需求还是不难的,记录手机操作的内容,如

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
时间|日志级别|类名_函数名_行数|分类|Log内容

这样的一种日志形式。

因为不希望频繁的读写,所以希望每十条Log生成之后,读写一次。而未写入硬盘的Log保存在内存中。按照天数,每天都有一份日志,并且在客户的手机异常之后,可以将所有日志压缩上传到服务器。需求介绍完了,并不难对不对。

在Log的生成方面,我的设计是枚举出日志的级别,之后利用Swift#function#line等定义,方便的获取函数名和行数,类名我是利用一个对于NSObjectextension来完成的,类似这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
extension NSObject {
    var className: String {
        return String(describing: type(of: self)).components(separatedBy: ".").last!
    }

    class var className: String {
        return String(describing: self).components(separatedBy: ".").last!
    }
}

开箱可用,准确获取类名。

生成log的核心函数例如如下这样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public func createLog(level: DebugLevel, targetClass: AnyClass, type: OperateType, content: String,  _ line: Int = #line, _ function: String = #function)
-> String {
    let lineStr = String.init(format: "line:%d", line)
    let levelStr = levelToString(level: level)
    let separator = "|"
    let classSeparator = "_"
    let log: String = Date().toString() + separator + levelStr + separator + targetClass.className + classSeparator + function + classSeparator + lineStr + separator + content + "\n"
    print(log)
    return log
}

而基于这个函数做一些封装,就能封装出很简便的打印各级别日志的API了。

至此,介绍完Log的生成类: LogGenerator

之后是对日志的读写,需要有一个文件读写的类,暂定名为LogStorage

因为文件的读写都是常规的操作,所以代码就不贴出来了。我在这里只是贴出我在LogStorage类里暴露的接口方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public protocol LogStorageProtocol {

    /// 获取日志缓存地址
    ///
    /// - Returns: String
    func getCachePath() -> String

    /// 删除文件
    ///
    /// - Parameter fileName: String
    /// - Returns: Bool
    func deleteFile(fileName: String) -> Bool

    /// 清除全部日志缓存
    ///
    /// - Returns: Bool
    func cleanCache() -> Bool

    /// 读取日志文件
    ///
    /// - Parameter fileName: String
    /// - Returns: Data
    func readFile(fileName: String) -> Data?

    /// 更新写入Log数据
    ///
    /// - Parameters:
    ///   - fileName: String
    ///   - data: Data
    /// - Returns: Data
    func updateFile(fileName: String, data: Data) -> Bool

    /// 自动根据天数创建文件名
    ///
    /// - Returns: String
    func createFileName() -> String
}

而这个十条一写,没有达到标准的就暂时保存在内存里,我的想法是创建一个循环队列,根据FIFO原则,当满足十条Log时,做一次写入操作,而循环队列在空间上是非常节省资源的,如果没有满足十条日志,那就都暂存在队列里,整个开销就是循环队列的一个数组,容量是11个元素,还有一个充当哨兵。

循环队列的数据结构是队列的数据结构里最基础的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protocol QueueProtocol {
    func createQueue()
    func traverseQueue()
    func isFullQueue() -> Bool
    func isEmptyQueue() -> Bool
    func Enqueue(log: String) -> Bool
    func Dequeue() -> Bool
}

在内部增加了一个遍历队列写入日志的函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private func updateFileWhenTranverse() {
    var i = queue.front
    while (i != queue.rear) {
        let fileName = LogStorage.share.createFileName()
        let data = queue.logData[i].data(using: .utf8)
        if (LogStorage.share.updateFile(fileName: fileName, data: data!)) {
            let _ = Dequeue()
        }
        i += 1
        i = i % queue.maxsize
    }
}

而最后一个需求就是压缩上传了,在这里使用了SSZipArchive这个第三方库来压缩文件成zip格式。封装成LogArchive类。是不是三言两语间,整个日志系统就设计完成了,但是我是用Swift来写的,若是Objective-C调用怎么办呢。答案当然是用Objc强大的宏定义来搞定咯,几个宏定义,轻松的一行代码就调用了Log输出。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define Cute_Debug(log) [[LogGenerator new] debugWithTargetClass:self.classForCoder content:[NSString stringWithFormat:@"%@", log] :(NSInteger)__LINE__ :[NSString stringWithFormat:@"%s", __FUNCTION__]];

#define Cute_Warning(log) [[LogGenerator new] warningWithTargetClass:self.classForCoder content:[NSString stringWithFormat:@"%@", log] :(NSInteger)__LINE__ :[NSString stringWithFormat:@"%s", __FUNCTION__]];

#define Cute_Info(log) [[LogGenerator new] infoWithTargetClass:self.classForCoder content:[NSString stringWithFormat:@"%@", log] :(NSInteger)__LINE__ :[NSString stringWithFormat:@"%s", __FUNCTION__]];

#define Cute_Error(log) [[LogGenerator new] errorWithTargetClass:self.classForCoder content:[NSString stringWithFormat:@"%@", log] :(NSInteger)__LINE__ :[NSString stringWithFormat:@"%s", __FUNCTION__]];

整个日志系统,我已经开源放在了我的github上,具体的代码可以去github上看。 欢迎提issue,如果有用,请点个star谢谢。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.06.29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【IOS开发进阶系列】IOS常用开发技巧专题
    将AFNetworking添加到预编译头文件,意味着这个框架会被自动的添加到工程的所有源代码文件中。
江中散人_Jun
2023/10/16
4750
【IOS开发进阶系列】IOS常用开发技巧专题
iOS开发中常用的宏
常用的宏 打印日志 //DEBUG 模式下打印日志,当前行 #ifdef DEBUG #define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); #else #define DLog(...) #endif //重写NSLog,Debug模式下打印日志和当前行数 #if DEBUG #define NSLog(FORMAT, ...) fp
码客说
2019/10/22
4500
C++实现简易log日志系统
在软件开发周期中,不管是前台还是后台,系统一般会采用一个持久化的日志系统来记录运行情况。
恋喵大鲤鱼
2018/08/03
8.5K0
iOS开发中 xib模块化设计
比如我们的xib名字为ZJUserPicView.xib 就必须建一个相同名字的类ZJUserPicView.swift并继承ZJXibView
码客说
2019/10/22
8420
日志代码编写
  日志是程序周期性运转或者特定时刻等一些常规或者特殊消息以特殊的形式打印出来,我们称为日志,关于日志,AI是这样回答的:
用户11029129
2024/11/02
840
日志代码编写
c++ 日志类 线程安全+缓存
根据上一次的测试,有缓存的日志类性能会更好。用到了time.h类函数,所以在linux下就要改动一下了,windows环境下写的。
forxtz
2020/10/10
1.3K0
C++日志系统如何设计
笔者在写作本章节的时候,并不敢把此章节的标题叫做《高性能日志系统的设计》,之所以不敢加上“高性能”三个字的原因是,第一,我的对于日志系统设计知识和经验都来自于学习和工作经验,我并不是原创者,只是知识的搬运工;第二,目前有许多优秀的、被广泛使用的开源的日志系统,他们给了我很多启发,不敢在此班门弄斧。不管怎样,笔者还是想写一些自己关于对日志系统的理解和经验,让我们开始吧。
范蠡
2018/12/12
2.6K0
C++日志系统如何设计
iOS小技能:NSLog调试技巧
应用场景:一个应用对应多个域名的情况,测试地址、生产地址、后台接口开发者的个人主机地址
公众号iOS逆向
2022/08/22
8830
iOS小技能:NSLog调试技巧
iOS-MVVM 模式简单演练
本篇只是简单介绍一下MVVM的大致模式,每个人对每种架构模式有自己的理解,本文也是单纯的从获取新闻列表数据,并将其显示到界面上而已。暂时不做过多的考虑。 ---- MVVM 简介 看下MVVM大致模式图 : 相当于在View、ViewController和Model之间多了一层ViewModel。那么多出这层起到了什么作用呢?好处又好在哪里呢? 简单说就是如果数据结构有变动,而View层没有变动的话,那么只要处理ViewModel中的业务逻辑就可以了。ViewModel的主要作用就是处理数据、处理一些小的业
用户1890628
2018/05/10
8630
YYCache 源码解析(二):磁盘缓存的设计与缓存组件设计思路
上一篇讲解了YYCache的使用方法,架构与内存缓存的设计。这一篇讲解磁盘缓存的设计与缓存组件的设计思路。
用户2932962
2018/08/30
2.1K0
Basic debugging using logging for iOS apps
今天周末时间关系,此文只完成了部分内容,后续完整内容请移步到博客(kunnan.blog.csdn.net)
公众号iOS逆向
2021/01/18
5310
Basic debugging using logging for iOS apps
(五)如何编写高性能日志
一、服务器端日志与客户端日志的区别 在正式讲解之前,我们先来看一个日志类的实现方法,这个日志类也是代表着大多数客户端日志的主流写法: /** *@desc: 程序运行log类,log.h *@author: zhangyl *@date: 2017.01.17 **/ #ifndef __LOG_H__ #define __LOG_H__ #ifdef _ZYL_LOG_ #define LogInfo(...) Log::GetInstance(
范蠡
2018/04/04
1.5K0
C++简易日志系统:打造高效、线程安全的日志记录工具
在当前的数字化时代,日志分析已经成为了云安全的重要组成部分,日志文件记录了系统、应用程序和网络的各种活动,通过分析这些日志,我们可以发现潜在的安全问题,预防和应对各种安全威胁
用户11316056
2024/10/19
1360
C++简易日志系统:打造高效、线程安全的日志记录工具
[iOS开发]JSONModel源码学习
首先,在这个模型类的对象被初始化的时候,遍历自身到所有的父类(直到JSONModel为止),获取所有的属性,并将其保存在一个字典里。获取传入字典的所有key,将这些key与保存的所有属性进行匹配。如果匹配成功,则进行kvc赋值。
Billy Miracle
2022/05/08
1.4K0
架构设计 - 日志管理接口设计
在后端代码中,日志无处不在,设计一套自己的日志管理代码,给框架提供一套好用的日志接口将大大方便代码的开发。 其中在日志管理代码的编写中,主要有以下难点: 1.数目不确定的入参函数编写 2.日志权限控制 3.日志输出形式。 接口设计: 1.提供三类日志打印形式:1)控制台打印信息,类似printf的接口封装             2)函数追踪接口,打印当前代码的文件名,函数名及行,以及一些设定的输出参数             3)日志打印函数,提供打印级别控制,且打印内容输出到日志文件中 2.提供日志级别
Aichen
2018/05/18
6700
React Native iOS原生模块开发实战|教程|心得
尊重版权,未经授权不得转载 本文出自:贾鹏辉的技术博客(http://www.devio.org) 告诉大家一个好消息,为大家精心准备的React Native视频教程发布了,大家现可以看视频学React Native了。 前言 一直想写一下我在React Native原生模块封装方面的一些经验和心得,来分享给大家,但实在抽不开身,今天看了一下日历发现马上就春节了,所以就赶在春节之前将这篇博文写好并发布(其实是两篇:要看Android篇的点这里《React Native Android原生模块
CrazyCodeBoy
2018/05/07
2.1K0
React Native iOS原生模块开发实战|教程|心得
spdlog 日志库学习,简易封装
spdlog wiki:https://github.com/gabime/spdlog/wiki
全栈程序员站长
2022/09/10
1.3K0
Go语言(十四)日志项目
日志项目 日志库需求分析 日志库产生的背景 程序运行是个黑盒 日志是程序之外的表现 通过日志,可以知道程序的健康状态 日志打印的级别 Debug:日志最详细,对程序的影响比较大 Trace: 用来追踪问题 Info: 比较重要的信息,比如访问日志 Warn:警告日志,表明程序存在问题 Error: 错误日志,运行程序时发生的错误 Fatal: 严重错误日志 日志存储的位置 直接输出到控制台 打印到文件里 直接打印到网络中,比如kafka 为什么使用接口 定义日志库的标准或者规范
alexhuiwang
2020/09/23
3040
iOS开发之NSURLSessionUploadTask上传数据
苹果在 iOS9 之后已经废弃了NSURLConnection,NSURLSession成为其替代者,其基本知识网上很多,主要可以从NSURLSessionDataTask 、NSURLSessionDownloadTask 和NSURLSessionUploadTask入手学习。最近在写案例时发现其中的NSURLSessionUploadTask还是有着不少的坑,在开发时有时候很难一次性成功。所以将研究的过程记录与分享一下。我会以一个完整的案例来讲解如何使用。 服务器开发 环境:IDEA 14 +Tomc
YungFan
2018/05/03
1.4K0
iOS开发之NSURLSessionUploadTask上传数据
Go语言(十六) 日志项目升级
日志项目升级 升级功能点 异步刷盘 日志切分 项目结构 xlog/ ├── console.go #console日志输出 ├── file.go #文件输出(本次优化点) ├── level.go #日志级别类 ├── log.go #日志库 ├── log_base.go # 基类库 └── tool.go #工具库,用于获取文件名,函数名,所在行 代码拆解 log.go package xlog
alexhuiwang
2020/09/23
5530
相关推荐
【IOS开发进阶系列】IOS常用开发技巧专题
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文