前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >API方式上传PB(Protobuf)日志至腾讯云日志服务

API方式上传PB(Protobuf)日志至腾讯云日志服务

作者头像
Cheng_Blog
发布2022-02-25 09:39:46
9450
发布2022-02-25 09:39:46
举报
文章被收录于专栏:Cheng's BlogCheng's Blog

点击进入腾讯日志服务官方文档查看

一、生成PB(Protobuf)上传日志类

使用插件的话,首先要下载安装Protobuf Support插件。

安装后重启IDEA即可。

接着需要对Protobuf Support插件进行配置.

maven的pom文件添加下面的代码

代码语言:javascript
复制
 <!--pb文件处理-->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.18.0</version>
        </dependency>
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java-util</artifactId>
            <version>3.18.0</version>
        </dependency>
        <dependency>
            <groupId>net.jpountz.lz4</groupId>
            <artifactId>lz4</artifactId>
            <version>1.3.0</version>
        </dependency>
        <!--pb文件处理-->
        <!--腾讯云服务-->
        <dependency>
            <groupId>com.tencentcloudapi</groupId>
            <artifactId>tencentcloud-sdk-java</artifactId>
            <version>3.1.361</version>
        </dependency>
        <dependency>
            <groupId>com.tencentcloudapi</groupId>
            <artifactId>tencentcloud-sdk-java-common</artifactId>
            <version>3.1.361</version>
        </dependency>
        <!--腾讯云服务-->
代码语言:javascript
复制
<extensions>
	<extension>
		<groupId>kr.motd.maven</groupId>
		<artifactId>os-maven-plugin</artifactId>
		<version>1.5.0.Final</version>
	</extension>
</extensions>
代码语言:javascript
复制
                        <plugin>
				<groupId>org.xolstice.maven.plugins</groupId>
				<artifactId>protobuf-maven-plugin</artifactId>
				<version>0.5.0</version>
				<configuration>
					<protocArtifact>
						com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}
					</protocArtifact>
					<pluginId>grpc-java</pluginId>
					<pluginArtifact>
						io.grpc:protoc-gen-grpc-java:1.11.0:exe:${os.detected.classifier}
					</pluginArtifact>
				</configuration>
				<executions>
					<execution>
						<goals>
							<goal>compile</goal>
							<goal>compile-custom</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

现在开始写.proto文件,在src/main下面新建proto文件夹,在proto里面新建一个文件,注意后缀是.proto,我这里是cls.proto,

代码语言:javascript
复制
package cls;
//syntax = "proto3";
//proto类生成路径
option java_package = "com.site.blog.my.core.entity.log";
option java_outer_classname = "Cls";
message Log
{
  message Content
  {
    required string key   = 1; // 每组字段的 key
    required string value = 2; // 每组字段的 value
  }
  required int64   time     = 1; // 时间戳,UNIX时间格式
  repeated Content contents = 2; // 一条日志里的多个kv组合
}

message LogTag
{
  required string key       = 1;
  required string value     = 2;
}

message LogGroup
{
  repeated Log    logs        = 1; // 多条日志合成的日志数组
  optional string contextFlow = 2; // 目前暂无效用
  optional string filename    = 3; // 日志文件名
  optional string source      = 4; // 日志来源,一般使用机器IP
  repeated LogTag logTags     = 5;
}

message LogGroupList
{
  repeated LogGroup logGroupList = 1; // 日志组列表
}

编写好.proto文件后,使用插件将proto文件转换为java文件

双击 protobuf:compile 即可

出现SUCCESS信息表示转换成功

然后在target/generated-sources/protobuf目录中即可找到生成的java文件,复制到src/main/java中你需要使用的位置即可。

二、上传pb日志工具类

1. 日志类型枚举
代码语言:javascript
复制
/**
 * 日志类型
 *
 * @author Houchengen
 * @date 2021/09/01
 */
public enum LogType {
    /**
     * info日志
     */
    INFO(1, "INFO"),
    /**
     * debug日志
     */
    DEBUG(2, "DEBUG"),
    /**
     * 错误日志
     */
    ERROR(3, "ERROR");


    LogType(Integer origin, String label) {
        this.origin = origin;
        this.label = label;
    }

    /**
     * 性质代码
     */
    private Integer origin;
    /**
     * 性质中文
     */
    private String label;

    public Integer getOrigin() {
        return origin;
    }

    public void setOrigin(Integer origin) {
        this.origin = origin;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }


    public static LogType getEnumByKey(Integer origin) {
        for (LogType type : LogType.values()) {
            if (origin.equals(type.origin)) {
                return type;
            }
        }
        return null;
    }
}
1. 日志上传类
代码语言:javascript
复制
import com.site.blog.my.core.entity.log.Cls;
import com.site.blog.my.core.entity.log.LogType;
import com.tencentcloudapi.common.CommonClient;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.common.profile.Region;
import net.jpountz.lz4.LZ4Compressor;
import net.jpountz.lz4.LZ4Factory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * 发送腾讯日志工具类
 *
 * @author Houchengen
 * @date 2021/09/22
 */
@EnableAsync
@Component
public class SendTencentLogUtil {


    //腾讯云账户密钥 secretId.
    public static final String SECRET_ID = "*****************";
    //腾讯云账户密钥 secretKey.
    public static final String SECRET_KEY = "*********************";

    public static final String ENDPOINT = "cls.tencentcloudapi.com";
    public static final String ROOT_DOMAIN = "tencentcloudapi.com";
    public static final String X_CLS_TOPIC_ID = "X-CLS-TopicId";
    public static final String X_CLS_HASH_KEY = "X-CLS-HashKey";
    public static final String X_CLS_COMPRESS_TYPE = "X-CLS-CompressType";
    public static final String LZ_4 = "lz4";
	//你的topicId
    public static final String TOPIC = "************";
    public static final String PRODUCT_NAME_CLS = "cls";
    public static final String UPLOAD_LOG_URL = "UploadLog";
    public static final String VERSION = "2020-10-16";


    /**
     * 发送日志
     *
     * @param logType 日志类型
     * @param params  参数
     */
    @Async
    public void sendLog(LogType logType, Map<String, String> params) {
        Credential cred = new Credential(SECRET_ID, SECRET_KEY);

        //region 设置http选项中的参数
        HttpProfile httpProfile = new HttpProfile();
        // post请求  (默认为post请求)
        httpProfile.setReqMethod(HttpProfile.REQ_POST);
        // 指定接入地域域名(默认就近接入)
        httpProfile.setEndpoint(ENDPOINT);
        httpProfile.setRootDomain(ROOT_DOMAIN);
        // 在外网互通的网络环境下支持http协议(默认是https协议),请选择(https:// or http://)
        httpProfile.setProtocol(HttpProfile.REQ_HTTPS);
        // 设置读取超时时间,单位为秒(默认0秒)
        httpProfile.setReadTimeout(0);
        // 设置写入超时时间,单位为秒(默认0秒)
        httpProfile.setWriteTimeout(0);
        // 请求连接超时时间,单位为秒(默认60秒)
        httpProfile.setConnTimeout(HttpProfile.TM_MINUTE);
        //endregion

        //region 设置client选项中的参数
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setHttpProfile(httpProfile);
        // 指定签名算法默认("TC3-HMAC-SHA256"),它更安全但是会轻微降低性能。
        clientProfile.setSignMethod(ClientProfile.SIGN_TC3_256);
        //打印日志,默认是false
        clientProfile.setDebug(false);
        //endregion

        //region headers 和 body 信息
        HashMap<String, String> headers = new HashMap<>();
        headers.put(X_CLS_TOPIC_ID, TOPIC);
        headers.put(X_CLS_HASH_KEY, "");
        // body lz4 压缩
        headers.put(X_CLS_COMPRESS_TYPE, LZ_4);
        byte[] body = compressedByte(getBodyInfo(logType, params));
        //endregion
        try {
            CommonClient client = new CommonClient(PRODUCT_NAME_CLS, VERSION, cred, Region.Chengdu.getValue(), clientProfile);
            String resp = client.callOctetStream(UPLOAD_LOG_URL, headers, body);
            System.out.println(resp);
        } catch (TencentCloudSDKException te) {
            System.out.println(te.getMessage());
        }
    }

    /**
     * pom依赖:
     * <dependency>
     * <groupId>net.jpountz.lz4</groupId>
     * <artifactId>lz4</artifactId>
     * <version>1.3.0</version>
     * </dependency>
     * <p>
     * 进行lz4压缩
     *
     * @param srcByte
     * @return
     */
    public static byte[] compressedByte(byte[] srcByte) {
        LZ4Factory factory = LZ4Factory.fastestInstance();
        LZ4Compressor compressor = factory.fastCompressor();
        return compressor.compress(srcByte);
    }

    /**
     * pom依赖:
     * <dependency>
     * <groupId>com.google.protobuf</groupId>
     * <artifactId>protobuf-java</artifactId>
     * <version>3.15.3</version>
     * </dependency
     * <p>
     * 构造http body 信息
     * protobuf 序列化为 byte[]
     *
     * @return byte[]
     */
    public static byte[] getBodyInfo(LogType logType, Map<String, String> params) {
        Cls.Log.Builder logBuilder = Cls.Log.newBuilder();
        logBuilder.setTime(System.currentTimeMillis() / 1000L);
        logBuilder.addContents(Cls.Log.Content.newBuilder()
                .setKey("type")
                .setValue(logType.getLabel())
                .build());
        params.forEach((k, v) -> {
            if (v == null) {
                v = "null";
            }
            logBuilder.addContents(Cls.Log.Content.newBuilder()
                    .setKey(k)
                    .setValue(v)
                    .build());
        });
        Cls.Log log = logBuilder.build();
        Cls.LogGroup logGroup = Cls.LogGroup.newBuilder()
                .addLogs(log)
                .build();

        Cls.LogGroupList logGroupList = Cls.LogGroupList.newBuilder()
                .addLogGroupList(logGroup)
                .build();

        //这里我们将封装有数据的对象实例,转换为字节数组,用于数据传输、存储等
        return logGroupList.toByteArray();
    }
}

三、使用示例

代码语言:javascript
复制
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.site.blog.my.core.entity.log.LogType;
import com.site.blog.my.core.util.SendTencentLogUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.HashMap;


/**
 * 请求日志上传切面
 *
 * @author Houchengen
 * @date 2021/09/22
 */
@Aspect
@Component
public class RequestLogAspect {

    @Autowired
    private SendTencentLogUtil sendTencentLogUtil;

    @Pointcut("execution(* com.site.blog.my.core.controller..*(..))")
    public void executeController() {
    }

    @Before("executeController()")
    public void doBefore(JoinPoint joinPoint) {
        //获取请求报文头部元数据
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //获取请求对象
        HttpServletRequest request = requestAttributes.getRequest();
        HashMap<String, String> map = new HashMap<>();
        map.put("params", Arrays.toString(joinPoint.getArgs()));
        map.put("method", request.getMethod());
        map.put("class_method", joinPoint.getSignature().getDeclaringTypeName() +
                "." + joinPoint.getSignature().getName());
        map.put("requestUrl", request.getRequestURL().toString());
        sendTencentLogUtil.sendLog(LogType.INFO, map);
    }

    @AfterReturning(returning = "ret", pointcut = "executeController()")
    public void doAfter(Object ret) {
        HashMap<String, String> map = new HashMap<>();
        map.put("responseBody", JSON.toJSONString(ret, SerializerFeature.WriteMapNullValue));
        sendTencentLogUtil.sendLog(LogType.INFO, map);
    }

}

四、上传后查看

发表时间:2021-09-02

本站文章除注明转载/出处外,皆为作者原创,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、生成PB(Protobuf)上传日志类
  • 二、上传pb日志工具类
    • 1. 日志类型枚举
      • 1. 日志上传类
      • 三、使用示例
      • 四、上传后查看
      相关产品与服务
      日志服务
      日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档