| // 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. |
| |
| #include "src/logger/internal_metrics.h" |
| |
| #include <cstdint> |
| #include <memory> |
| #include <sstream> |
| #include <utility> |
| |
| #include "src/logger/internal_metrics_config.cb.h" |
| #include "src/logging.h" |
| #include "src/public/lib/registry_identifiers.h" |
| |
| namespace cobalt::logger { |
| namespace { |
| const std::map<std::string, uint32_t> project_map = { |
| {"2147483647/205836624", 1}, |
| {"1/929352809", 2}, |
| {"1/657579885", 3}, |
| {"1/7", 4}, |
| {"1/2322225253", 5}, |
| {"1/4", 6}, |
| {"1/5", 7}, |
| {"1/3708719327", 8}, |
| {"1/4228153068", 9}, |
| {"1/2", 10}, |
| {"1/2820332838", 11}, |
| {"1/1334068210", 12}, |
| {"1/3676913920", 13}, |
| {"1/285903809", 14}, |
| {"1/3142410971", 15}, |
| {"1/3509424520", 16}, |
| {"1/2165403525", 17}, |
| {"1/1", 18}, |
| {"1/3", 19}, |
| {"1/2550112954", 20}, |
| {"1/4247972873", 21}, |
| {"1/6", 22}, |
| {"1/8", 23}, |
| {"1/9", 24}, |
| {"1/10", 25}, |
| {"1/11", 26}, |
| {"1/12", 27}, |
| {"1/13", 28}, |
| {"1/14", 29}, |
| {"1/15", 30}, |
| {"1/16", 31}, |
| }; |
| |
| uint32_t GetProjectEventCode(const std::string& project_identifier) { |
| auto event_code = project_map.find(project_identifier); |
| if (event_code != project_map.end()) { |
| return event_code->second; |
| } |
| return 0; |
| } |
| } // namespace |
| |
| std::unique_ptr<InternalMetrics> InternalMetrics::NewWithLogger(LoggerInterface* logger, |
| DiagnosticsInterface* diagnostics) { |
| if (logger) { |
| return std::make_unique<InternalMetricsImpl>(logger, diagnostics); |
| } |
| return std::make_unique<NoOpInternalMetrics>(); |
| } |
| |
| InternalMetricsImpl::InternalMetricsImpl(LoggerInterface* logger, DiagnosticsInterface* diagnostics) |
| : logger_(logger), diagnostics_(diagnostics) { |
| CHECK(logger_); |
| } |
| |
| void InternalMetricsImpl::LoggerCalled( |
| PerProjectLoggerCallsMadeMigratedMetricDimensionLoggerMethod method, const Project& project) { |
| fields_.lock()->queued_lambdas.emplace_back([this, method, project] { |
| auto status = logger_->LogOccurrence(kLoggerCallsMadeMigratedMetricId, 1, {method}); |
| |
| if (!status.ok()) { |
| VLOG(1) << "InternalMetricsImpl::LoggerCalled: LogOccurrence() returned status=" << status; |
| } |
| |
| std::ostringstream component; |
| component << project.customer_id() << '/' << project.project_id(); |
| status = logger_->LogOccurrence(kPerProjectLoggerCallsMadeMigratedMetricId, 1, |
| {GetProjectEventCode(component.str()), method}); |
| |
| if (!status.ok()) { |
| VLOG(1) << "InternalMetricsImpl::LoggerCalled: LogOccurrence() returned status=" << status; |
| } |
| |
| if (diagnostics_ != nullptr) { |
| std::ostringstream diagnostics_component; |
| diagnostics_component << project.customer_name() << '/' << project.project_name(); |
| diagnostics_->LoggerCalled(method, diagnostics_component.str()); |
| } |
| }); |
| } |
| |
| void InternalMetricsImpl::BytesUploaded(BytesUploadedMetricDimensionStatus upload_status, |
| size_t byte_count) { |
| fields_.lock()->queued_lambdas.emplace_back([this, upload_status, byte_count] { |
| Status status = logger_->LogOccurrence(kBytesUploadedMetricId, |
| static_cast<uint64_t>(byte_count), {upload_status}); |
| |
| if (!status.ok()) { |
| VLOG(1) << "InternalMetricsImpl::BytesUploaded: LogOccurrence() returned " |
| << "status=" << status; |
| } |
| }); |
| } |
| |
| void InternalMetricsImpl::BytesUploaded( |
| PerProjectBytesUploadedMigratedMetricDimensionStatus upload_status, size_t byte_count, |
| const lib::ProjectIdentifier& project_identifier) { |
| fields_.lock()->queued_lambdas.emplace_back( |
| [this, upload_status, byte_count, project_identifier] { |
| std::ostringstream component; |
| component << project_identifier.customer_id() << '/' << project_identifier.project_id(); |
| |
| auto status = logger_->LogInteger(kPerProjectBytesUploadedMigratedMetricId, |
| static_cast<int64_t>(byte_count), |
| {GetProjectEventCode(component.str()), upload_status}); |
| |
| if (!status.ok()) { |
| VLOG(1) << "InternalMetricsImpl::BytesUploaded: LogInteger() returned " |
| << "status=" << status; |
| } |
| }); |
| } |
| |
| void InternalMetricsImpl::BytesStored( |
| PerProjectBytesStoredMigratedMetricDimensionStatus upload_status, size_t byte_count, |
| const lib::ProjectIdentifier& project_identifier) { |
| fields_.lock()->queued_lambdas.emplace_back( |
| [this, upload_status, byte_count, project_identifier] { |
| std::ostringstream component; |
| component << project_identifier.customer_id() << '/' << project_identifier.project_id(); |
| |
| auto status = logger_->LogInteger(kPerProjectBytesStoredMigratedMetricId, |
| static_cast<int64_t>(byte_count), |
| {GetProjectEventCode(component.str()), upload_status}); |
| |
| if (!status.ok()) { |
| VLOG(1) << "InternalMetricsImpl::BytesStored: LogInteger() returned status=" << status; |
| } |
| }); |
| } |
| |
| void InternalMetricsImpl::IdleObservationUpload( |
| IdleObservationUploadMigratedMetricDimensionDeviceState state) { |
| fields_.lock()->queued_lambdas.emplace_back([this, state] { |
| auto status = logger_->LogOccurrence(kIdleObservationUploadMigratedMetricId, 1, {state}); |
| if (!status.ok()) { |
| VLOG(1) << "InternalMetricsImpl::IdleObservationUpload: LogOccurrence() returned status=" |
| << status; |
| } |
| }); |
| } |
| |
| void InternalMetricsImpl::InaccurateClockEventsCached(int64_t event_count) { |
| fields_.lock()->queued_lambdas.emplace_back([this, event_count] { |
| auto status = |
| logger_->LogOccurrence(kInaccurateClockEventsCachedMigratedMetricId, event_count, {}); |
| |
| if (!status.ok()) { |
| VLOG(1) |
| << "InternalMetricsImpl::InaccurateClockEventsCached: LogOccurrence() returned status=" |
| << status; |
| } |
| }); |
| } |
| |
| void InternalMetricsImpl::InaccurateClockEventsDropped(int64_t event_count) { |
| fields_.lock()->queued_lambdas.emplace_back([this, event_count] { |
| auto status = |
| logger_->LogOccurrence(kInaccurateClockEventsDroppedMigratedMetricId, event_count, {}); |
| |
| if (!status.ok()) { |
| VLOG(1) |
| << "InternalMetricsImpl::InaccurateClockEventsDropped: LogOccurrence() returned status=" |
| << status; |
| } |
| }); |
| } |
| |
| void InternalMetricsImpl::SetSoftwareDistributionInfoCalled( |
| SetSoftwareDistributionInfoCalledMigratedEventCodes event_codes) { |
| fields_.lock()->queued_lambdas.emplace_back([this, event_codes] { |
| auto status = logger_->LogOccurrence(kSetSoftwareDistributionInfoCalledMigratedMetricId, 1, |
| event_codes.ToVector()); |
| |
| if (!status.ok()) { |
| VLOG(1) << "InternalMetricsImpl::SetSoftwareDistributionInfoCalled: LogOccurrence() returned " |
| "status=" |
| << status; |
| } |
| }); |
| } |
| |
| const float kPerMilleMultiplier = 1000.0; |
| void InternalMetricsImpl::TrackDiskUsage(StorageClass storage_class, size_t bytes, |
| int64_t max_bytes) { |
| fields_.lock()->queued_lambdas.emplace_back([this, storage_class, bytes, max_bytes] { |
| // N.B. This method may only include Cobalt 1.1 metrics. Using Cobalt 1.0 metrics here have the |
| // potential to cause logging loops. |
| auto status = |
| logger_->LogInteger(kStoreUsageMetricId, static_cast<int64_t>(bytes), {storage_class}); |
| if (!status.ok()) { |
| VLOG(1) << "InternalMetricsImpl::TrackDiskUsage: LogInteger(disk_usage) returned status=" |
| << status; |
| } |
| |
| if (max_bytes >= 0) { |
| auto fullness_per_mille = static_cast<uint32_t>( |
| (static_cast<float>(bytes) / static_cast<float>(max_bytes)) * kPerMilleMultiplier); |
| status = logger_->LogInteger(kStoreFullnessMetricId, fullness_per_mille, {storage_class}); |
| if (!status.ok()) { |
| VLOG(1) << "InternalMetricsImpl::TrackDiskUsage: LogInteger(disk_fullness) returned status=" |
| << status; |
| } |
| } |
| |
| if (diagnostics_ != nullptr) { |
| diagnostics_->TrackDiskUsage(storage_class, static_cast<int64_t>(bytes), max_bytes); |
| } |
| }); |
| } |
| |
| void InternalMetricsImpl::Flush() { |
| std::vector<std::function<void()>> queued; |
| fields_.lock()->queued_lambdas.swap(queued); |
| |
| for (const auto& task : queued) { |
| task(); |
| } |
| } |
| |
| } // namespace cobalt::logger |