syntax = "proto2";

package code.justin.tv.release.trace.pbmsg;
option go_package = "pbmsg";

import public "code.justin.tv/release/trace/pbmsg/iana/iana.proto";
import public "code.justin.tv/release/trace/pbmsg/memcached/memcached.proto";
import "code.justin.tv/release/trace/pbmsg/event.proto";

// A Transaction groups together a collection of Calls into one
// tree. It provides access to the transaction_id which is shared by
// all of its constituent Calls.
message Transaction {
  // 128-bit identifier for the transaction, as set in
  // code.justin.tv.release.trace.pbmsg.Event messages: two 64-bit
  // integers, least significant word first.
  repeated fixed64 transaction_id = 1 [packed=true];
  // root stores the data on the root call of the transaction.
  optional Call root = 2;
  // In some rare cases, the root client of a transaction may be
  // known. If that's the case, such data can be stored in the
  // optional client field.
  optional Service client = 3;
}

// A Call represents a single RPC call out to a service in the
// distributed stack trace.
//
// The client of the call is not explicitly listed here. The client
// can instead be inferred from the entire Transaction's tree:
//
//   - If this is the root call in the RPC tree, then the Transaction
//     has an optional client field which lists the client if it sends
//     data to trace. If not, then the client can't be known.
//   - If this is non-root node, then it has a parent. The svc of the
//     parent call is the client of this call.
message Call {
  // subcalls are the subcalls that this call depended on, in path order.
  repeated Call subcalls = 1;
  // path is the same path identifier as used in event.proto.
  repeated uint32 path = 2 [packed=true];

  // svc holds the identity of the service which served the RPC
  // call. This might be left unset if the service does not send data
  // to Trace.
  optional Service svc = 3;

  // params are the parameters of the Call, like the HTTP URI or SQL
  // query. They may be filled by either client or server; the
  // server's log of its outbound request should be preferred if they
  // conflict, since server owners are responsible for maintaining
  // metadata about what RPCs they provide.
  optional RPCParams params = 4;

  // client_timestamps and service_timestamps provide lists of timing
  // information accordiong to each side of the call. They will only
  // be available if the respective side is sending Trace data. They
  // will be sorted by increasing time values (earliest first, in
  // other words). It's guaranteed that at least one set of timestamps
  // will have at least one value.
  repeated Timestamp client_timestamps = 5;
  repeated Timestamp service_timestamps = 6;

  // request_sent_to is the host:port that the client established its
  // connection to to make the RPC. This is the client's perception,
  // and doesn't necessarily reflect where the server is actually
  // listening; proxies might be in between.
  optional string request_sent_to = 7;
}

// Service represents an application which is capable of handling RPC
// calls.
message Service {
  // The name of the service
  optional string name = 1;
  // The FQDN of the host that the service is running on
  optional string host = 2;
  // PID of the process
  optional sint32 pid = 3;
  // The ip:port sending the request to this service.
  optional string peer = 4;
}

// Timestamp provides a marker for when something happened in a call.
message Timestamp {
  // time is when a call started, recorded as unix epoch
  // time in nanoseconds
  optional sfixed64 time = 1;
  // kind describes what happened at the specified time
  optional Event.Kind kind = 2;
}

// RPCParams contains data on the details of the request that the
// client made.
message RPCParams {
  optional HTTPParams http = 1;
  optional SQLParams sql = 2;
  optional MemcachedParams memcached = 3;
  optional GRPCParams grpc = 4;
}

message HTTPParams {
  // The path part of the URI of the request.
  optional string uri_path = 1;

  // HTTP Status code. Values less than zero indicate an error
  // observed by the client which caused it to give up on the request
  // before getting a status code from the server.
  optional sint32 status = 2;

  // Method of HTTP request.
  optional iana.HTTPMethod method = 3;

  // If we have sufficient data to give a name to the route, then that
  // human-readable name will be stored here.
  optional string route = 4;
}

message SQLParams {
  // Name of the database where the query runs.
  optional string dbname = 1;
  // Username used to connect to the database.
  optional string dbuser = 2;
  // Query string with all user data removed.
  optional string stripped_query = 3;
  // List of tables directly referenced in the query.
  repeated string tables = 4;
}

message MemcachedParams {
  // The command sent to memcached by a client
  optional memcached.Command command = 1;

  // The number of keys in the client's request
  optional uint32 n_keys_request = 2;

  // The number of keys in the server's response
  optional uint32 n_keys_response = 3;
}

message GRPCParams {
  // Fully-qualified method name, including proto package name,
  // service name, and method name.
  optional string method = 1;
}
