blob: 0f069ce8c00910a42697176955822e86647053f6 [file] [log] [blame]
// Copyright 2016 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.
@available(added=26)
library fuchsia.tracing.controller;
using fuchsia.tracing;
using zx;
/// The maximum number of providers supported.
const MAX_NUM_PROVIDERS uint32 = 100;
/// The maximum length of an alert name.
const MAX_ALERT_NAME_LENGTH uint32 = 14;
/// aliases
alias AlertName = string:MAX_ALERT_NAME_LENGTH;
/// This covers errors from using the `Tracing` protocol (specifically
/// trace recording errors).
@available(added=NEXT)
type RecordingError = flexible enum {
/// Error encountered when opening the proxy to the target.
TARGET_PROXY_OPEN = 0;
/// This is a general error when starting a trace.
RECORDING_START = 1;
/// An error encountered if a trace recording has already been started
/// for a given Fuchsia target.
RECORDING_ALREADY_STARTED = 2;
/// An error encountered when attempting to stop a trace. This causes an
/// immediate termination of the client channel, so the user should not
/// attempt to run `StopRecording` again.
RECORDING_STOP = 3;
/// Error for when a trace file is already being written to by the tracing
/// service.
DUPLICATE_TRACE_FILE = 4;
/// When attempting to stop a trace, there were no active traces found for
/// the given lookup name.
NO_SUCH_TRACE_FILE = 5;
/// No targets were found matching the query.
NO_SUCH_TARGET = 6;
/// The query matched a target that is not connected to the Daemon's FIDL
/// channels.
DISCONNECTED_TARGET = 7;
};
/// An action to be preformed on this trace. Used as part of a Trigger.
@available(added=NEXT)
type Action = flexible enum {
/// Terminates the active trace.
TERMINATE = 1;
};
/// A trigger is an action that is done when a certain alert has been raised in the
/// fuchsia tracing system.
@available(added=NEXT)
type Trigger = table {
/// The name of the alert being watched.
/// See fuchsia.tracing.controller.Controller.WatchAlert for more info.
1: alert string:MAX_ALERT_NAME_LENGTH;
/// The action to run when this alert has been witnessed.
2: action Action;
};
/// Covers how a trace will be run when invoking `StartRecording`.
@available(added=NEXT)
type TraceOptions = table {
/// Determines how long a trace recording will run before terminating in
/// nanoseconds. This is an "at-least" duration, with the actual
/// runtime terminating likely a few dozen milliseconds longer.
///
/// If this is not set, a trace will run indefinitely and must be stopped
/// using `StopRecording`. Or by cleanly shutting down the daemon via
/// `ffx daemon stop` or by using the Deamon proxy itself.
1: duration_ns zx.Duration;
/// The triggers to run against this trace.
2: triggers vector<Trigger>:MAX;
/// The requested categories for the trace. These could include
/// groups, or nothing. These categories are expanded and the expanded
/// list is in the TraceConfig. This list is used to support the nice UX of
/// explicitly checking for events with these categories and warn the
/// user if the no events were captured for any of these categories.
3: requested_categories fuchsia.tracing.EnabledCategoryList;
};
/// Status of the trace session managed by SessionManager
@available(added=NEXT)
type TraceStatus = table {
// 1-2: reserved
/// The total duration of the command in fractional seconds. This will not
/// be set if the command is supposed to run indefinitely.
3: duration zx.Duration;
/// The amount of time remaining before the trace terminates. This will not
/// be set if the command is supposed to run indefinitely.
4: remaining_runtime zx.Duration;
/// The original config sent to the `StartRecording` command.
5: config TraceConfig;
/// A list of triggers active for this trace. See [Trigger] for more info.
6: triggers vector<Trigger>:MAX;
/// unique id of this trace session.
7: task_id uint64;
};
/// The state of the tracing session.
/// A "session" is everything between `Initialize` and `Terminate`.
type SessionState = flexible enum {
/// The tracing system is ready for a new session.
/// There can be only one session at a time.
READY = 1;
/// A new tracing session has been initialized.
INITIALIZED = 2;
/// Tracing is in the midst of starting.
STARTING = 3;
/// Tracing has started.
STARTED = 4;
/// Tracing is in the midst of being stopped.
STOPPING = 5;
/// Tracing has fully stopped.
STOPPED = 6;
/// Tracing is in the midst of being terminated.
/// Once the system has completely terminated the session it goes back
/// to the READY state.
TERMINATING = 7;
};
/// The provisioner interface used to initialize a trace Session, that can
/// then be started and stopped.
///
/// The provisioner is required to start a trace Session and bind the control
/// to the client. It can also perform tasks like getting the list of registered
/// providers and known categories, which can be performed without a existing
/// trace Session.
@discoverable
open protocol Provisioner {
/// Requests to initialize tracing with the specified `config`.
///
/// A bad request will terminate the connection.
///
/// Dropping the socket connection will abort and terminate the
/// existing trace Session.
///
/// The trace controller emits trace data to `output` as a sequence of
/// binary formatted trace records. Traces obtained from different providers
/// are delimited by metadata records within the stream.
flexible InitializeTracing(resource struct {
controller server_end:Session;
config TraceConfig;
output zx.Handle:<SOCKET, zx.Rights.WRITE | zx.Rights.WAIT>;
});
/// Return the set of registered providers.
flexible GetProviders() -> (struct {
providers vector<ProviderInfo>:MAX_NUM_PROVIDERS;
});
// Gets the known categories.
flexible GetKnownCategories() -> (struct {
categories vector<fuchsia.tracing.KnownCategory>:fuchsia.tracing.MAX_NUM_KNOWN_CATEGORIES;
});
};
@available(added=NEXT)
@discoverable
open protocol SessionManager {
/// Return the set of registered providers.
flexible GetProviders() -> (struct {
providers vector<ProviderInfo>:MAX_NUM_PROVIDERS;
});
/// Gets the known categories.
flexible GetKnownCategories() -> (struct {
categories vector<fuchsia.tracing.KnownCategory>:fuchsia.tracing.MAX_NUM_KNOWN_CATEGORIES;
});
/// Starts a Trace session.
flexible StartTraceSession(resource struct {
config TraceConfig;
options TraceOptions;
}) -> (struct {
task_id uint64;
}) error RecordingError;
/// Configure a Trace session to start when the component starts.
flexible StartTraceSessionOnBoot(resource struct {
config TraceConfig;
options TraceOptions;
}) -> () error RecordingError;
/// Ends the trace session.
/// If task_id is non-zero, then only the trace task with the given id is checked.
/// Note: Currently there is only 1 trace task active at a time, so the task_id is of
/// little value at this time.
flexible EndTraceSession(resource struct {
task_id uint64;
output zx.Handle:<SOCKET, zx.Rights.WRITE | zx.Rights.WAIT | zx.Rights.TRANSFER>;
}) -> (struct {
options TraceOptions;
result StopResult;
}) error RecordingError;
/// Returns the status of the current trace session.
flexible Status() -> (TraceStatus) error RecordingError;
};
/// The session interface used by the trace tool to start/stop/terminate a trace Session.
///
/// The trace Session may lightly validate the structure of
/// trace records as it copies them from trace buffers into the output.
/// In particular, it may verify the size of each record header to ensure
/// that the framing of trace records in the data stream is maintained.
///
/// The trace Session does not validate the contents of the trace records
/// themselves. For example, it does not try to check argument lengths in
/// events. This ensures that the trace format can be extended without needing
/// to modify the trace Session.
///
/// The trace Session must be initialized from the provisioner. It can then be
/// used to start/stop tracing as many times as needed. Dropping the Session
/// will terminate tracing.
open protocol Session {
/// Requests to start tracing with the specified `options`.
///
/// If tracing has already started then the request is ignored,
/// except to send back an error code.
///
/// The trace Session acknowledges the request when all
/// registered providers have been started or after
/// `TraceConfig.start_timeout_milliseconds` milliseconds.
/// One useful reason for the has-started acknowledgement is that the
/// trace program can start a program to trace knowing that all the
/// providers are started.
flexible StartTracing(StartOptions) -> () error StartError;
/// Requests to stop tracing.
///
/// If tracing has already stopped then this does nothing.
/// Returning a result lets callers know when it's ok to, for example,
/// start tracing again.
flexible StopTracing(StopOptions) -> (StopResult) error StopError;
/// Returns the next alert when it arrives.
///
/// Alerts received by the Session are queued until a WatchAlert
/// request is received. Alerts are sent to the caller in the order
/// they were received.
///
/// WatchAlert requests are also queued until an alert is received
/// and the requests are serviced in the order they were received.
flexible WatchAlert() -> (struct {
alert_name AlertName;
});
/// Event sent when the Session state changes.
flexible -> OnSessionStateChange(struct {
state SessionState;
});
};
// Individual providers can be tuned with this.
type ProviderSpec = table {
1: name fuchsia.tracing.ProviderName;
2: buffer_size_megabytes_hint uint32;
3: categories fuchsia.tracing.EnabledCategoryList;
};
/// Provides options for the trace.
type TraceConfig = table {
/// The trace categories to record, or an empty array for all.
1: categories fuchsia.tracing.EnabledCategoryList;
/// Suggested size of trace buffer which each provider should receive.
// If table defaults were supported, this would default to 4.
2: buffer_size_megabytes_hint uint32;
/// Acknowledge start request after at most `start_timeout_milliseconds`.
// If table defaults were supported, this would default to 5000.
3: start_timeout_milliseconds uint64;
// If table defaults were supported, this would default to BufferingMode.ONESHOT.
4: buffering_mode fuchsia.tracing.BufferingMode;
/// Overrides for particular providers.
5: provider_specs vector<ProviderSpec>:MAX_NUM_PROVIDERS;
/// Maximum trace format version supported byt the client.
/// If not set, this defaults to the latest available trace format version.
6: version FxtVersion;
/// When true, the session will buffer the trace within the
/// fuchsia.tracing.controller server and only send the trace over the
/// output socket to the client once the trace completes.
///
/// It is recommended that defering the trace transfer be set to true when
/// using streaming mode and the fuchsia.tracing.controller client is across
/// the host-device boundary, such as with ffx. In this, or other cases
/// where sending the trace data could cause exess cpu overhead, the disk
/// writing cost is preferrable to the cost of sending to the client.
///
/// NOTE: defer_transfer only has effect during BufferingMode.STREAMING as
/// other modes don't otherwise send trace data to the client during a
/// trace.
@available(added=28)
7: defer_transfer bool;
};
/// Statistics data per provider collected over the course of the tracing session
type ProviderStats = table {
1: name fuchsia.tracing.ProviderName;
2: pid zx.Koid;
3: buffering_mode fuchsia.tracing.BufferingMode;
4: buffer_wrapped_count uint32;
5: records_dropped uint64;
6: percentage_durable_buffer_used float32;
7: non_durable_bytes_written uint64;
};
/// Result of a terminate request.
type StopResult = table {
1: provider_stats vector<ProviderStats>:MAX_NUM_PROVIDERS;
};
/// Error codes from Start operations.
type StartError = flexible enum {
/// Tracing hasn't been initialized, not ready to start.
NOT_INITIALIZED = 1;
/// Tracing has already been started.
ALREADY_STARTED = 2;
/// Tracing is currently being stopped.
STOPPING = 3;
/// Tracing is currently being terminated.
TERMINATING = 4;
};
/// Error codes from Stop operations.
type StopError = flexible enum {
/// Trace controller is unavailable. Nothing to stop.
NOT_INITIALIZED = 1;
/// Tracing has not started or is currently stoppped.
NOT_STARTED = 2;
/// Tracing aborted due to error.
ABORTED = 3;
};
/// Additional options to control trace data collection.
type StartOptions = table {
/// Whether and how to clear the buffer when starting data collection.
/// This allows, for example, multiple Start/Stop trace runs to be
/// collected in the same buffer.
///
/// If the preceding `Stop()` request had `save_after_stopped=true`
/// then this value is overridden to CLEAR_ENTIRE_BUFFER to avoid
/// duplicate data being saved.
1: buffer_disposition fuchsia.tracing.BufferDisposition;
/// The trace categories to add to the initial set provided in
/// `TraceConfig`. If the combined number of categories goes over the
/// limit then the extra categories past the limit are discarded.
2: additional_categories fuchsia.tracing.EnabledCategoryList;
};
/// Additional options to control stopping of a trace.
type StopOptions = table {
/// If true then write all collected data after tracing has stopped.
/// This is useful in situations where one wants to clear the buffer
/// before starting the next trace, without having to first terminate the
/// trace and start a new one.
1: write_results bool;
};
/// Result of `GetProviders`.
type ProviderInfo = table {
/// The provider's ID, assigned by trace-manager.
1: id fuchsia.tracing.ProviderId;
/// The provider's pid.
2: pid zx.Koid;
/// The name of the provider.
3: name fuchsia.tracing.ProviderName;
};
/// Version of trace record format.
///
/// Default to the latest available version, which is currently 0.1.
///
/// More information about the format of trace records can be found here:
/// https://fuchsia.dev/fuchsia-src/reference/tracing/trace-format
type FxtVersion = table {
/// Defaults to 0.
1: major uint32;
/// Defaults to 1
2: minor uint32;
};