// Copyright 2020 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/developer/memory/monitor/metrics.h"

#include <lib/syslog/cpp/macros.h>
#include <lib/trace/event.h>
#include <zircon/time.h>

#include <algorithm>
#include <array>
#include <string>

#include <src/lib/cobalt/cpp/metric_event_builder.h>

#include "lib/fpromise/result.h"
#include "src/developer/memory/metrics/digest.h"
#include "src/developer/memory/metrics/printer.h"

namespace monitor {

using namespace memory;
using cobalt_registry::MemoryMigratedMetricDimensionBucket;
using TimeSinceBoot = cobalt_registry::MemoryLeakMigratedMetricDimensionTimeSinceBoot;

namespace {
static const std::map<zx_duration_t, TimeSinceBoot> UptimeLevelMap = {
    {zx_duration_from_min(1), TimeSinceBoot::Up},
    {zx_duration_from_min(30), TimeSinceBoot::UpOneMinute},
    {zx_duration_from_hour(1), TimeSinceBoot::UpThirtyMinutes},
    {zx_duration_from_hour(6), TimeSinceBoot::UpOneHour},
    {zx_duration_from_hour(12), TimeSinceBoot::UpSixHours},
    {zx_duration_from_hour(24), TimeSinceBoot::UpTwelveHours},
    {zx_duration_from_hour(48), TimeSinceBoot::UpOneDay},
    {zx_duration_from_hour(72), TimeSinceBoot::UpTwoDays},
    {zx_duration_from_hour(144), TimeSinceBoot::UpThreeDays},
};
}  // namespace

// Metrics polls the memory state periodically asynchroniously using the passed dispatcher and sends
// information about the memory Digests to Cobalt, in the form of several Events.
Metrics::Metrics(const std::vector<memory::BucketMatch>& bucket_matches,
                 zx::duration poll_frequency, async_dispatcher_t* dispatcher,
                 sys::ComponentInspector* inspector,
                 fuchsia::metrics::MetricEventLogger_Sync* logger, CaptureCb capture_cb,
                 DigestCb digest_cb)
    : poll_frequency_(poll_frequency),
      dispatcher_(dispatcher),
      logger_(logger),
      capture_cb_(std::move(capture_cb)),
      digest_cb_(std::move(digest_cb)),
      bucket_name_to_code_({
          {"TotalBytes", MemoryMigratedMetricDimensionBucket::TotalBytes},
          {"Free", MemoryMigratedMetricDimensionBucket::Free},
          {"Kernel", MemoryMigratedMetricDimensionBucket::Kernel},
          {"Orphaned", MemoryMigratedMetricDimensionBucket::Orphaned},
          {"Undigested", MemoryMigratedMetricDimensionBucket::Undigested},
          {"[Addl]PagerTotal", MemoryMigratedMetricDimensionBucket::__Addl_PagerTotal},
          {"[Addl]PagerNewest", MemoryMigratedMetricDimensionBucket::__Addl_PagerNewest},
          {"[Addl]PagerOldest", MemoryMigratedMetricDimensionBucket::__Addl_PagerOldest},
          {"[Addl]DiscardableLocked",
           MemoryMigratedMetricDimensionBucket::__Addl_DiscardableLocked},
          {"[Addl]DiscardableUnlocked",
           MemoryMigratedMetricDimensionBucket::__Addl_DiscardableUnlocked},
      }),
      inspector_(inspector),
      platform_metric_node_(inspector_->root().CreateChild(kInspectPlatformNodeName)),
      // Diagram of hierarchy can be seen below:
      // root
      // - platform_metrics
      //   - memory_usages
      //     - Amber
      //     - Amlogic
      //     - ...
      //     - timestamp
      //   - memory_bandwidth
      //     - readings
      metric_memory_node_(platform_metric_node_.CreateChild(kMemoryNodeName)),
      inspect_memory_timestamp_(metric_memory_node_.CreateInt(kReadingMemoryTimestamp, 0)),
      metric_memory_bandwidth_node_(platform_metric_node_.CreateChild(kMemoryBandwidthNodeName)),
      inspect_memory_bandwidth_(
          metric_memory_bandwidth_node_.CreateUintArray(kReadings, kMemoryBandwidthArraySize)),
      inspect_memory_bandwidth_timestamp_(
          metric_memory_bandwidth_node_.CreateInt(kReadingMemoryTimestamp, 0)) {
  for (const auto& bucket : bucket_matches) {
    if (!bucket.event_code().has_value()) {
      continue;
    }
    bucket_name_to_code_.emplace(
        bucket.name(), static_cast<MemoryMigratedMetricDimensionBucket>(*bucket.event_code()));
  }
  for (const auto& element : bucket_name_to_code_) {
    inspect_memory_usages_.insert(std::pair<std::string, inspect::UintProperty>(
        element.first, metric_memory_node_.CreateUint(element.first, 0)));
  }

  task_.PostDelayed(dispatcher_, zx::usec(1));
}

void Metrics::CollectMetrics() {
  TRACE_DURATION("memory_monitor", "Watcher::Metrics::CollectMetrics");
  Capture capture;
  capture_cb_(&capture);
  Digest digest;
  digest_cb_(capture, &digest);

  WriteDigestToInspect(digest);

  std::vector<fuchsia::metrics::MetricEvent> events;
  const auto& kmem = capture.kmem();
  AddKmemEvents(kmem, &events);
  AddKmemEventsWithUptime(kmem, capture.time(), &events);
  auto builder = cobalt::MetricEventBuilder(cobalt_registry::kMemoryMigratedMetricId);
  for (const auto& bucket : digest.buckets()) {
    if (bucket.size() == 0) {
      continue;
    }
    const auto& code_iter = bucket_name_to_code_.find(bucket.name());
    if (code_iter == bucket_name_to_code_.end()) {
      FX_LOGS_FIRST_N(ERROR, 3) << "Metrics::CollectMetrics: Invalid bucket name: "
                                << bucket.name();
      continue;
    }
    events.push_back(builder.Clone().with_event_code(code_iter->second).as_integer(bucket.size()));
  }
  fuchsia::metrics::MetricEventLogger_LogMetricEvents_Result response =
      fpromise::error(fuchsia::metrics::Error::INTERNAL_ERROR);
  logger_->LogMetricEvents(std::move(events), &response);
  if (response.is_err() && response.err() == fuchsia::metrics::Error::INVALID_ARGUMENTS) {
    FX_LOGS(ERROR) << "LogMetricEvents() returned status INVALID_ARGUMENTS";
  }
  task_.PostDelayed(dispatcher_, poll_frequency_);
}

void Metrics::WriteDigestToInspect(const memory::Digest& digest) {
  TRACE_DURATION("memory_monitor", "Watcher::Metrics::WriteDigestToInspect");
  // The division is to address JSON int range problem in b/156523968
  // JSON does not suport 64 bit integers and some readers using JSON libraries will
  // crash if we write a value greater than MAX_INT_32.
  // The unit in seconds is sufficient.
  inspect_memory_timestamp_.Set(digest.time() / 1000000000);
  for (auto const& bucket : digest.buckets()) {
    auto it = inspect_memory_usages_.find(bucket.name());
    if (it == inspect_memory_usages_.end()) {
      FX_LOGS_FIRST_N(INFO, 3) << "Not_in_map: " << bucket.name() << ": " << bucket.size() << "\n";
      continue;
    }
    it->second.Set(bucket.size());
  }
}

void Metrics::AddKmemEvents(const zx_info_kmem_stats_t& kmem,
                            std::vector<fuchsia::metrics::MetricEvent>* events) {
  TRACE_DURATION("memory_monitor", "Metrics::AddKmemEvents");
  auto builder =
      cobalt::MetricEventBuilder(cobalt_registry::kMemoryGeneralBreakdownMigratedMetricId);
  using Breakdown = cobalt_registry::MemoryGeneralBreakdownMigratedMetricDimensionGeneralBreakdown;
  events->push_back(
      builder.Clone().with_event_code(Breakdown::TotalBytes).as_integer(kmem.total_bytes));
  events->push_back(builder.Clone()
                        .with_event_code(Breakdown::UsedBytes)
                        .as_integer(kmem.total_bytes - kmem.free_bytes));
  events->push_back(
      builder.Clone().with_event_code(Breakdown::FreeBytes).as_integer(kmem.free_bytes));
  events->push_back(
      builder.Clone().with_event_code(Breakdown::VmoBytes).as_integer(kmem.vmo_bytes));
  events->push_back(builder.Clone()
                        .with_event_code(Breakdown::KernelFreeHeapBytes)
                        .as_integer(kmem.free_heap_bytes));
  events->push_back(
      builder.Clone().with_event_code(Breakdown::MmuBytes).as_integer(kmem.mmu_overhead_bytes));
  events->push_back(
      builder.Clone().with_event_code(Breakdown::IpcBytes).as_integer(kmem.ipc_bytes));
  events->push_back(builder.Clone()
                        .with_event_code(Breakdown::KernelTotalHeapBytes)
                        .as_integer(kmem.total_heap_bytes));
  events->push_back(
      builder.Clone().with_event_code(Breakdown::WiredBytes).as_integer(kmem.wired_bytes));
  events->push_back(
      builder.Clone().with_event_code(Breakdown::OtherBytes).as_integer(kmem.other_bytes));
}

// TODO(fxbug.dev/3778): Refactor this when dedup enum is availble in generated
// cobalt config source code.
void Metrics::AddKmemEventsWithUptime(const zx_info_kmem_stats_t& kmem,
                                      const zx_time_t capture_time,
                                      std::vector<fuchsia::metrics::MetricEvent>* events) {
  TRACE_DURATION("memory_monitor", "Metrics::AddKmemEventsWithUptime");
  auto builder = std::move(cobalt::MetricEventBuilder(cobalt_registry::kMemoryLeakMigratedMetricId)
                               .with_event_code_at(1, GetUpTimeEventCode(capture_time)));
  using Breakdown = cobalt_registry::MemoryLeakMigratedMetricDimensionGeneralBreakdown;
  events->push_back(
      builder.Clone().with_event_code_at(0, Breakdown::TotalBytes).as_integer(kmem.total_bytes));
  events->push_back(builder.Clone()
                        .with_event_code_at(0, Breakdown::UsedBytes)
                        .as_integer(kmem.total_bytes - kmem.free_bytes));
  events->push_back(
      builder.Clone().with_event_code_at(0, Breakdown::FreeBytes).as_integer(kmem.free_bytes));
  events->push_back(
      builder.Clone().with_event_code_at(0, Breakdown::VmoBytes).as_integer(kmem.vmo_bytes));
  events->push_back(builder.Clone()
                        .with_event_code_at(0, Breakdown::KernelFreeHeapBytes)
                        .as_integer(kmem.free_heap_bytes));
  events->push_back(builder.Clone()
                        .with_event_code_at(0, Breakdown::MmuBytes)
                        .as_integer(kmem.mmu_overhead_bytes));
  events->push_back(
      builder.Clone().with_event_code_at(0, Breakdown::IpcBytes).as_integer(kmem.ipc_bytes));
  events->push_back(builder.Clone()
                        .with_event_code_at(0, Breakdown::KernelTotalHeapBytes)
                        .as_integer(kmem.total_heap_bytes));
  events->push_back(
      builder.Clone().with_event_code_at(0, Breakdown::WiredBytes).as_integer(kmem.wired_bytes));
  events->push_back(
      builder.Clone().with_event_code_at(0, Breakdown::OtherBytes).as_integer(kmem.other_bytes));
}

TimeSinceBoot Metrics::GetUpTimeEventCode(const zx_time_t capture_time) {
  zx_duration_t uptime = zx_duration_from_nsec(capture_time);
  for (auto const& map : UptimeLevelMap) {
    if (uptime < map.first) {
      return map.second;
    }
  }
  return TimeSinceBoot::UpSixDays;
}

void Metrics::NextMemoryBandwidthReading(uint64_t reading, zx_time_t ts) {
  inspect_memory_bandwidth_.Set(memory_bandwidth_index_, reading);
  inspect_memory_bandwidth_timestamp_.Set(ts);
  if (++memory_bandwidth_index_ >= kMemoryBandwidthArraySize)
    memory_bandwidth_index_ = 0;
}

}  // namespace monitor
