#
# Autogenerated by Thrift Compiler (0.9.3)
#
# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
#
#  options string: py:new_style=true:slots=true
#

from thrift.Thrift import TType, TMessageType, TException, TApplicationException

from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol, TProtocol
try:
  from thrift.protocol import fastbinary
except:
  fastbinary = None


class AnnotationType(object):
  """
  A subset of thrift base types, except BYTES.
  """
  BOOL = 0
  BYTES = 1
  I16 = 2
  I32 = 3
  I64 = 4
  DOUBLE = 5
  STRING = 6

  _VALUES_TO_NAMES = {
    0: "BOOL",
    1: "BYTES",
    2: "I16",
    3: "I32",
    4: "I64",
    5: "DOUBLE",
    6: "STRING",
  }

  _NAMES_TO_VALUES = {
    "BOOL": 0,
    "BYTES": 1,
    "I16": 2,
    "I32": 3,
    "I64": 4,
    "DOUBLE": 5,
    "STRING": 6,
  }


class Endpoint(object):
  """
  Indicates the network context of a service involved in a span.

  Attributes:
   - ipv4: IPv4 host address packed into 4 bytes.

  Ex for the ip 1.2.3.4, it would be (1 << 24) | (2 << 16) | (3 << 8) | 4
   - port: IPv4 port or 0, if unknown.

  Note: this is to be treated as an unsigned integer, so watch for negatives.
   - service_name: Classifier of a source or destination in lowercase, such as "zipkin-web".

  This is the primary parameter for trace lookup, so should be intuitive as
  possible, for example, matching names in service discovery.

  Conventionally, when the service name isn't known, service_name = "unknown".
  However, it is also permissible to set service_name = "" (empty string).
  The difference in the latter usage is that the span will not be queryable
  by service name unless more information is added to the span with non-empty
  service name, e.g. an additional annotation from the server.

  Particularly clients may not have a reliable service name at ingest. One
  approach is to set service_name to "" at ingest, and later assign a
  better label based on binary annotations, such as user agent.
  """

  thrift_spec = (
    None, # 0
    (1, TType.I32, 'ipv4', None, None, ), # 1
    (2, TType.I16, 'port', None, None, ), # 2
    (3, TType.STRING, 'service_name', None, None, ), # 3
  )

  def __init__(self, ipv4=None, port=None, service_name=None,):
    self.ipv4 = ipv4
    self.port = port
    self.service_name = service_name

  def read(self, iprot):
    if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
      fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
      return
    iprot.readStructBegin()
    while True:
      (fname, ftype, fid) = iprot.readFieldBegin()
      if ftype == TType.STOP:
        break
      if fid == 1:
        if ftype == TType.I32:
          self.ipv4 = iprot.readI32()
        else:
          iprot.skip(ftype)
      elif fid == 2:
        if ftype == TType.I16:
          self.port = iprot.readI16()
        else:
          iprot.skip(ftype)
      elif fid == 3:
        if ftype == TType.STRING:
          self.service_name = iprot.readString()
        else:
          iprot.skip(ftype)
      else:
        iprot.skip(ftype)
      iprot.readFieldEnd()
    iprot.readStructEnd()

  def write(self, oprot):
    if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
      oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
      return
    oprot.writeStructBegin('Endpoint')
    if self.ipv4 is not None:
      oprot.writeFieldBegin('ipv4', TType.I32, 1)
      oprot.writeI32(self.ipv4)
      oprot.writeFieldEnd()
    if self.port is not None:
      oprot.writeFieldBegin('port', TType.I16, 2)
      oprot.writeI16(self.port)
      oprot.writeFieldEnd()
    if self.service_name is not None:
      oprot.writeFieldBegin('service_name', TType.STRING, 3)
      oprot.writeString(self.service_name)
      oprot.writeFieldEnd()
    oprot.writeFieldStop()
    oprot.writeStructEnd()

  def validate(self):
    return


  def __hash__(self):
    value = 17
    value = (value * 31) ^ hash(self.ipv4)
    value = (value * 31) ^ hash(self.port)
    value = (value * 31) ^ hash(self.service_name)
    return value

  def __repr__(self):
    L = ['%s=%r' % (key, value)
      for key, value in self.__dict__.iteritems()]
    return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

  def __eq__(self, other):
    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

  def __ne__(self, other):
    return not (self == other)

class Annotation(object):
  """
  Associates an event that explains latency with a timestamp.

  Unlike log statements, annotations are often codes: for example "sr".

  Attributes:
   - timestamp: Microseconds from epoch.

  This value should use the most precise value possible. For example,
  gettimeofday or syncing nanoTime against a tick of currentTimeMillis.
   - value: Usually a short tag indicating an event, like "sr" or "finagle.retry".
   - host: The host that recorded the value, primarily for query by service name.
  """

  thrift_spec = (
    None, # 0
    (1, TType.I64, 'timestamp', None, None, ), # 1
    (2, TType.STRING, 'value', None, None, ), # 2
    (3, TType.STRUCT, 'host', (Endpoint, Endpoint.thrift_spec), None, ), # 3
  )

  def __init__(self, timestamp=None, value=None, host=None,):
    self.timestamp = timestamp
    self.value = value
    self.host = host

  def read(self, iprot):
    if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
      fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
      return
    iprot.readStructBegin()
    while True:
      (fname, ftype, fid) = iprot.readFieldBegin()
      if ftype == TType.STOP:
        break
      if fid == 1:
        if ftype == TType.I64:
          self.timestamp = iprot.readI64()
        else:
          iprot.skip(ftype)
      elif fid == 2:
        if ftype == TType.STRING:
          self.value = iprot.readString()
        else:
          iprot.skip(ftype)
      elif fid == 3:
        if ftype == TType.STRUCT:
          self.host = Endpoint()
          self.host.read(iprot)
        else:
          iprot.skip(ftype)
      else:
        iprot.skip(ftype)
      iprot.readFieldEnd()
    iprot.readStructEnd()

  def write(self, oprot):
    if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
      oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
      return
    oprot.writeStructBegin('Annotation')
    if self.timestamp is not None:
      oprot.writeFieldBegin('timestamp', TType.I64, 1)
      oprot.writeI64(self.timestamp)
      oprot.writeFieldEnd()
    if self.value is not None:
      oprot.writeFieldBegin('value', TType.STRING, 2)
      oprot.writeString(self.value)
      oprot.writeFieldEnd()
    if self.host is not None:
      oprot.writeFieldBegin('host', TType.STRUCT, 3)
      self.host.write(oprot)
      oprot.writeFieldEnd()
    oprot.writeFieldStop()
    oprot.writeStructEnd()

  def validate(self):
    return


  def __hash__(self):
    value = 17
    value = (value * 31) ^ hash(self.timestamp)
    value = (value * 31) ^ hash(self.value)
    value = (value * 31) ^ hash(self.host)
    return value

  def __repr__(self):
    L = ['%s=%r' % (key, value)
      for key, value in self.__dict__.iteritems()]
    return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

  def __eq__(self, other):
    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

  def __ne__(self, other):
    return not (self == other)

class BinaryAnnotation(object):
  """
  Binary annotations are tags applied to a Span to give it context. For
  example, a binary annotation of "http.uri" could the path to a resource in a
  RPC call.

  Binary annotations of type STRING are always queryable, though more a
  historical implementation detail than a structural concern.

  Binary annotations can repeat, and vary on the host. Similar to Annotation,
  the host indicates who logged the event. This allows you to tell the
  difference between the client and server side of the same key. For example,
  the key "http.uri" might be different on the client and server side due to
  rewriting, like "/api/v1/myresource" vs "/myresource. Via the host field,
  you can see the different points of view, which often help in debugging.

  Attributes:
   - key: Name used to lookup spans, such as "http.uri" or "finagle.version".
   - value: Serialized thrift bytes, in TBinaryProtocol format.

  For legacy reasons, byte order is big-endian. See THRIFT-3217.
   - annotation_type: The thrift type of value, most often STRING.

  annotation_type shouldn't vary for the same key.
   - host: The host that recorded value, allowing query by service name or address.

  There are two exceptions: when key is "ca" or "sa", this is the source or
  destination of an RPC. This exception allows zipkin to display network
  context of uninstrumented services, such as browsers or databases.
  """

  thrift_spec = (
    None, # 0
    (1, TType.STRING, 'key', None, None, ), # 1
    (2, TType.STRING, 'value', None, None, ), # 2
    (3, TType.I32, 'annotation_type', None, None, ), # 3
    (4, TType.STRUCT, 'host', (Endpoint, Endpoint.thrift_spec), None, ), # 4
  )

  def __init__(self, key=None, value=None, annotation_type=None, host=None,):
    self.key = key
    self.value = value
    self.annotation_type = annotation_type
    self.host = host

  def read(self, iprot):
    if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
      fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
      return
    iprot.readStructBegin()
    while True:
      (fname, ftype, fid) = iprot.readFieldBegin()
      if ftype == TType.STOP:
        break
      if fid == 1:
        if ftype == TType.STRING:
          self.key = iprot.readString()
        else:
          iprot.skip(ftype)
      elif fid == 2:
        if ftype == TType.STRING:
          self.value = iprot.readString()
        else:
          iprot.skip(ftype)
      elif fid == 3:
        if ftype == TType.I32:
          self.annotation_type = iprot.readI32()
        else:
          iprot.skip(ftype)
      elif fid == 4:
        if ftype == TType.STRUCT:
          self.host = Endpoint()
          self.host.read(iprot)
        else:
          iprot.skip(ftype)
      else:
        iprot.skip(ftype)
      iprot.readFieldEnd()
    iprot.readStructEnd()

  def write(self, oprot):
    if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
      oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
      return
    oprot.writeStructBegin('BinaryAnnotation')
    if self.key is not None:
      oprot.writeFieldBegin('key', TType.STRING, 1)
      oprot.writeString(self.key)
      oprot.writeFieldEnd()
    if self.value is not None:
      oprot.writeFieldBegin('value', TType.STRING, 2)
      oprot.writeString(self.value)
      oprot.writeFieldEnd()
    if self.annotation_type is not None:
      oprot.writeFieldBegin('annotation_type', TType.I32, 3)
      oprot.writeI32(self.annotation_type)
      oprot.writeFieldEnd()
    if self.host is not None:
      oprot.writeFieldBegin('host', TType.STRUCT, 4)
      self.host.write(oprot)
      oprot.writeFieldEnd()
    oprot.writeFieldStop()
    oprot.writeStructEnd()

  def validate(self):
    return


  def __hash__(self):
    value = 17
    value = (value * 31) ^ hash(self.key)
    value = (value * 31) ^ hash(self.value)
    value = (value * 31) ^ hash(self.annotation_type)
    value = (value * 31) ^ hash(self.host)
    return value

  def __repr__(self):
    L = ['%s=%r' % (key, value)
      for key, value in self.__dict__.iteritems()]
    return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

  def __eq__(self, other):
    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

  def __ne__(self, other):
    return not (self == other)

class Span(object):
  """
  A trace is a series of spans (often RPC calls) which form a latency tree.

  Spans are usually created by instrumentation in RPC clients or servers, but
  can also represent in-process activity. Annotations in spans are similar to
  log statements, and are sometimes created directly by application developers
  to indicate events of interest, such as a cache miss.

  The root span is where parent_id = Nil; it usually has the longest duration
  in the trace.

  Span identifiers are packed into i64s, but should be treated opaquely.
  String encoding is fixed-width lower-hex, to avoid signed interpretation.

  Attributes:
   - trace_id: Unique 8-byte identifier for a trace, set on all spans within it.
   - name: Span name in lowercase, rpc method for example. Conventionally, when the
  span name isn't known, name = "unknown".
   - id: Unique 8-byte identifier of this span within a trace. A span is uniquely
  identified in storage by (trace_id, id).
   - parent_id: The parent's Span.id; absent if this the root span in a trace.
   - annotations: Associates events that explain latency with a timestamp. Unlike log
  statements, annotations are often codes: for example SERVER_RECV("sr").
  Annotations are sorted ascending by timestamp.
   - binary_annotations: Tags a span with context, usually to support query or aggregation. For
  example, a binary annotation key could be "http.uri".
   - debug: True is a request to store this span even if it overrides sampling policy.
   - timestamp: Epoch microseconds of the start of this span, absent if this an incomplete
  span.

  This value should be set directly by instrumentation, using the most
  precise value possible. For example, gettimeofday or syncing nanoTime
  against a tick of currentTimeMillis.

  For compatibilty with instrumentation that precede this field, collectors
  or span stores can derive this via Annotation.timestamp.
  For example, SERVER_RECV.timestamp or CLIENT_SEND.timestamp.

  Timestamp is nullable for input only. Spans without a timestamp cannot be
  presented in a timeline: Span stores should not output spans missing a
  timestamp.

  There are two known edge-cases where this could be absent: both cases
  exist when a collector receives a span in parts and a binary annotation
  precedes a timestamp. This is possible when..
   - The span is in-flight (ex not yet received a timestamp)
   - The span's start event was lost
   - duration: Measurement in microseconds of the critical path, if known.

  This value should be set directly, as opposed to implicitly via annotation
  timestamps. Doing so encourages precision decoupled from problems of
  clocks, such as skew or NTP updates causing time to move backwards.

  For compatibility with instrumentation that precede this field, collectors
  or span stores can derive this by subtracting Annotation.timestamp.
  For example, SERVER_SEND.timestamp - SERVER_RECV.timestamp.

  If this field is persisted as unset, zipkin will continue to work, except
  duration query support will be implementation-specific. Similarly, setting
  this field non-atomically is implementation-specific.

  This field is i64 vs i32 to support spans longer than 35 minutes.
  """

  thrift_spec = (
    None, # 0
    (1, TType.I64, 'trace_id', None, None, ), # 1
    None, # 2
    (3, TType.STRING, 'name', None, None, ), # 3
    (4, TType.I64, 'id', None, None, ), # 4
    (5, TType.I64, 'parent_id', None, None, ), # 5
    (6, TType.LIST, 'annotations', (TType.STRUCT,(Annotation, Annotation.thrift_spec)), None, ), # 6
    None, # 7
    (8, TType.LIST, 'binary_annotations', (TType.STRUCT,(BinaryAnnotation, BinaryAnnotation.thrift_spec)), None, ), # 8
    (9, TType.BOOL, 'debug', None, False, ), # 9
    (10, TType.I64, 'timestamp', None, None, ), # 10
    (11, TType.I64, 'duration', None, None, ), # 11
  )

  def __init__(self, trace_id=None, name=None, id=None, parent_id=None, annotations=None, binary_annotations=None, debug=thrift_spec[9][4], timestamp=None, duration=None,):
    self.trace_id = trace_id
    self.name = name
    self.id = id
    self.parent_id = parent_id
    self.annotations = annotations
    self.binary_annotations = binary_annotations
    self.debug = debug
    self.timestamp = timestamp
    self.duration = duration

  def read(self, iprot):
    if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
      fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
      return
    iprot.readStructBegin()
    while True:
      (fname, ftype, fid) = iprot.readFieldBegin()
      if ftype == TType.STOP:
        break
      if fid == 1:
        if ftype == TType.I64:
          self.trace_id = iprot.readI64()
        else:
          iprot.skip(ftype)
      elif fid == 3:
        if ftype == TType.STRING:
          self.name = iprot.readString()
        else:
          iprot.skip(ftype)
      elif fid == 4:
        if ftype == TType.I64:
          self.id = iprot.readI64()
        else:
          iprot.skip(ftype)
      elif fid == 5:
        if ftype == TType.I64:
          self.parent_id = iprot.readI64()
        else:
          iprot.skip(ftype)
      elif fid == 6:
        if ftype == TType.LIST:
          self.annotations = []
          (_etype3, _size0) = iprot.readListBegin()
          for _i4 in xrange(_size0):
            _elem5 = Annotation()
            _elem5.read(iprot)
            self.annotations.append(_elem5)
          iprot.readListEnd()
        else:
          iprot.skip(ftype)
      elif fid == 8:
        if ftype == TType.LIST:
          self.binary_annotations = []
          (_etype9, _size6) = iprot.readListBegin()
          for _i10 in xrange(_size6):
            _elem11 = BinaryAnnotation()
            _elem11.read(iprot)
            self.binary_annotations.append(_elem11)
          iprot.readListEnd()
        else:
          iprot.skip(ftype)
      elif fid == 9:
        if ftype == TType.BOOL:
          self.debug = iprot.readBool()
        else:
          iprot.skip(ftype)
      elif fid == 10:
        if ftype == TType.I64:
          self.timestamp = iprot.readI64()
        else:
          iprot.skip(ftype)
      elif fid == 11:
        if ftype == TType.I64:
          self.duration = iprot.readI64()
        else:
          iprot.skip(ftype)
      else:
        iprot.skip(ftype)
      iprot.readFieldEnd()
    iprot.readStructEnd()

  def write(self, oprot):
    if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
      oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
      return
    oprot.writeStructBegin('Span')
    if self.trace_id is not None:
      oprot.writeFieldBegin('trace_id', TType.I64, 1)
      oprot.writeI64(self.trace_id)
      oprot.writeFieldEnd()
    if self.name is not None:
      oprot.writeFieldBegin('name', TType.STRING, 3)
      oprot.writeString(self.name)
      oprot.writeFieldEnd()
    if self.id is not None:
      oprot.writeFieldBegin('id', TType.I64, 4)
      oprot.writeI64(self.id)
      oprot.writeFieldEnd()
    if self.parent_id is not None:
      oprot.writeFieldBegin('parent_id', TType.I64, 5)
      oprot.writeI64(self.parent_id)
      oprot.writeFieldEnd()
    if self.annotations is not None:
      oprot.writeFieldBegin('annotations', TType.LIST, 6)
      oprot.writeListBegin(TType.STRUCT, len(self.annotations))
      for iter12 in self.annotations:
        iter12.write(oprot)
      oprot.writeListEnd()
      oprot.writeFieldEnd()
    if self.binary_annotations is not None:
      oprot.writeFieldBegin('binary_annotations', TType.LIST, 8)
      oprot.writeListBegin(TType.STRUCT, len(self.binary_annotations))
      for iter13 in self.binary_annotations:
        iter13.write(oprot)
      oprot.writeListEnd()
      oprot.writeFieldEnd()
    if self.debug is not None:
      oprot.writeFieldBegin('debug', TType.BOOL, 9)
      oprot.writeBool(self.debug)
      oprot.writeFieldEnd()
    if self.timestamp is not None:
      oprot.writeFieldBegin('timestamp', TType.I64, 10)
      oprot.writeI64(self.timestamp)
      oprot.writeFieldEnd()
    if self.duration is not None:
      oprot.writeFieldBegin('duration', TType.I64, 11)
      oprot.writeI64(self.duration)
      oprot.writeFieldEnd()
    oprot.writeFieldStop()
    oprot.writeStructEnd()

  def validate(self):
    return


  def __hash__(self):
    value = 17
    value = (value * 31) ^ hash(self.trace_id)
    value = (value * 31) ^ hash(self.name)
    value = (value * 31) ^ hash(self.id)
    value = (value * 31) ^ hash(self.parent_id)
    value = (value * 31) ^ hash(self.annotations)
    value = (value * 31) ^ hash(self.binary_annotations)
    value = (value * 31) ^ hash(self.debug)
    value = (value * 31) ^ hash(self.timestamp)
    value = (value * 31) ^ hash(self.duration)
    return value

  def __repr__(self):
    L = ['%s=%r' % (key, value)
      for key, value in self.__dict__.iteritems()]
    return '%s(%s)' % (self.__class__.__name__, ', '.join(L))

  def __eq__(self, other):
    return isinstance(other, self.__class__) and self.__dict__ == other.__dict__

  def __ne__(self, other):
    return not (self == other)
