如何在日志导出

时间:2017-11-11 18:13:01

标签: java google-cloud-dataflow google-cloud-pubsub stackdriver google-cloud-stackdriver

我已将日志导出启用到pub子主题。我正在使用数据流来处理这些日志并在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);
}

但是我收到了以下错误:

com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class com.google.protobuf.Descriptors$FieldDescriptor]

编辑: 我尝试了以下代码:

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: Protocol message end-group tag did not match expected tag

1 个答案:

答案 0 :(得分:0)

JSON format parser应该能够做到这一点。 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类型链接到全局注册表。

如果服务添加新字段并导出它们并且您尚未更新proto描述符的副本,则需要“ignoringUnknownFields”。导出的JSON中的任何“@type”字段也会导致问题。

您可能需要对有效负载进行特殊处理(即,如果从JSON中剥离,然后单独解析)。如果它是JSON,我希望解析器尝试填充不存在的子消息。如果它是原型......如果你也注册Any类型,它实际上可能有用。