blob: 15c206c0085897f0e95d9e6cbce52a485b066090 [file] [log] [blame]
// Copyright 2019 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 "metrics.h"
#include <lib/async-testing/test_loop.h>
#include <memory>
#include <type_traits>
#include <utility>
#include <cobalt-client/cpp/collector.h>
#include <cobalt-client/cpp/in_memory_logger.h>
#include <fs/metrics/events.h>
#include <zxtest/zxtest.h>
namespace devmgr {
namespace {
using EventIntType = std::underlying_type<fs_metrics::Event>::type;
std::unique_ptr<cobalt_client::Collector> MakeCollector(cobalt_client::InMemoryLogger** logger) {
std::unique_ptr<cobalt_client::InMemoryLogger> logger_ptr =
std::make_unique<cobalt_client::InMemoryLogger>();
*logger = logger_ptr.get();
return std::make_unique<cobalt_client::Collector>(std::move(logger_ptr));
}
class MetricsTest : public zxtest::Test {
public:
void SetUp() override { collector_ = MakeCollector(&logger_); }
void TearDown() override { logger_ = nullptr; }
protected:
cobalt_client::InMemoryLogger* logger_;
std::unique_ptr<cobalt_client::Collector> collector_;
};
cobalt_client::MetricOptions MakeMetricOptionsFromId(uint32_t metric_id) {
cobalt_client::MetricOptions info = {};
info.metric_id = metric_id;
info.metric_dimensions = 2;
info.event_codes = {0};
info.event_codes[0] = static_cast<uint32_t>(fs_metrics::CorruptionSource::kMinfs);
info.event_codes[1] = static_cast<uint32_t>(fs_metrics::CorruptionType::kMetadata);
return info;
}
constexpr auto kCorruptionMetricId = static_cast<EventIntType>(fs_metrics::Event::kDataCorruption);
TEST_F(MetricsTest, LogMinfsDataCorruption) {
FsHostMetrics metrics(std::move(collector_));
ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
logger_->counters().end());
metrics.LogMinfsCorruption();
// Nothing is logged until flushed.
ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
logger_->counters().end());
// Once we flush, we should see the logged event in the metrics.
metrics.mutable_collector()->Flush();
ASSERT_NE(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
logger_->counters().end());
EXPECT_EQ(logger_->counters().at(MakeMetricOptionsFromId(kCorruptionMetricId)), 1);
}
TEST_F(MetricsTest, MultipleFlushWorks) {
FsHostMetrics metrics(std::move(collector_));
metrics.LogMinfsCorruption();
// Logger is not working
logger_->fail_logging(true);
metrics.Flush();
ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
logger_->counters().end());
// After 1 second, nothing should be logged. Sleep allows some time for the flushing
// thread to run.
sleep(1);
ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
logger_->counters().end());
// Logger begins working.
logger_->fail_logging(false);
metrics.Flush();
// After FsHostMetrics flush. Metrics should be available now.
// Block till counters change. Timed sleep without while loop is not sufficient because
// it make make test flake in virtual environment.
// The test may timeout and fail if the counter is never seen.
while (logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)) ==
logger_->counters().end()) {
// Rather than busy waiting, sleep for a second to let other threads to run.
sleep(1);
}
EXPECT_EQ(logger_->counters().at(MakeMetricOptionsFromId(kCorruptionMetricId)), 1);
}
TEST_F(MetricsTest, FlushDoesNotHangIfLoggerNotWorking) {
FsHostMetrics metrics(std::move(collector_));
metrics.LogMinfsCorruption();
// Logger is not working
logger_->fail_logging(true);
metrics.Flush();
ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
logger_->counters().end());
// After 1 second, nothing should be logged. Sleep allows some time for the flushing
// thread to run.
sleep(1);
ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
logger_->counters().end());
// Try to flush again.
metrics.Flush();
// Metrics should still be unavailable now.
ASSERT_EQ(logger_->counters().find(MakeMetricOptionsFromId(kCorruptionMetricId)),
logger_->counters().end());
}
TEST_F(MetricsTest, DestroyImmediatelySucceeds) {
FsHostMetrics metrics(std::move(collector_));
metrics.LogMinfsCorruption();
}
TEST_F(MetricsTest, SuccessWithNullCollector) {
FsHostMetrics metrics(nullptr);
metrics.LogMinfsCorruption();
// Sleep allows some time for thread to run.
sleep(1);
metrics.Flush();
}
} // namespace
} // namespace devmgr