// Copyright 2018 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=7)
library fuchsia.logger;

using zx;
using fuchsia.diagnostics;

/// Log levels used with log related filtering.
/// Filtering uses a heuristic based on a threshold of
/// minimum severity level - with any log equal to or
/// greater than the threshold being included in the
/// printable logs.
type LogLevelFilter = strict enum : int8 {
    @available(removed=8)
    DEPRECATED_INFO_LOAD_BEARING_IN_CHROMIUM = 0;
    TRACE = 0x10;
    DEBUG = 0x20;
    INFO = 0x30;
    WARN = 0x40;
    ERROR = 0x50;
    FATAL = 0x60;
    NONE = 0x7F;
};

/// The interval between discrete log severity levels
const LOG_SEVERITY_STEP_SIZE uint8 = 0x10;

/// Maximum available log severity.
const LOG_SEVERITY_MAX_STEP uint8 = 6;

/// The interval between discrete log verbosity levels
const LOG_VERBOSITY_STEP_SIZE uint8 = 0x1;

/// Default log level used to initialize loggers.
const LOG_LEVEL_DEFAULT LogLevelFilter = LogLevelFilter.INFO;

/// Max number of tags that can be passed to filter by listener.
const MAX_TAGS uint8 = 16;

/// Max tag length that can be passed to filter by listener.
const MAX_TAG_LEN_BYTES uint8 = 63;

type LogFilterOptions = struct {
    filter_by_pid bool;
    pid uint64;

    filter_by_tid bool;
    tid uint64;

    /// If more than zero, logs would be filtered based on verbosity and
    /// `min_severity` would be ignored.
    verbosity uint8;

    /// Severity used as threshold to determine logging level.
    min_severity LogLevelFilter;

    /// If non-empty, return all messages which contain at least one specified
    /// tag.  If empty, messages will not be filtered by tag.
    /// Passed tags should not be more than `MAX_TAG_LEN_BYTES` bytes in length
    /// and max tags can be `MAX_TAGS`.
    /// Listener would be discarded if the limit is not followed.
    tags vector<string:MAX_TAG_LEN_BYTES>:MAX_TAGS;
};

/// Max tags that will be attached to a LogMessage.
const MAX_TAGS_PER_LOG_MESSAGE uint8 = 5;

/// Max byte size for message payload.
const MAX_DATAGRAM_LEN_BYTES uint32 = 32768;

type LogMessage = struct {
    pid uint64;
    tid uint64;
    /// https://fuchsia.dev/fuchsia-src/reference/syscalls/clock_get_monotonic.md
    time zx.time;
    severity int32;

    /// See //zircon/system/ulib/syslog/include/lib/syslog/wire_format.h. As messages
    /// can be served out of order, this should only be logged if more than last
    /// count.
    dropped_logs uint32;
    tags vector<string:MAX_TAG_LEN_BYTES>:MAX_TAGS_PER_LOG_MESSAGE;
    msg string:MAX_DATAGRAM_LEN_BYTES;
};

/// Interface for LogListenerSafe to register to listen to logs.
@discoverable
protocol Log {
    /// Dumps all cached logs by calling LogMany() in batches followed by Log() for each new log
    /// message.
    /// A null `options` indicates no filtering is requested.
    ListenSafe(resource struct {
        log_listener client_end:LogListenerSafe;
        options box<LogFilterOptions>;
    });

    /// Dumps all cached logs by calling LogMany() followed by Done() on `log_listener`.
    /// A null `options` indicates no filtering is requested.
    DumpLogsSafe(resource struct {
        log_listener client_end:LogListenerSafe;
        options box<LogFilterOptions>;
    });

    /// Listens to new log entries by calling Log() on `log_listener`.
    /// A null `options` indicates no filtering is requested.
    ListenSafeWithSelectors(resource struct {
        log_listener client_end:LogListenerSafe;
        options box<LogFilterOptions>;
        selectors
                vector<fuchsia.diagnostics.LogInterestSelector>:fuchsia.diagnostics.MAX_LOG_SELECTORS;
    });
};

type InterestChangeError = strict enum : uint32 {
    /// Incorrectly called WaitForInterestChange twice
    /// without waiting for the first call to return.
    CALLED_TWICE = 1;
};

/// Drains a program's logs.
@discoverable
protocol LogSink {
    /// Send this socket to be drained.
    ///
    /// See //zircon/system/ulib/syslog/include/lib/syslog/wire_format.h for what is expected to be
    /// received over the socket.
    Connect(resource struct {
        socket zx.handle:SOCKET;
    });

    /// LogSink implementers will return to this hanging-get whenever the scope of
    /// their interest changes. Clients are expected to emit messages based on
    /// the registered Interest. In the event that an empty interest is
    /// conveyed, clients should emit messages based on their default
    /// e.g. compile time configuration. Each client may only poll this once at a time.
    /// Invoking WaitForInterestChange a second time before the first call returns will
    /// result in an error being returned.
    WaitForInterestChange() -> (struct {
        data fuchsia.diagnostics.Interest;
    }) error InterestChangeError;

    /// Send this socket to be drained, using the structured logs format.
    ///
    /// See //docs/reference/diagnostics/logs/encoding.md for what is expected to be received over
    /// the socket.
    ConnectStructured(resource struct {
        socket zx.handle:SOCKET;
    });
};

/// Max log bytes per call to a listener.
const MAX_LOG_MANY_SIZE_BYTES uint64 = 16384;

/// A listener who will notify the `Log` of the receipt of each message.
protocol LogListenerSafe {
    /// Called for single messages.
    ///
    /// The return value is used for flow control, and implementers should acknowledge receipt of
    /// each message in order to continue receiving future messages.
    Log(struct {
        log LogMessage;
    }) -> ();

    /// Called when serving cached logs.
    ///
    /// Max logs size per call is `MAX_LOG_MANY_SIZE_BYTES` bytes.
    ///
    /// The return value is used for flow control, and implementers should acknowledge receipt of
    /// each batch in order to continue receiving future messages.
    LogMany(struct {
        log vector<LogMessage>:MAX;
    }) -> ();

    /// Called when this listener was passed to `DumpLogsSafe()` and all cached logs have been sent.
    Done();
};
