blob: 636179b0e27b0782f57fefec52c762db561e8fe1 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library cobalt;
// Cobalt is the service used in Fuchsia to report metrics. This file contains
// interfaces that allow clients to report metric Observations to Cobalt.
// To use Cobalt, you must have a project id, metric id and encoding id
// registered with the Cobalt system. In the current verison of Cobalt
// registration consists of entries in the YAML files in this repo:
// https://cobalt-analytics.googlesource.com/config/.
// In a Garnet checkout that is mapped to //third_party/cobalt_config.
// While Cobalt's code and registration files are open source, the running
// system being managed by the Cobalt team is currently intended to be used by
// software engineers at Google in order to collect metrics in a way that
// preserves our users' privacy. If you are a Google software engineer
// please see our internal [user guide](go/fuchsia-cobalt-userguide) or
// ask for assistance from the Cobalt [team](go/fuchsia-cobalt#comms).
// Usage: First use CobaltEncoderFactory to get a CobaltEncoder for your
// project. Then you add Observations using the Add*Observation() methods.
// Observations are accumulated by the CobaltEncoder and periodically sent
// to the Cobalt server.
// The maximum size of a single Observation is 100 KB.
const int64 kMaxBytesPerObservation = 102400;
// Response codes for Cobalt encoder operations.
enum Status : int32 {
OK = 0;
// For example the supplied metric id, encoding id or observation value is
// invalid.
INVALID_ARGUMENTS = 1;
// Sending observations failed too many times or with an unrecoverable error
// Try the send again later. OBSOLETE: This status is never used.
SEND_FAILED = 2;
// The attempted operation failed because some precondition was not met.
// OBSOLETE: This status is never used.
FAILED_PRECONDITION = 3;
// An attempt was made to add an Observation whose seralized size exceeds
// kMaxBytesPerObservation.
OBSERVATION_TOO_BIG = 4;
// Cobalt's local cache is temporarily full and cannot handle any more
// Observations at this time. This condition should be rare because Cobalt
// will automatically send Observations to the server and clear the cache
// when it starts to get too full. In the current version of Cobalt,
// Observations are cached in memory so this error could possibly occur if the
// server is down for a long time. In the future Cobalt will store
// Observations in non-volatile storage making this condition much less
// likely.
TEMPORARILY_FULL = 5;
// Catch-all for unexpected errors.
INTERNAL_ERROR = -1;
};
// One part of a multi-part observation. This is used by the method
// AddMultipartObservation(). To add a simple single-part Observation this
// type is not needed.
struct ObservationValue {
// The name of an ObservationPart, as registered in Cobalt's configuration.
string name;
// The value to assign to that part of the Observation.
Value value;
// The ID of the encoding to use for that part of the Observation.
uint32 encoding_id;
};
struct BucketDistributionEntry {
uint32 index;
uint64 count;
};
// A value that may be a string, int, double, index or distribution of ints.
union Value {
string string_value;
int64 int_value;
float64 double_value;
uint32 index_value;
// Definition of the buckets is given by the IntegerBuckets in the MetricPart
// definition registered with Cobalt.
vector<BucketDistributionEntry> int_bucket_distribution;
};
[Discoverable]
// CobaltEncoderFactory creates a CobaltEncoder for a particular project.
interface CobaltEncoderFactory {
// Creates a CobaltEncoder for the specified project.
// |project_id| Should be a project ID registered with the Cobalt system.
1: GetEncoder(int32 project_id, request<CobaltEncoder> encoder);
};
// CobaltEncoder accumulates Observations in a local cache and periodically
// sends them to the server. An instance of CobaltEncoder is associated with a
// particular Cobalt project ID.
//
// Next method ordinal: 12
interface CobaltEncoder {
// Adds a string observation. It will eventually be sent to the Cobalt server.
// |metric_id| Must be a metric ID registered with the Cobalt system and
// associated with this encoder's project ID. The specified
// metric must have a single part of type STRING.
//
// |encoding_id| Must be an encoding ID registered with the Cobalt system
// and associated with this encoder's project ID.
//
// |observation| The string value to be encoded. Must be consistent with
// the definition of the metric and encoding. Some encodings
// restrict the set of values to a pre-defined list.
1: AddStringObservation(uint32 metric_id, uint32 encoding_id,
string observation)
-> (Status @status);
// Adds an integer observation. It will eventually be sent to the Cobalt
// server.
// |metric_id| Must be a metric ID registered with the Cobalt system and
// associated with this encoder's project ID. The specified
// metric must have a single part of type INT.
//
// |encoding_id| Must be an encoding ID registered with the Cobalt system
// and associated with this encoder's project ID.
//
// |observation| The integer value to be encoded. Must be consistent with
// the definition of the metric and encoding. Some encodings
// restrict the set of values to a pre-defined list.
4: AddIntObservation(uint32 metric_id, uint32 encoding_id, int64 observation)
-> (Status @status);
// Adds a double observation. It will eventually be sent to the Cobalt server.
// |metric_id| Must be a metric ID registered with the Cobalt system and
// associated with this encoder's project ID. The specified
// metric must have a single part of type DOUBLE.
//
// |encoding_id| Must be an encoding ID registered with the Cobalt system
// and associated with this encoder's project ID.
//
// |observation| The double value to be encoded. Must be consistent with
// the definition of the metric and encoding.
5: AddDoubleObservation(uint32 metric_id, uint32 encoding_id,
float64 observation)
-> (Status @status);
// Adds an observation specified by its index. This only makes sense if
// the specified metric and encoding are consistent with values of type INDEX.
// The Observation will eventually be sent to the Cobalt server.
// |metric_id| Must be a metric ID registered with the Cobalt system and
// associated with this encoder's project ID. The specified
// metric must have a single part of type INDEX.
//
// |encoding_id| Must be an encoding ID registered with the Cobalt system
// and associated with this encoder's project ID. The
// ecoding must support values of type INDEX. Some encoding
// configurations may specify a maximum index and in that case
// |index| must not exceed that maximum.
//
// |index| The zero-based index of the value to be encoded. This is an index
// into some enumerated set of values that must be maintained outside
// of the scope of Cobalt's client-side configuration system by the
// client of this API. Cobalt treats the given |index| as opaque,
// except that human-readable string labels may optionally be
// associated with the indices in Cobalt's server-side configuration
// in a |ReportConfig|. This allows Cobalt to use these strings in
// place of the indices when generating reports. However there is
// no requirement to register a label with an index in order to
// use the index here. Also the label may be added or changed later.
2: AddIndexObservation(uint32 metric_id, uint32 encoding_id, uint32 index)
-> (Status @status);
// Adds an observation. It will eventually be sent to the Cobalt server.
// This version of Add*Observation() allows the user to specify the
// observation using the variadic type |Value|.
//
// |metric_id| Must be a metric ID registered with the Cobalt system and
// associated with this encoder's project ID. The specified
// metric must have a single part and the the type of this part
// must be consistent with the runtime type of |observation|.
//
// |encoding_id| Must be an encoding ID registered with the Cobalt system
// and associated with this encoder's project ID.
//
// |observation| The Observation to be encoded. The runtime type must be
// consistent with the definition of the metric and encoding.
8: AddObservation(uint32 metric_id, uint32 encoding_id,
Value observation)
-> (Status @status);
// Adds a distribution of int observations. It will eventually be sent to the
// Cobalt server.
//
// |metric_id| Must be a metric ID registered with the Cobalt system and
// associated with this encoder's project ID. The specified
// metric must have a single part of type INT.
//
// |encoding_id| Must be an encoding ID registered with the Cobalt system
// and associated with this encoder's project ID.
//
// |distribution| The Distribution to be encoded. A bucket distribution is a
// mapping from bucket indices to element counts in those
// buckets. The definition of the buckets is given by the
// IntegerBuckets in the MetricPart definition registered with
// Cobalt.
7: AddIntBucketDistribution(uint32 metric_id, uint32 encoding_id,
vector<BucketDistributionEntry> distribution)
-> (Status @status);
// Adds a multi-part observation. It will eventually be sent to the Cobalt
// server.
// |metric_id| Must be a metric ID registered with the Cobalt system and
// associated with this encoder's project ID.
//
// |observation| The multi-value Observation to be encoded. Must be
// consistent with the definition of the metric and encoding.
6: AddMultipartObservation(uint32 metric_id,
vector<ObservationValue> observation)
-> (Status @status);
// This method is part of Cobalt's helper service for measuring the time
// delta between two events that occur in different processes. This starts
// the timer. A corresponding invocation of EndTimer() with the same
// |timer_id| ends the timer. It is OK if Cobalt receives the EndTimer()
// call before the StartTimer() call.
//
// |metric_id| Must be a metric ID registered with the Cobalt system and
// associated with this encoder's project ID. The specified
// metric must have at least one part of type INTEGER that will
// be used to store the time delta. The EndTimer() call
// determines which metric part to use.
//
// |encoding_id| Must be an encoding ID registered with the Cobalt system
// and associated with this encoder's project ID. It will be
// used to encode the time delta.
//
// |timer_id| The ID of the timer being started. This is an arbitrary
// non-empty string provided by the caller and it is the caller's
// responsibility to ensure that Cobalt receives a pair of
// StartTimer(), EndTimer() calls with this id before the timeout
// and without any intervening additional calls to StartTimer()
// or EndTimer() using the same id. Once such a pair is received
// Cobalt will delete the timer with this ID and after that the
// ID may be re-used.
//
// |timestamp| The timestamp to set as the start of the timer. The units used
// are application-dependent and must be documented in the
// Metric definition in the Cobalt registration.
//
// |timeout_s| The number of seconds Cobalt should wait to receive the
// corresponding EndTimer() call with the same |timer_id|. If
// Cobalt has already received the corresponding EndTimer() call
// before receiving this StartTimer() call then this value is
// ignored as the timeout has already been set by the EndTimer()
// call. If Cobalt does not receive the corresponding EndTimer()
// call before the timeout then the timer will be deleted and
// this invocation of StartTimer() will be forgotten. Must be a
// positive value less than 300.
// |status| Returns OK on success. There are two success cases:
// (i) Cobalt does not currently have any timers with the given
// timer_id. In that case this call creates a new timer with
// the given ID and start timestamp.
// (ii) Cobalt currently has a timer with the given timer_id for
// which it has received exactly one EndTimer() call and no
// StartTimer() calls. In this case Cobalt will delete the
// timer and create a new Observation using the difference
// between the end timestamp and the start timestamp as the
// value of the Observation's unique part. It is ok if this
// time delta is negative.
// Returns INVALID_ARGUMENTS if |timer_id| is empty or the timeout
// is not positive and less than 5 minutes.
// Returns FAILED_PRECONDITION if Cobalt currently has a timer
// with the given timer_ID and it already has a start
// timestamp. In this case Cobalt will delete the timer with
// the given |timer_id| and this invocation of StartTimer()
// will be forgotten.
// Returns a different error if Cobalt tries to create an
// Observation with the given arguments and fails. See
// Cobalt::Status for more information.
9: StartTimer(uint32 metric_id, uint32 encoding_id, string timer_id,
uint64 timestamp, uint32 timeout_s) -> (Status @status);
// This method is part of Cobalt's helper service for measuring the time
// delta between two events that occur in different processes. This ends the
// timer. A corresponding invocation of StartTimer() with the same
// |timer_id| starts the timer. It is OK if Cobalt receives the EndTimer()
// call before the StartTimerCall().
//
// |timer_id| The ID of the timer being ended. This is an arbitrary
// non-empty string provided by the caller and it is the caller's
// responsibility to ensure that Cobalt receives a pair of
// StartTimer(), EndTimer() calls with this id before the timeout
// and without any intervening additional calls to StartTimer()
// or EndTimer() using the same id. Once such a pair is received
// Cobalt will delete the timer with this ID and after that the
// ID may be re-used.
//
// |timestamp| The timestamp to set as the end of the timer. The units used
// are application-dependent and must be documented in the
// Metric definition in the Cobalt registration.
//
// |timeout_s| The number of seconds Cobalt should wait to receive the
// corresponding StartTimer() call with the same |timer_id|. If
// Cobalt has already received the corresponding StartTimer()
// call before receiving this EndTimer() call then this value is
// ignored as the timeout has already been set by the
// StartTimer() call. Must be a positive value less than 300.
// If Cobalt does not receive the corresponding StartTimer()
// call before the timeout then the timer will be deleted and
// this invocation of EndTimer() will be forgotten.
// |status| Returns OK on success. There are two success cases:
// (i) Cobalt does not currently have any timers with the given
// timer_id. In that case this call creates a new timer with
// the given ID and end timestamp.
// (ii) Cobalt currently has a timer with the given timer_id for
// which it has received exactly one StartTimer() call and no
// EndTimer() calls. In this case Cobalt will delete the
// timer and create a new Observation using the difference
// between the end timestamp and the start timestamp as the
// value of the Observation's unique part. It is ok if this
// time delta is negative.
// Returns INVALID_ARGUMENTS if |timer_id| is empty or the timeout
// is not positive and less than 5 minutes.
// Returns FAILED_PRECONDITION if Cobalt currently has a timer
// with the given timer_ID and it already has an end timestamp.
// In this case Cobalt will delete the timer with the given
// |timer_id| and this invocation of EndTimer() will be
// forgotten.
// Returns a different error if Cobalt tries to create an
// Observation with the given arguments and fails. See
// Cobalt::Status for more information.
10: EndTimer(string timer_id, uint64 timestamp, uint32 timeout_s)
-> (Status @status);
// This version of EndTimer() supports multi-part observations in which there
// are other parts in addition to the time delta. See the documentation on
// the other version of EndTimer().
//
// |timer_id| The ID of the timer being ended. This is an arbitrary
// non-empty string provided by the caller and it is the caller's
// responsibility to ensure that Cobalt receives a pair of
// StartTimer(), EndTimer() calls with this id before the timeout
// and without any intervening additional calls to StartTimer()
// or EndTimer() using the same id. Once such a pair is received
// Cobalt will delete the timer with this ID and after that the
// ID may be re-used.
//
// |timestamp| The timestamp to set as the end of the timer. The units used
// are application-dependent and must be documented in the
// Metric definition in the Cobalt registration.
//
// |part_name| Must be the name of a part of type INTEGER within the metric
// whose ID is given. The time delta will become the value for
// this part of the observation.
//
// |observations| The multi-value Observation to be encoded in addition to
// the time delta.
//
// |timeout_s| The number of seconds Cobalt should wait to receive the
// corresponding StartTimer() call with the same |timer_id|. If
// Cobalt has already received the corresponding StartTimer()
// call before receiving this EndTimer() call then this value is
// ignored as the timeout has already been set by the
// StartTimer() call. Must be a positive value less than 300.
// If Cobalt does not receive the corresponding StartTimer()
// call before the timeout then the timer will be deleted and
// this invocation of EndTimer() will be forgotten.
// |status| Returns OK on success. There are two success cases:
// (i) Cobalt does not currently have any timers with the given
// timer_id. In that case this call creates a new timer with
// the given ID and end timestamp.
// (ii) Cobalt currently has a timer with the given timer_id for
// which it has received exactly one StartTimer() call and no
// EndTimer() calls. In this case Cobalt will delete the
// timer and create a new Observation using the difference
// between the end timestamp and the start timestamp as the
// value of the Observation's unique part. It is ok if this
// time delta is negative.
// Returns INVALID_ARGUMENTS if |timer_id| is empty or the timeout
// is not positive and less than 5 minutes or if part_name is
// an empty string.
// Returns FAILED_PRECONDITION if Cobalt currently has a timer
// with the given timer_ID and it already has an end timestamp.
// In this case Cobalt will delete the timer with the given
// |timer_id| and this invocation of EndTimer() will be
// forgotten.
// Returns a different error if Cobalt tries to create an
// Observation with the given arguments and fails. See
// Cobalt::Status for more information.
11: EndTimerMultiPart(string timer_id, uint64 timestamp, string part_name,
vector<ObservationValue> observation, uint32 timeout_s)
-> (Status @status);
// Obsolete. This does nothing and always returns OK.
3: SendObservations() -> (Status @status);
};