blob: 7afdfed94e0c667b3aaba63b84b280eded810a13 [file] [log] [blame]
// 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 <memory>
#include <string>
#include <utility>
#include "src/logger/internal_metrics_config.cb.h"
#include "src/logging.h"
namespace cobalt::logger {
std::unique_ptr<InternalMetrics> InternalMetrics::NewWithLogger(LoggerInterface* logger) {
if (logger) {
return std::make_unique<InternalMetricsImpl>(logger);
}
return std::make_unique<NoOpInternalMetrics>();
}
InternalMetricsImpl::InternalMetricsImpl(LoggerInterface* logger) : logger_(logger) {
CHECK(logger_);
}
void InternalMetricsImpl::LoggerCalled(PerProjectLoggerCallsMadeMetricDimensionLoggerMethod method,
const Project& project) {
fields_.lock()->queued_lambdas.emplace_back([this, method, project] {
auto status = logger_->LogEventCount(kLoggerCallsMadeMetricId, method, "", 0, 1);
if (status != kOK) {
VLOG(1) << "InternalMetricsImpl::LoggerCalled: LogEventCount() returned status=" << status;
}
std::ostringstream component;
component << project.customer_name() << '/' << project.project_name();
status =
logger_->LogEventCount(kPerProjectLoggerCallsMadeMetricId, method, component.str(), 0, 1);
if (status != kOK) {
VLOG(1) << "InternalMetricsImpl::LoggerCalled: LogEventCount() returned status=" << status;
}
});
}
void InternalMetricsImpl::BytesUploaded(PerDeviceBytesUploadedMetricDimensionStatus upload_status,
int64_t byte_count) {
fields_.lock()->queued_lambdas.emplace_back([this, upload_status, byte_count] {
Status status =
logger_->LogEventCount(kPerDeviceBytesUploadedMetricId, upload_status, "", 0, byte_count);
if (status != kOK) {
VLOG(1) << "InternalMetricsImpl::BytesUploaded: LogEventCount() returned "
<< "status=" << status;
}
status = logger_->LogOccurrence(kBytesUploadedMetricId, byte_count, {upload_status});
if (status != kOK) {
VLOG(1) << "InternalMetricsImpl::BytesUploaded: LogOccurrence() returned "
<< "status=" << status;
}
});
}
void InternalMetricsImpl::BytesUploaded(PerProjectBytesUploadedMetricDimensionStatus upload_status,
int64_t byte_count, uint32_t customer_id,
uint32_t project_id) {
fields_.lock()->queued_lambdas.emplace_back(
[this, upload_status, byte_count, customer_id, project_id] {
std::ostringstream component;
component << customer_id << '/' << project_id;
auto status = logger_->LogEventCount(kPerProjectBytesUploadedMetricId, upload_status,
component.str(), 0, byte_count);
if (status != kOK) {
VLOG(1) << "InternalMetricsImpl::BytesUploaded: LogEventCount() returned "
<< "status=" << status;
}
});
}
void InternalMetricsImpl::BytesStored(PerProjectBytesStoredMetricDimensionStatus upload_status,
int64_t byte_count, uint32_t customer_id,
uint32_t project_id) {
fields_.lock()->queued_lambdas.emplace_back([this, upload_status, byte_count, customer_id,
project_id] {
std::ostringstream component;
component << customer_id << '/' << project_id;
auto status = logger_->LogMemoryUsage(kPerProjectBytesStoredMetricId, upload_status,
component.str(), byte_count);
if (status != kOK) {
VLOG(1) << "InternalMetricsImpl::BytesStored: LogMemoryUsage() returned status=" << status;
}
});
}
void InternalMetricsImpl::IdleObservationUpload(
IdleObservationUploadMetricDimensionDeviceState state) {
fields_.lock()->queued_lambdas.emplace_back([this, state] {
auto status = logger_->LogEventCount(kIdleObservationUploadMetricId, state, "", 0, 1);
if (status != kOK) {
VLOG(1) << "InternalMetricsImpl::IdleObservationUpload: LogEventCount() returned status="
<< status;
}
});
}
void InternalMetricsImpl::InaccurateClockEventsCached(int64_t event_count, uint32_t customer_id,
uint32_t project_id) {
fields_.lock()->queued_lambdas.emplace_back([this, event_count, customer_id, project_id] {
std::ostringstream component;
component << customer_id << '/' << project_id;
auto status = logger_->LogEventCount(kInaccurateClockEventsCachedMetricId, {}, component.str(),
0, event_count);
if (status != kOK) {
VLOG(1)
<< "InternalMetricsImpl::InaccurateClockEventsCached: LogEventCount() returned status="
<< status;
}
});
}
void InternalMetricsImpl::InaccurateClockEventsDropped(int64_t event_count, uint32_t customer_id,
uint32_t project_id) {
fields_.lock()->queued_lambdas.emplace_back([this, event_count, customer_id, project_id] {
std::ostringstream component;
component << customer_id << '/' << project_id;
auto status = logger_->LogEventCount(kInaccurateClockEventsDroppedMetricId, {}, component.str(),
0, event_count);
if (status != kOK) {
VLOG(1)
<< "InternalMetricsImpl::InaccurateClockEventsDropped: LogEventCount() returned status="
<< status;
}
});
}
void InternalMetricsImpl::SetSoftwareDistributionInfoCalled(
SetSoftwareDistributionInfoCalledEventCodes event_codes) {
fields_.lock()->queued_lambdas.emplace_back([this, event_codes] {
auto status = logger_->LogEventCount(kSetSoftwareDistributionInfoCalledMetricId,
event_codes.ToVector(), "", 0, 1);
if (status != kOK) {
VLOG(1) << "InternalMetricsImpl::SetSoftwareDistributionInfoCalled: LogEventCount() returned "
"status="
<< status;
}
});
}
const float kPerMilleMultiplier = 1000.0;
void InternalMetricsImpl::TrackDiskUsage(StorageClass storage_class, int64_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, bytes, {storage_class});
if (status != kOK) {
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 != kOK) {
VLOG(1) << "InternalMetricsImpl::TrackDiskUsage: LogInteger(disk_fullness) returned status="
<< status;
}
}
});
}
void InternalMetricsImpl::Flush() {
std::vector<std::function<void()>> queued;
fields_.lock()->queued_lambdas.swap(queued);
for (const auto& task : queued) {
task();
}
}
} // namespace cobalt::logger