Java 如何在日志导出中将pubsub负载转换为LogEntry对象
我已启用日志导出到发布子主题。我正在使用数据流处理这些日志,并将相关列存储在BigQuery中。请有人帮助将pubsub消息负载转换为Java 如何在日志导出中将pubsub负载转换为LogEntry对象,java,google-cloud-dataflow,google-cloud-pubsub,stackdriver,google-cloud-stackdriver,Java,Google Cloud Dataflow,Google Cloud Pubsub,Stackdriver,Google Cloud Stackdriver,我已启用日志导出到发布子主题。我正在使用数据流处理这些日志,并将相关列存储在BigQuery中。请有人帮助将pubsub消息负载转换为LogEntry对象。 我尝试了以下代码: @ProcessElement public void processElement(ProcessContext c) throws Exception { PubsubMessage pubsubMessage = c.element(); ObjectMapper mapper = new Obj
LogEntry
对象。
我尝试了以下代码:
@ProcessElement
public void processElement(ProcessContext c) throws Exception {
PubsubMessage pubsubMessage = c.element();
ObjectMapper mapper = new ObjectMapper();
byte[] payload = pubsubMessage.getPayload();
String s = new String(payload, "UTF8");
LogEntry logEntry = mapper.readValue(s, LogEntry.class);
}
try {
ByteArrayInputStream stream = new ByteArrayInputStream(Base64.decodeBase64(pubsubMessage.getPayload()));
LogEntry logEntry = LogEntry.parseDelimitedFrom(stream);
System.out.println("Log Entry = " + logEntry);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
但我得到了以下错误:
com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class com.google.protobuf.Descriptors$FieldDescriptor]
编辑:
我尝试了以下代码:
@ProcessElement
public void processElement(ProcessContext c) throws Exception {
PubsubMessage pubsubMessage = c.element();
ObjectMapper mapper = new ObjectMapper();
byte[] payload = pubsubMessage.getPayload();
String s = new String(payload, "UTF8");
LogEntry logEntry = mapper.readValue(s, LogEntry.class);
}
try {
ByteArrayInputStream stream = new ByteArrayInputStream(Base64.decodeBase64(pubsubMessage.getPayload()));
LogEntry logEntry = LogEntry.parseDelimitedFrom(stream);
System.out.println("Log Entry = " + logEntry);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
但我现在得到了以下错误:
com.google.protobuf.InvalidProtocolBufferException:协议消息结束组标记与预期标记不匹配
应该能够执行此操作。Java不是我的强项,但我认为您正在寻找类似于:
@ProcessElement
public void processElement(ProcessContext c) throws Exception {
LogEntry.Builder entryBuilder = LogEntry.newBuilder();
JsonFormat.Parser.usingTypeRegistry(
JsonFormat.TypeRegistry.newBuilder()
.add(LogEntry.getDescriptor())
.build())
.ignoringUnknownFields()
.merge(c.element(), entryBuilder);
LogEntry entry = entryBuilder.build();
...
}
您可能不需要注册类型就可以离开。我认为C++中的PROTO类型链接到一个全局注册表。p>
您将需要“IgnoringUnknowFields”,以防服务添加新字段并导出它们,而您尚未更新原型描述符的副本。导出的JSON中也会导致问题的任何“@type”字段
您可能需要对有效负载进行特殊处理(即从JSON中剥离if,然后单独解析)。如果是JSON,我希望解析器尝试填充不存在的子消息。如果它是原型。。。如果您也注册该类型,它实际上可能会起作用。应该能够做到这一点。Java不是我的强项,但我认为您正在寻找类似于:
@ProcessElement
public void processElement(ProcessContext c) throws Exception {
LogEntry.Builder entryBuilder = LogEntry.newBuilder();
JsonFormat.Parser.usingTypeRegistry(
JsonFormat.TypeRegistry.newBuilder()
.add(LogEntry.getDescriptor())
.build())
.ignoringUnknownFields()
.merge(c.element(), entryBuilder);
LogEntry entry = entryBuilder.build();
...
}
您可能不需要注册类型就可以离开。我认为C++中的PROTO类型链接到一个全局注册表。p>
您将需要“IgnoringUnknowFields”,以防服务添加新字段并导出它们,而您尚未更新原型描述符的副本。导出的JSON中也会导致问题的任何“@type”字段
您可能需要对有效负载进行特殊处理(即从JSON中剥离if,然后单独解析)。如果是JSON,我希望解析器尝试填充不存在的子消息。如果它是原型。。。如果你也注册这个类型,它实际上可能会起作用