java什么是报文日志_Java:gRPC中如何将输入输出报文以json格式打印到日志文件中...

gRPC是使用二进制格式传输报文的,有时项目需要记录请求调用输入输出日志,以方便错误排查。但以二进制记录报文的话不方便查看,如果记录的日志是以json或XML的形式,则更方便查看,下面本文将介绍如果将输入输出报文以json的形式记录到日志文件中。

首先,实现一个用户打印日志的Marshaller,它创建时需要传入实现进行报文转换的Marshaller,此Marshaller只是把转换后的object转换成json(解析输入报文后),或者将转换前的object转换成json(生成输出报文前),并打印到日志文件中。

package com.example.tutorial.tool;

import java.io.InputStream;

import java.util.logging.Level;

import java.util.logging.Logger;

import com.google.protobuf.Message;

import com.google.protobuf.util.JsonFormat;

import com.google.protobuf.util.JsonFormat.Printer;

import io.grpc.MethodDescriptor.Marshaller;

/**

* 使用JSON格式记录输入与输出日志

*

*/

public class JsonLoggerMarshallerimplements Marshaller{

private static final Logger LOG = Logger.getLogger(JsonLoggerMarshaller.class.getName());

private MarshallerbaseMarshaller;

private final Printer printer = JsonFormat.printer().omittingInsignificantWhitespace();

public JsonLoggerMarshaller(MarshallerbaseMarshaller) {

this.baseMarshaller = baseMarshaller;

}

public InputStream stream(T value) {

try {

// 记录输出日志

String info = printer.print(value);

LOG.info("output:" + info);

} catch (Exception e) {

LOG.log(Level.SEVERE, "do stream error", e);

}

return baseMarshaller.stream(value);

}

public T parse(InputStream stream) {

T msg = baseMarshaller.parse(stream);

try {

// 记录输入日志

String info = printer.print(msg);

LOG.info("input:" + info);

} catch (Exception e) {

LOG.log(Level.SEVERE, "do parse error", e);

}

return msg;

}

}

然后,使用如下代码将JsonLoggerMarshaller注册到服务中去。

package com.example.tutorial.tool;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

import java.lang.reflect.Modifier;

import java.util.logging.Level;

import java.util.logging.Logger;

import io.grpc.MethodDescriptor;

import io.grpc.MethodDescriptor.Marshaller;

import io.grpc.MethodDescriptor.PrototypeMarshaller;

public class GlobalMarshallerInitializer {

private static final Logger LOG = Logger.getLogger(GlobalMarshallerInitializer.class.getName());

// 为记录json格式的日志,注册JsonLoggerMarshaller

public static void initiateJsonLoggerMarshaller(Class> serviceClass) {

try {

Field serviceNameField = serviceClass.getField("SERVICE_NAME");

if (serviceNameField == null) {

return;

}

for (Method m : serviceClass.getDeclaredMethods()) {

if (Modifier.isStatic(m.getModifiers()) && m.getReturnType() == MethodDescriptor.class) {

// 为各RPC调用方法生成默认的MethodDescriptor,默认MethodDescriptor中的Marshaller使用的是二进制格式传输报文

MethodDescriptor, ?> md = (MethodDescriptor, ?>) m.invoke(null);

Field requestMarshallerField = md.getClass().getDeclaredField("requestMarshaller");

Field responseMarshallerField = md.getClass().getDeclaredField("responseMarshaller");

// 使用反射机制设置输入与输出Marshaller

requestMarshallerField.setAccessible(true);

requestMarshallerField.set(md, new JsonLoggerMarshaller(md.getRequestMarshaller()));

requestMarshallerField.setAccessible(false);

responseMarshallerField.setAccessible(true);

responseMarshallerField.set(md, new JsonLoggerMarshaller(md.getResponseMarshaller()));

responseMarshallerField.setAccessible(false);

LOG.info("finish to initiate method: " + md.getFullMethodName());

}

}

} catch (Exception e) {

LOG.log(Level.SEVERE, "fail to initiate JsonLoggerMarshaller " + serviceClass.getName(), e);

}

}

}

最后,只需要在服务端代码和客户端代码中,对需要日志功能的服务,调用上述代码进行初始化。

GlobalMarshallerInitializer.initiateJsonLoggerMarshaller(GreeterGrpc.class);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值