// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "util/histogram-metric.h"

#include "kudu/util/hdr_histogram.h"
#include "util/json-util.h"
#include "util/pretty-printer.h"

#include "common/names.h"

namespace impala {

HistogramMetric::HistogramMetric(
    const TMetricDef& def, uint64_t highest_trackable_value, int num_significant_digits)
  : Metric(def),
    histogram_(new HdrHistogram(highest_trackable_value, num_significant_digits)),
    unit_(def.units) {
  DCHECK_EQ(TMetricKind::HISTOGRAM, def.kind);
}

void HistogramMetric::Reset() {
  lock_guard<SpinLock> l(lock_);
  uint64_t highest = histogram_->highest_trackable_value();
  int digits = histogram_->num_significant_digits();
  histogram_.reset(new HdrHistogram(highest, digits));
}

void HistogramMetric::ToJson(rapidjson::Document* document, rapidjson::Value* value) {
  rapidjson::Value container(rapidjson::kObjectType);
  AddStandardFields(document, &container);

  {
    lock_guard<SpinLock> l(lock_);

    container.AddMember(
        "25th %-ile", histogram_->ValueAtPercentile(25), document->GetAllocator());
    container.AddMember(
        "50th %-ile", histogram_->ValueAtPercentile(50), document->GetAllocator());
    container.AddMember(
        "75th %-ile", histogram_->ValueAtPercentile(75), document->GetAllocator());
    container.AddMember(
        "90th %-ile", histogram_->ValueAtPercentile(90), document->GetAllocator());
    container.AddMember(
        "95th %-ile", histogram_->ValueAtPercentile(95), document->GetAllocator());
    container.AddMember(
        "99.9th %-ile", histogram_->ValueAtPercentile(99.9), document->GetAllocator());
    container.AddMember("max", histogram_->MaxValue(), document->GetAllocator());
    container.AddMember("min", histogram_->MinValue(), document->GetAllocator());
    container.AddMember("count", histogram_->TotalCount(), document->GetAllocator());
  }
  rapidjson::Value type_value(
      PrintThriftEnum(TMetricKind::HISTOGRAM).c_str(), document->GetAllocator());
  container.AddMember("kind", type_value, document->GetAllocator());
  rapidjson::Value units(PrintThriftEnum(unit()).c_str(), document->GetAllocator());
  container.AddMember("units", units, document->GetAllocator());

  *value = container;
}

TMetricKind::type HistogramMetric::ToPrometheus(
    string name, stringstream* value, stringstream* metric_kind) {
  {
    lock_guard<SpinLock> l(lock_);

    // check if unit its 'TIME_MS','TIME_US' or 'TIME_NS' and convert it to seconds,
    // this is because prometheus only supports time format in seconds
    if (IsUnitTimeBased(unit_)) {
      *value << name << "{quantile=\"0.2\"} "
             << ConvertToPrometheusSecs(histogram_->ValueAtPercentile(25), unit_) << "\n";
    } else {
      *value << name << "{quantile=\"0.2\"} " << histogram_->ValueAtPercentile(25)
             << "\n";
    }

    if (IsUnitTimeBased(unit_)) {
      *value << name << "{quantile=\"0.5\"} "
             << ConvertToPrometheusSecs(histogram_->ValueAtPercentile(50), unit_) << "\n";
    } else {
      *value << name << "{quantile=\"0.5\"} " << histogram_->ValueAtPercentile(50)
             << "\n";
    }

    if (IsUnitTimeBased(unit_)) {
      *value << name << "{quantile=\"0.7\"} "
             << ConvertToPrometheusSecs(histogram_->ValueAtPercentile(75), unit_) << "\n";
    } else {
      *value << name << "{quantile=\"0.7\"} " << histogram_->ValueAtPercentile(75)
             << "\n";
    }

    if (IsUnitTimeBased(unit_)) {
      *value << name << "{quantile=\"0.9\"} "
             << ConvertToPrometheusSecs(histogram_->ValueAtPercentile(90), unit_) << "\n";
    } else {
      *value << name << "{quantile=\"0.9\"} " << histogram_->ValueAtPercentile(90)
             << "\n";
    }

    if (IsUnitTimeBased(unit_)) {
      *value << name << "{quantile=\"0.95\"} "
             << ConvertToPrometheusSecs(histogram_->ValueAtPercentile(95), unit_) << "\n";
    } else {
      *value << name << "{quantile=\"0.95\"} " << histogram_->ValueAtPercentile(95)
             << "\n";
    }

    if (IsUnitTimeBased(unit_)) {
      *value << name << "{quantile=\"0.999\"} "
             << ConvertToPrometheusSecs(histogram_->ValueAtPercentile(99.9), unit_)
             << "\n";
    } else {
      *value << name << "{quantile=\"0.999\"} " << histogram_->ValueAtPercentile(99.9)
             << "\n";
    }

    *value << name << "_count " << histogram_->TotalCount() << "\n";

    if (IsUnitTimeBased(unit_)) {
      *value << name << "_sum " << ConvertToPrometheusSecs(histogram_->TotalSum(), unit_);
    } else {
      *value << name << "_sum " << histogram_->TotalSum();
    }
  }

  *metric_kind << "# TYPE " << name << " summary";
  return TMetricKind::HISTOGRAM;
}

string HistogramMetric::ToHumanReadable() {
  lock_guard<SpinLock> l(lock_);
  return HistogramToHumanReadable(histogram_.get(), unit_);
}

template <class T>
string HistogramMetric::HistogramToHumanReadable(T* histogram, TUnit::type unit) {
  DCHECK(histogram != nullptr);
  stringstream out;
  out << "Count: " << histogram->TotalCount() << ", "
      << "min / max: " << PrettyPrinter::Print(histogram->MinValue(), unit) << " / "
      << PrettyPrinter::Print(histogram->MaxValue(), unit) << ", "
      << "25th %-ile: " << PrettyPrinter::Print(histogram->ValueAtPercentile(25), unit)
      << ", "
      << "50th %-ile: " << PrettyPrinter::Print(histogram->ValueAtPercentile(50), unit)
      << ", "
      << "75th %-ile: " << PrettyPrinter::Print(histogram->ValueAtPercentile(75), unit)
      << ", "
      << "90th %-ile: " << PrettyPrinter::Print(histogram->ValueAtPercentile(90), unit)
      << ", "
      << "95th %-ile: " << PrettyPrinter::Print(histogram->ValueAtPercentile(95), unit)
      << ", "
      << "99.9th %-ile: "
      << PrettyPrinter::Print(histogram->ValueAtPercentile(99.9), unit);
  return out.str();
}

// Instantiate the template for both Impala and Kudu histograms.
template string HistogramMetric::HistogramToHumanReadable<>(HdrHistogram*, TUnit::type);
template string HistogramMetric::HistogramToHumanReadable<>(
    kudu::HdrHistogram*, TUnit::type);
} // namespace impala
