| // 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 { |
| |
| uint32_t GetProjectEventCode(const std::string& project_identifier, |
| const std::map<std::string, uint32_t>& project_map) { |
| auto event_code = project_map.find(project_identifier); |
| if (event_code != project_map.end()) { |
| return event_code->second; |
| } |
| return 0; |
| } |
| |
| uint32_t GetProjectEventCode(const std::string& project_identifier) { |
| return GetProjectEventCode(project_identifier, |
| kPerProjectBytesStoredMigratedMetricDimensionProjectsNameMap); |
| } |
| |
| } // 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) {} |
| |
| 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::LocalAggregationQuotaEvent( |
| const lib::ProjectIdentifier& project_identifier, |
| LocalAggregationQuotaMetricDimensionEventType event_type) { |
| fields_.lock()->queued_lambdas.emplace_back([this, project_identifier, event_type] { |
| std::ostringstream component; |
| component << project_identifier.customer_id() << '/' << project_identifier.project_id(); |
| |
| auto status = logger_.LogOccurrence(kLocalAggregationQuotaMetricId, 1, |
| {GetProjectEventCode(component.str()), event_type}); |
| |
| if (!status.ok()) { |
| VLOG(1) << "InternalMetricsImpl::BytesStored: LogInteger() returned status=" << status; |
| } |
| |
| if (diagnostics_ != nullptr) { |
| diagnostics_->LocalAggregationQuotaEvent(project_identifier, event_type); |
| } |
| }); |
| } |
| |
| void InternalMetricsImpl::Flush() { |
| std::vector<std::function<void()>> queued; |
| fields_.lock()->queued_lambdas.swap(queued); |
| |
| for (const auto& task : queued) { |
| task(); |
| } |
| } |
| |
| } // namespace cobalt::logger |