All Downloads are FREE. Search and download functionalities are using the official Maven repository.

zipkin2.elasticsearch.internal.JsonSerializers Maven / Gradle / Ivy

/*
 * Copyright The OpenZipkin Authors
 * SPDX-License-Identifier: Apache-2.0
 */
package zipkin2.elasticsearch.internal;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.OutputStream;
import zipkin2.Annotation;
import zipkin2.DependencyLink;
import zipkin2.Endpoint;
import zipkin2.Span;

/**
 * JSON serialization utilities and parsing code.
 */
public final class JsonSerializers {
  public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
    .setSerializationInclusion(JsonInclude.Include.NON_NULL);
  public static final JsonFactory JSON_FACTORY = new JsonFactory();

  public static JsonGenerator jsonGenerator(OutputStream stream) {
    try {
      return JSON_FACTORY.createGenerator(stream);
    } catch (IOException e) {
      throw new AssertionError("Could not create JSON generator for a memory stream.", e);
    }
  }

  public interface ObjectParser {
    T parse(JsonParser jsonParser) throws IOException;
  }

  public static final ObjectParser SPAN_PARSER = JsonSerializers::parseSpan;

  static Span parseSpan(JsonParser parser) throws IOException {
    if (!parser.isExpectedStartObjectToken()) {
      throw new IllegalArgumentException("Not a valid JSON object, start token: " +
        parser.currentToken());
    }

    Span.Builder result = Span.newBuilder();

    JsonToken value;
    while ((value = parser.nextValue()) != JsonToken.END_OBJECT) {
      if (value == null) {
        throw new IOException("End of input while parsing object.");
      }
      if (value == JsonToken.VALUE_NULL) {
        continue;
      }
      switch (parser.currentName()) {
        case "traceId":
          result.traceId(parser.getText());
          break;
        case "parentId":
          result.parentId(parser.getText());
          break;
        case "id":
          result.id(parser.getText());
          break;
        case "kind":
          result.kind(Span.Kind.valueOf(parser.getText()));
          break;
        case "name":
          result.name(parser.getText());
          break;
        case "timestamp":
          result.timestamp(parser.getLongValue());
          break;
        case "duration":
          result.duration(parser.getLongValue());
          break;
        case "localEndpoint":
          result.localEndpoint(parseEndpoint(parser));
          break;
        case "remoteEndpoint":
          result.remoteEndpoint(parseEndpoint(parser));
          break;
        case "annotations":
          if (value != JsonToken.START_ARRAY) {
            throw new IOException("Invalid span, expecting annotations array start, got: " +
              value);
          }
          while (parser.nextToken() != JsonToken.END_ARRAY) {
            Annotation a = parseAnnotation(parser);
            result.addAnnotation(a.timestamp(), a.value());
          }
          break;
        case "tags":
          if (value != JsonToken.START_OBJECT) {
            throw new IOException("Invalid span, expecting tags object, got: " + value);
          }
          while (parser.nextValue() != JsonToken.END_OBJECT) {
            result.putTag(parser.currentName(), parser.getValueAsString());
          }
          break;
        case "debug":
          result.debug(parser.getBooleanValue());
          break;
        case "shared":
          result.shared(parser.getBooleanValue());
          break;
        default:
          // Skip
      }
    }

    return result.build();
  }

  static Endpoint parseEndpoint(JsonParser parser) throws IOException {
    if (!parser.isExpectedStartObjectToken()) {
      throw new IllegalArgumentException("Not a valid JSON object, start token: " +
        parser.currentToken());
    }

    String serviceName = null, ipv4 = null, ipv6 = null;
    int port = 0;

    while (parser.nextToken() != JsonToken.END_OBJECT) {
      JsonToken value = parser.nextValue();
      if (value == JsonToken.VALUE_NULL) {
        continue;
      }

      switch (parser.currentName()) {
        case "serviceName":
          serviceName = parser.getText();
          break;
        case "ipv4":
          ipv4 = parser.getText();
          break;
        case "ipv6":
          ipv6 = parser.getText();
          break;
        case "port":
          port = parser.getIntValue();
          break;
        default:
          // Skip
      }
    }

    if (serviceName == null && ipv4 == null && ipv6 == null && port == 0) return null;
    return Endpoint.newBuilder()
      .serviceName(serviceName)
      .ip(ipv4)
      .ip(ipv6)
      .port(port)
      .build();
  }

  static Annotation parseAnnotation(JsonParser parser) throws IOException {
    if (!parser.isExpectedStartObjectToken()) {
      throw new IllegalArgumentException("Not a valid JSON object, start token: " +
        parser.currentToken());
    }

    long timestamp = 0;
    String value = null;

    while (parser.nextValue() != JsonToken.END_OBJECT) {
      switch (parser.currentName()) {
        case "timestamp":
          timestamp = parser.getLongValue();
          break;
        case "value":
          value = parser.getValueAsString();
          break;
        default:
          // Skip
      }
    }

    if (timestamp == 0 || value == null) {
      throw new IllegalArgumentException("Incomplete annotation at " + parser.currentToken());
    }
    return Annotation.create(timestamp, value);
  }

  public static final ObjectParser DEPENDENCY_LINK_PARSER = parser -> {
    if (!parser.isExpectedStartObjectToken()) {
      throw new IllegalArgumentException("Expected start of dependency link object but was "
        + parser.currentToken());
    }

    DependencyLink.Builder result = DependencyLink.newBuilder();
    JsonToken value;
    while ((value = parser.nextValue()) != JsonToken.END_OBJECT) {
      if (value == null) {
        throw new IOException("End of input while parsing object.");
      }
      switch (parser.currentName()) {
        case "parent":
          result.parent(parser.getText());
          break;
        case "child":
          result.child(parser.getText());
          break;
        case "callCount":
          result.callCount(parser.getLongValue());
          break;
        case "errorCount":
          result.errorCount(parser.getLongValue());
          break;
        default:
          // Skip
      }
    }
    return result.build();
  };
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy