找回密码
 立即注册
查看: 269|回复: 0

记录货拉拉的glog日志框架和Protobuf数据框架的配套使用

[复制链接]
发表于 2022-12-31 18:07 | 显示全部楼层 |阅读模式
glog 的优点


mmap 内存映射实现,支持同步/异步写入模式,采用自定义的二进制文件格式,上层可以自定义序列化方式,兼具灵活,高性能和容错能力。支持增量(按天)归档和全量(按文件)归档 、 日志流式压缩、加密,支持自动清理日志文件,SDK 包含基于 C++ 实现的日志读取功能。
具体背景及原理说明 可看该网址  https://juejin.cn/post/7168662263337861133
1. glog日志框架的依赖


在需要的module 下的build.gradle 下
android{ defaultConfig {        ndk {            abiFilters "armeabi-v7a"//保留一个架构的so        }    }}dependencies { implementation "cn.huolala.glog.android:glog-android-static:1.0.0"//货拉拉的日志库}2. Protobuf数据框架的依赖


在项目的根目录下的build.gradle 下
dependencies {           classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.15' //    }2.1 Protobuf数据框架的依赖


在需要的module 下的build.gradle 下
apply plugin: 'com.google.protobuf'android{    compileOptions {        sourceCompatibility JavaVersion.VERSION_1_8        targetCompatibility JavaVersion.VERSION_1_8    }        sourceSets {        main {            // 定义proto文件目录 默认就是proto 可以不写改步骤 或者重新定义目录            proto {                srcDir 'src/main/proto'                include '*.proto'            }            java {                srcDir 'src/main/java'            }        }    }  }dependencies { implementation 'com.google.protobuf:protobuf-lite:3.0.0'}protobuf {    protoc {             artifact = 'com.google.protobuf:protoc:3.7.0'    }    plugins {        javalite {                artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0'        }    }// 默认路径为 build/generated/source/proto// 该目录下会按 buildType 生成 debug /release 目录    generatedFilesBaseDir = "$projectDir/src/main/xxx" //预编译生成的文件    generateProtoTasks {        all().each { task ->            task.builtins {                remove java            }            task.plugins {                javalite {}            }        }    }}3. 简单的封装使用

3.1  glog 的封装及说明

   日志内容需要我们自己定义 来把要收集的堆栈信息及线程和异常进行整理成msg 写入import android.content.Context;import android.os.Process;import android.text.TextUtils;import android.util.Log;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.Arrays;import java.util.Date;import java.util.concurrent.atomic.AtomicLong;import glog.android.BuildConfig;import glog.android.Glog;/** * @author: tjf * @date: 2022-12-31 * @desc: Glog 日志框架简单的封装     先initialize 初始化 后再配置setGlogConfig日志信息 *  */public class GlogManager {    private Glog glog;    Context context;    private GlogManager() {    }    public static GlogManager getInstance() {        return SingletonHelper.INSTANCE;    }    private static class SingletonHelper {        private static final GlogManager INSTANCE = new GlogManager();    }    public void initialize() {        Glog.initialize(BuildConfig.DEBUG ? Glog.InternalLogLevel.InternalLogLevelDebug :                Glog.InternalLogLevel.InternalLogLevelInfo);    }    // 初始化实例 配置glog    public void setGlogConfig(Context context) {        this.context = context;        int EXPIRES_SECS = 14 * 24 * 60 * 60; // 14 day //日志的定期删除时间 默认是 7天         final int TOTAL_ARCHIVE_SIZE_LIMIT = 56 * 1024 * 1024; // 56 MB  每个日志文件的大小 限制 默认是16MB大小        glog = new Glog.Builder(context)                .protoName("glog_potbuf")         // 实例标识,相同标识的实例只创建一次 文件名的前缀                .rootDirectory(context.getFilesDir().getAbsolutePath() + "/glog")//日志存储的文件目录                // 默认在data/user/0/包名/files/glog/文件                .async(true)//是否异步写入                .expireSeconds(EXPIRES_SECS)//日志的定期删除时间                .compressMode(Glog.CompressMode.Zlib)//压缩格式  默认开启压缩                .totalArchiveSizeLimit(TOTAL_ARCHIVE_SIZE_LIMIT)//每个日志文件的大小限制                .encryptMode(Glog.EncryptMode.AES)  // 加密方式  默认无                .key("")                            // ECDH Server public key  加密的公钥                .incrementalArchive(true)        //支持增量(按天)归档 和 全量(按文件)归档;                // 默认 false 重命名缓存文件的方式归档  true 增量归档,当天日志写入同一文件                .build();    }    //写入日志    public void glogWirter(String msg) {        glog.write(msg.getBytes());    }    //写入proto 格式的日志 tag的    public void glogWirtes_Potobuf(String tag, String msg) {        AtomicLong seq = new AtomicLong();        byte[] msgBytes = LogProtos.Log.newBuilder()                .setLogLevel(LogProtos.Log.Level.INFO)                .setSequence(seq.getAndIncrement())                .setTimestamp(String.valueOf(System.currentTimeMillis()))                .setPid(Process.myPid())                .setTid(String.valueOf(Thread.currentThread().getId()))                .setTag(tag)                .setMsg(msg)                .build()                .toByteArray();        glog.write(msgBytes);    }    //写入proto 格式的日志日志 级别 和tag  和内容    public void glogWirtes_Potobuf(LogProtos.Log.Level logLevel, String tag, String msg) {        AtomicLong seq = new AtomicLong();        byte[] msgBytes = LogProtos.Log.newBuilder()                .setLogLevel(logLevel)                .setSequence(seq.getAndIncrement())                .setTimestamp(String.valueOf(System.currentTimeMillis()))                .setPid(Process.myPid())                .setTid(String.valueOf(Thread.currentThread().getId()))                .setTag(tag)                .setMsg(msg)                .build()                .toByteArray();        glog.write(msgBytes);    }    //释放清空    public void destroy() {        if (glog != null) {            glog.flush();            glog.destroy();        }    }    private final String TAG = "GlogDemo";    // 读取当天的日志  type 1 普通格式  2 proto 格式    public void readNewDateLog(int type) {        glog.flush();        String[] logArchiveFiles = glog.getArchivesOfDate(new Date().getTime() / 1000);        byte[] inBuf = new byte[Glog.getSingleLogMaxLength()];        Log.i(TAG, "开始读取当天日志, 文件列表:" + Arrays.toString(logArchiveFiles));        for (int i = 0; i < logArchiveFiles.length; i++) {            String filename = logArchiveFiles;            try {                Glog.Reader readers = glog.openReader(filename);                String str;                StringBuilder stb = new StringBuilder();                while (true) {                    int count = readers.read(inBuf);                    if (count < 0) { // 读取结束                        break;                    } else if (count == 0) { // 破损恢复                        continue;                    }                    byte[] outBuf = new byte[count];                    System.arraycopy(inBuf, 0, outBuf, 0, count);                    if (type == 1) {                        str = new String(outBuf, "UTF8");                        Log.i(TAG, str);                    } else if (type == 2) {                        Log.i(TAG, LogProtos(LogProtos.Log.parseFrom(outBuf)));                    }                }            } catch (IOException e) {                e.printStackTrace();            }        }        Log.i(TAG, "读取完成");    }    // 读取放在assets下的glog 文件    public void readAssetsFile(String fileName) {        glog.flush();        String filePath = copyAssetAndWrite(context, fileName);        if (TextUtils.isEmpty(filePath)) {            Log.i(TAG, "没有该文件 无法解析");            return;        }        byte[] inBuf = new byte[(int) new File(filePath).length()];        Log.i(TAG, "开始读取, 文件名:" + filePath);        try {            Glog.Reader readers = glog.openReader(filePath);            while (true) {                int count = readers.read(inBuf);                if (count < 0) { // 读取结束                    break;                } else if (count == 0) { // 破损恢复                    continue;                }                byte[] outBuf = new byte[count];                System.arraycopy(inBuf, 0, outBuf, 0, count);                Log.i(TAG, LogProtos(LogProtos.Log.parseFrom(outBuf)));            }        } catch (IOException e) {            e.printStackTrace();        }        Log.i(TAG, "读取完成");    }    //Proto 格式的输出    private String LogProtos(LogProtos.Log logs) {        return "Log{" +                "sequence=" + logs.getSequence() +                ", timestamp='" + logs.getTimestamp() + '\'' +                ", logLevel=" + logs.getLogLevelValue() +                ", pid=" + logs.getPid() +                ", tid='" + logs.getTid() + '\'' +                ", tag='" + logs.getTag() + '\'' +                ", msg='" + logs.getMsg() + '\'' +                '}';    }    /**     * 读取assets 下的文件 到app的缓存目录下     *     * @param context     * @param fileName     * @return     */    public String copyAssetAndWrite(Context context, String fileName) {        try {            File cacheDir = context.getCacheDir();            if (!cacheDir.exists()) {                cacheDir.mkdirs();            }            File outFile = new File(cacheDir, fileName);            if (!outFile.exists()) {                boolean res = outFile.createNewFile();                if (!res) {                    return null;                }            } else {                if (outFile.length() > 10) {//表示已经写入一次                    return outFile.getPath();                }            }            InputStream is = context.getResources().getAssets().open(fileName);            FileOutputStream fos = new FileOutputStream(outFile);            byte[] buffer = new byte[1024];            int byteCount;            while ((byteCount = is.read(buffer)) != -1) {                fos.write(buffer, 0, byteCount);            }            fos.flush();            is.close();            fos.close();            return outFile.getPath();        } catch (IOException e) {            e.printStackTrace();        }        return null;    }}3.2  protos 的格式文件


在main 的同级 下新建一个proto文件夹  新建一个日志类型的proto 的数据结构 Log.proto
建好后 通过AS 的build 下的 rebuild project 来创建 编译的LogProtos 文件生成
syntax = "proto3";//proto3 版本package glog;//包option java_package = "com.tjf.glogpotobufdemo";//包名称option java_outer_classname = "LogProtos";//别名message Log {  enum Level {    INFO = 0;    DEBUG = 1;    VERBOSE = 2;    WARN = 3;    ERROR = 4;  }  int64 sequence = 1;  string timestamp = 2;  Level logLevel = 3;  int32 pid = 4;  string tid = 5;  string tag = 6;  string msg = 7;}4. 完结


元旦快乐

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 12:35 , Processed in 0.121276 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表