| // 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. |
| |
| #include "garnet/bin/cobalt/app/logger_factory_impl.h" |
| |
| #include "garnet/bin/cobalt/app/legacy_logger_impl.h" |
| #include "garnet/bin/cobalt/app/utils.h" |
| #include "lib/fsl/vmo/file.h" |
| #include "lib/fsl/vmo/strings.h" |
| |
| namespace cobalt { |
| |
| constexpr char kInternalMetricsProtoPath[] = |
| "/pkgfs/packages/cobalt/0/data/cobalt_internal_metrics_registry.pb"; |
| |
| using cobalt::TimerManager; |
| using config::ClientConfig; |
| using config::ProjectConfigs; |
| using fuchsia::cobalt::ProjectProfile; |
| using fuchsia::cobalt::Status; |
| |
| const int32_t kFuchsiaCustomerId = 1; |
| constexpr char kFuchsiaCustomerName[] = "fuchsia"; |
| |
| namespace { |
| std::pair<std::unique_ptr<ClientConfig>, uint32_t> GetClientConfig( |
| ProjectProfile profile) { |
| fsl::SizedVmo config_vmo; |
| bool success = |
| fsl::SizedVmo::FromTransport(std::move(profile.config), &config_vmo); |
| if (!success) { |
| FXL_LOG(ERROR) << "Transport buffer is invalid"; |
| return std::make_pair(nullptr, 0); |
| } |
| |
| std::string config_bytes; |
| success = fsl::StringFromVmo(config_vmo, &config_bytes); |
| if (!success) { |
| FXL_LOG(ERROR) << "Could not read Cobalt config from VMO"; |
| return std::make_pair(nullptr, 0); |
| } |
| |
| return ClientConfig::CreateFromCobaltProjectConfigBytes(config_bytes); |
| } |
| |
| ReleaseStage ToReleaseStageProto(fuchsia::cobalt::ReleaseStage stage) { |
| switch (stage) { |
| case fuchsia::cobalt::ReleaseStage::GA: |
| return ReleaseStage::GA; |
| case fuchsia::cobalt::ReleaseStage::DOGFOOD: |
| return ReleaseStage::DOGFOOD; |
| case fuchsia::cobalt::ReleaseStage::FISHFOOD: |
| return ReleaseStage::FISHFOOD; |
| case fuchsia::cobalt::ReleaseStage::DEBUG: |
| return ReleaseStage::DEBUG; |
| default: |
| FXL_LOG(ERROR) << "Unknown ReleaseStage provided. Defaulting to DEBUG."; |
| return ReleaseStage::DEBUG; |
| } |
| } |
| std::pair<std::unique_ptr<encoder::ProjectContext>, |
| std::unique_ptr<logger::ProjectContext>> |
| CreateProjectContexts(ProjectProfile profile) { |
| auto release_stage = profile.release_stage; |
| auto config_id_pair = GetClientConfig(std::move(profile)); |
| |
| std::shared_ptr<config::ClientConfig> project_config; |
| project_config.reset(config_id_pair.first.release()); |
| if (project_config == nullptr) { |
| FXL_LOG(ERROR) << "Cobalt config is invalid"; |
| return std::pair(nullptr, nullptr); |
| } |
| |
| if (project_config->IsLegacy()) { |
| std::unique_ptr<encoder::ProjectContext> project_context( |
| new encoder::ProjectContext(kFuchsiaCustomerId, config_id_pair.second, |
| project_config)); |
| return std::pair(std::move(project_context), nullptr); |
| } else { |
| auto customer_cfg = project_config->TakeCustomerConfig(); |
| auto project_cfg = customer_cfg->mutable_projects(0); |
| auto metrics = std::make_unique<MetricDefinitions>(); |
| metrics->mutable_metric()->Swap(project_cfg->mutable_metrics()); |
| return std::pair( |
| nullptr, std::make_unique<logger::ProjectContext>( |
| customer_cfg->customer_id(), project_cfg->project_id(), |
| customer_cfg->customer_name(), project_cfg->project_name(), |
| std::move(metrics), ToReleaseStageProto(release_stage))); |
| } |
| } |
| } // namespace |
| |
| LoggerFactoryImpl::LoggerFactoryImpl( |
| encoder::ClientSecret client_secret, |
| encoder::ObservationStore* observation_store, |
| util::EncryptedMessageMaker* encrypt_to_analyzer, |
| encoder::ShippingManager* shipping_manager, |
| const encoder::SystemData* system_data, TimerManager* timer_manager, |
| logger::Encoder* logger_encoder, |
| logger::ObservationWriter* observation_writer, |
| std::shared_ptr<config::ClientConfig> client_config, |
| std::shared_ptr<ProjectConfigs> project_configs) |
| : client_secret_(std::move(client_secret)), |
| observation_store_(observation_store), |
| encrypt_to_analyzer_(encrypt_to_analyzer), |
| shipping_manager_(shipping_manager), |
| system_data_(system_data), |
| timer_manager_(timer_manager), |
| logger_encoder_(logger_encoder), |
| observation_writer_(observation_writer), |
| client_config_(client_config), |
| project_configs_(project_configs) { |
| ProjectProfile profile; |
| fsl::SizedVmo config_vmo; |
| fsl::VmoFromFilename(kInternalMetricsProtoPath, &config_vmo); |
| profile.config = std::move(config_vmo).ToTransport(); |
| |
| auto [legacy_project_context, project_context] = |
| CreateProjectContexts(std::move(profile)); |
| internal_project_context_ = std::move(project_context); |
| internal_logger_.reset( |
| new logger::Logger(logger_encoder_, observation_writer_, |
| internal_project_context_.get(), nullptr)); |
| } |
| |
| void LoggerFactoryImpl::CreateLogger( |
| ProjectProfile profile, |
| fidl::InterfaceRequest<fuchsia::cobalt::Logger> request, |
| CreateLoggerCallback callback) { |
| auto [legacy_project_context, project_context] = |
| CreateProjectContexts(std::move(profile)); |
| if (legacy_project_context) { |
| logger_bindings_.AddBinding( |
| std::make_unique<LegacyLoggerImpl>( |
| std::move(legacy_project_context), client_secret_, |
| observation_store_, encrypt_to_analyzer_, shipping_manager_, |
| system_data_, timer_manager_), |
| std::move(request)); |
| callback(Status::OK); |
| } else if (project_context) { |
| logger_bindings_.AddBinding( |
| std::make_unique<LoggerImpl>(std::move(project_context), |
| logger_encoder_, observation_writer_, |
| timer_manager_, internal_logger_.get()), |
| std::move(request)); |
| callback(Status::OK); |
| } else { |
| callback(Status::INVALID_ARGUMENTS); |
| } |
| } |
| |
| void LoggerFactoryImpl::CreateLoggerSimple( |
| ProjectProfile profile, |
| fidl::InterfaceRequest<fuchsia::cobalt::LoggerSimple> request, |
| CreateLoggerSimpleCallback callback) { |
| auto [legacy_project_context, project_context] = |
| CreateProjectContexts(std::move(profile)); |
| |
| if (legacy_project_context) { |
| logger_simple_bindings_.AddBinding( |
| std::make_unique<LegacyLoggerImpl>( |
| std::move(legacy_project_context), client_secret_, |
| observation_store_, encrypt_to_analyzer_, shipping_manager_, |
| system_data_, timer_manager_), |
| std::move(request)); |
| callback(Status::OK); |
| } else if (project_context) { |
| logger_simple_bindings_.AddBinding( |
| std::make_unique<LoggerImpl>(std::move(project_context), |
| logger_encoder_, observation_writer_, |
| timer_manager_, internal_logger_.get()), |
| std::move(request)); |
| callback(Status::OK); |
| } else { |
| callback(Status::INVALID_ARGUMENTS); |
| } |
| } |
| |
| void LoggerFactoryImpl::CreateLoggerFromProjectName( |
| fidl::StringPtr project_name, fuchsia::cobalt::ReleaseStage release_stage, |
| fidl::InterfaceRequest<fuchsia::cobalt::Logger> request, |
| CreateLoggerFromProjectNameCallback callback) { |
| auto project_context_or = logger::ProjectContext::ConstructWithProjectConfigs( |
| kFuchsiaCustomerName, project_name.get(), project_configs_, |
| ToReleaseStageProto(release_stage)); |
| |
| if (!project_context_or.ok()) { |
| FXL_LOG(ERROR) << "Failed to construct ProjectContext from ProjectConfigs: " |
| << project_context_or.status().error_message(); |
| callback(ToCobaltStatus(project_context_or.status())); |
| return; |
| } |
| |
| logger_bindings_.AddBinding( |
| std::make_unique<LoggerImpl>(project_context_or.ConsumeValueOrDie(), |
| logger_encoder_, observation_writer_, |
| timer_manager_, internal_logger_.get()), |
| std::move(request)); |
| callback(Status::OK); |
| } |
| |
| void LoggerFactoryImpl::CreateLoggerSimpleFromProjectName( |
| fidl::StringPtr project_name, fuchsia::cobalt::ReleaseStage release_stage, |
| fidl::InterfaceRequest<fuchsia::cobalt::LoggerSimple> request, |
| CreateLoggerSimpleFromProjectNameCallback callback) { |
| auto project_context_or = logger::ProjectContext::ConstructWithProjectConfigs( |
| kFuchsiaCustomerName, project_name.get(), project_configs_, |
| ToReleaseStageProto(release_stage)); |
| |
| if (!project_context_or.ok()) { |
| FXL_LOG(ERROR) << "Failed to construct ProjectContext from ProjectConfigs: " |
| << project_context_or.status().error_message(); |
| callback(ToCobaltStatus(project_context_or.status())); |
| return; |
| } |
| |
| logger_simple_bindings_.AddBinding( |
| std::make_unique<LoggerImpl>(project_context_or.ConsumeValueOrDie(), |
| logger_encoder_, observation_writer_, |
| timer_manager_, internal_logger_.get()), |
| std::move(request)); |
| callback(Status::OK); |
| } |
| |
| void LoggerFactoryImpl::CreateLoggerFromProjectId( |
| uint32_t project_id, fuchsia::cobalt::ReleaseStage release_stage, |
| fidl::InterfaceRequest<fuchsia::cobalt::Logger> request, |
| CreateLoggerFromProjectIdCallback callback) { |
| auto project_context = std::make_unique<encoder::ProjectContext>( |
| kFuchsiaCustomerId, project_id, client_config_); |
| |
| logger_bindings_.AddBinding( |
| std::make_unique<LegacyLoggerImpl>( |
| std::move(project_context), client_secret_, observation_store_, |
| encrypt_to_analyzer_, shipping_manager_, system_data_, |
| timer_manager_), |
| std::move(request)); |
| |
| callback(Status::OK); |
| } |
| |
| void LoggerFactoryImpl::CreateLoggerSimpleFromProjectId( |
| uint32_t project_id, fuchsia::cobalt::ReleaseStage release_stage, |
| fidl::InterfaceRequest<fuchsia::cobalt::LoggerSimple> request, |
| CreateLoggerSimpleFromProjectIdCallback callback) { |
| auto project_context = std::make_unique<encoder::ProjectContext>( |
| kFuchsiaCustomerId, project_id, client_config_); |
| |
| logger_simple_bindings_.AddBinding( |
| std::make_unique<LegacyLoggerImpl>( |
| std::move(project_context), client_secret_, observation_store_, |
| encrypt_to_analyzer_, shipping_manager_, system_data_, |
| timer_manager_), |
| std::move(request)); |
| |
| callback(Status::OK); |
| } |
| |
| } // namespace cobalt |