Java 如何在日志导出中将pubsub负载转换为LogEntry对象

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

我已启用日志导出到发布子主题。我正在使用数据流处理这些日志,并将相关列存储在BigQuery中。请有人帮助将pubsub消息负载转换为
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,我希望解析器尝试填充不存在的子消息。如果它是原型。。。如果你也注册这个类型,它实际上可能会起作用