// Copyright 2020 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.

//! The Archivist collects and stores diagnostic data from components.

#![warn(missing_docs)]

use {
    anyhow::{Context, Error},
    archivist_lib::{
        archivist, configs, diagnostics, events::sources::LogConnectorEventSource, logs,
    },
    argh::FromArgs,
    fdio::service_connect,
    fidl_fuchsia_sys2::EventSourceMarker,
    fidl_fuchsia_sys_internal::{ComponentEventProviderMarker, LogConnectorMarker},
    fuchsia_async as fasync,
    fuchsia_component::client::connect_to_service,
    fuchsia_component::server::MissingStartupHandle,
    fuchsia_syslog, fuchsia_zircon as zx,
    std::path::PathBuf,
    tracing::{debug, error, info, warn},
};

/// Monitor, collect, and store diagnostics from components.
// TODO(fxbug.dev/67983) make flags positive rather than negative
#[derive(Debug, Default, FromArgs)]
pub struct Args {
    /// disables proxying kernel logger
    #[argh(switch)]
    disable_klog: bool,

    /// disables log connector so that indivisual instances of
    /// observer don't compete for log connector listener.
    #[argh(switch)]
    disable_log_connector: bool,

    /// whether to connecto to event source or not. This can be set to true when the archivist won't
    /// consume events from the Component Framework v2 to remove log spam.
    #[argh(switch)]
    disable_event_source: bool,

    /// whether to connecto to the component event provider or not. This can be set to true when the
    /// archivist won't consume events from the Component Framework v1 to remove log spam.
    #[argh(switch)]
    disable_component_event_provider: bool,

    /// initializes syslog library with a log socket to itself
    #[argh(switch)]
    consume_own_logs: bool,

    /// serve fuchsia.diagnostics.test.Controller
    #[argh(switch)]
    install_controller: bool,

    /// retrieve a fuchsia.process.Lifecycle handle from the runtime and listen to shutdown events
    #[argh(switch)]
    listen_to_lifecycle: bool,

    /// path to a JSON configuration file
    #[argh(option)]
    config_path: PathBuf,

    /// path to additional configuration for services to connect to
    #[argh(option)]
    service_config_path: Option<PathBuf>,
}

fn main() -> Result<(), Error> {
    let opt: Args = argh::from_env();

    let mut log_server = None;
    if opt.consume_own_logs {
        let (log_client, server) = zx::Socket::create(zx::SocketOpts::DATAGRAM)?;
        log_server = Some(server);
        fuchsia_syslog::init_with_socket_and_name(log_client, "archivist")?;
        info!("Logging started.");
        logs::redact::emit_canary();
    } else {
        fuchsia_syslog::init_with_tags(&["embedded"])?;
    }

    let mut executor = fasync::Executor::new()?;

    diagnostics::init();

    let archivist_configuration: configs::Config = match configs::parse_config(&opt.config_path) {
        Ok(config) => config,
        Err(parsing_error) => panic!("Parsing configuration failed: {}", parsing_error),
    };
    debug!("Configuration parsed.");

    let num_threads = archivist_configuration.num_threads;

    let mut archivist = archivist::ArchivistBuilder::new(archivist_configuration)?;
    debug!("Archivist initialized from configuration.");

    executor
        .run_singlethreaded(archivist.install_log_services(archivist::LogOpts {
            ingest_v2_logs: !opt.disable_event_source,
        }));
    executor
        .run_singlethreaded(async {
            if !opt.disable_component_event_provider {
                let legacy_event_provider = connect_to_service::<ComponentEventProviderMarker>()
                    .context("failed to connect to event provider")?;
                archivist.add_event_source("v1", Box::new(legacy_event_provider)).await;
            }

            if !opt.disable_event_source {
                let event_source = connect_to_service::<EventSourceMarker>()
                    .context("failed to connect to event source")?;
                archivist.add_event_source("v2", Box::new(event_source)).await;
            }

            Ok::<(), Error>(())
        })
        .context("failed to add event lifecycle event sources")?;

    if let Some(socket) = log_server {
        archivist.consume_own_logs(socket);
    }

    assert!(
        !(opt.install_controller && opt.listen_to_lifecycle),
        "only one shutdown mechanism can be specified."
    );

    if opt.install_controller {
        archivist.install_controller_service();
    }

    if opt.listen_to_lifecycle {
        archivist.install_lifecycle_listener();
    }

    if !opt.disable_log_connector {
        let connector = connect_to_service::<LogConnectorMarker>()?;
        executor.run_singlethreaded(
            archivist.add_event_source(
                "log_connector",
                Box::new(LogConnectorEventSource::new(connector)),
            ),
        );
    }

    if !opt.disable_klog {
        let debuglog = executor
            .run_singlethreaded(logs::KernelDebugLog::new())
            .context("Failed to read kernel logs")?;
        fasync::Task::spawn(archivist.data_repo().clone().drain_debuglog(debuglog)).detach();
    }

    let mut services = vec![];

    if let Some(service_config_path) = &opt.service_config_path {
        match configs::parse_service_config(service_config_path) {
            Err(e) => {
                error!("Couldn't parse service config: {}", e);
            }
            Ok(config) => {
                for name in config.service_list.iter() {
                    info!("Connecting to service {}", name);
                    let (local, remote) = zx::Channel::create().expect("cannot create channels");
                    match service_connect(&format!("/svc/{}", name), remote) {
                        Ok(_) => {
                            services.push(local);
                        }
                        Err(e) => {
                            error!("Couldn't connect to service {}: {:?}", name, e);
                        }
                    }
                }
            }
        }
    }

    let startup_handle =
        fuchsia_runtime::take_startup_handle(fuchsia_runtime::HandleType::DirectoryRequest.into())
            .ok_or(MissingStartupHandle)?;

    debug!("Running executor with {} threads.", num_threads);
    executor.run(archivist.run(zx::Channel::from(startup_handle)), num_threads)?;

    debug!("Exiting.");
    Ok(())
}
