stats.hpp 8.83 KiB
Newer Older
Ramon Nou's avatar
Ramon Nou committed
/*
  Copyright 2018-2022, Barcelona Supercomputing Center (BSC), Spain
  Copyright 2015-2022, Johannes Gutenberg Universitaet Mainz, Germany

  This software was partially supported by the
  EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).

  This software was partially supported by the
  ADA-FS project under the SPPEXA project funded by the DFG.

  This file is part of GekkoFS.

  GekkoFS is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  GekkoFS is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with GekkoFS.  If not, see <https://www.gnu.org/licenses/>.

  SPDX-License-Identifier: GPL-3.0-or-later
*/

#ifndef GKFS_COMMON_STATS_HPP
#define GKFS_COMMON_STATS_HPP

#include <cstdint>
#include <unistd.h>
#include <cassert>
#include <map>
Ramon Nou's avatar
Ramon Nou committed
#include <vector>
#include <deque>
#include <chrono>
#include <initializer_list>
Ramon Nou's avatar
Ramon Nou committed
#include <thread>
#include <iostream>
#include <iomanip>
#include <fstream>
Ramon Nou's avatar
Ramon Nou committed
#include <config.hpp>
Ramon Nou's avatar
Ramon Nou committed


Ramon Nou's avatar
Ramon Nou committed
// PROMETHEUS includes
#ifdef GKFS_ENABLE_PROMETHEUS
Ramon Nou's avatar
Ramon Nou committed
#include <prometheus/counter.h>
#include <prometheus/summary.h>
Ramon Nou's avatar
Ramon Nou committed
#include <prometheus/exposer.h>
#include <prometheus/registry.h>
#include <prometheus/gateway.h>
Ramon Nou's avatar
Ramon Nou committed

using namespace prometheus;
Ramon Nou's avatar
Ramon Nou committed
/**
 * Provides storage capabilities to provide stats about GekkoFS
Ramon Nou's avatar
Ramon Nou committed
 * The information is per server.
Ramon Nou's avatar
Ramon Nou committed
 * We do not provide accurate stats for 1-5-10 minute stats
Ramon Nou's avatar
Ramon Nou committed
 *
Ramon Nou's avatar
Ramon Nou committed
 */
namespace gkfs::utils {

Ramon Nou's avatar
Ramon Nou committed
/**
 *
 * Number of operations (Create, write/ read, remove, mkdir...)
 * Size of database (metadata keys, should be not needed, any)
 * Size of data (+write - delete)
 * Server Bandwidth (write / read operations)
 *
 * mean, (lifetime of the server)
 * 1 minute mean
 * 5 minute mean
 * 10 minute mean
 *
 * To provide the stats that we need,
 * we need to store the info and the timestamp to calculate it
 * A vector should work, with a maximum of elements,
 */

Ramon Nou's avatar
Ramon Nou committed
class Stats {
public:
Ramon Nou's avatar
Ramon Nou committed
    enum class IopsOp {
        iops_create,
        iops_write,
        iops_read,
        iops_stats,
        iops_dirent,
        iops_remove,
Ramon Nou's avatar
Ramon Nou committed
    }; ///< enum storing IOPS Stats
Ramon Nou's avatar
Ramon Nou committed

Ramon Nou's avatar
Ramon Nou committed
    enum class SizeOp { write_size, read_size }; ///< enum storing Size Stats
Ramon Nou's avatar
Ramon Nou committed

Ramon Nou's avatar
Ramon Nou committed
private:
Ramon Nou's avatar
Ramon Nou committed
    constexpr static const std::initializer_list<Stats::IopsOp> all_IopsOp = {
            IopsOp::iops_create, IopsOp::iops_write,
            IopsOp::iops_read,   IopsOp::iops_stats,
            IopsOp::iops_dirent, IopsOp::iops_remove}; ///< Enum IOPS iterator

    constexpr static const std::initializer_list<Stats::SizeOp> all_SizeOp = {
            SizeOp::write_size, SizeOp::read_size}; ///< Enum SIZE iterator

    const std::vector<std::string> IopsOp_s = {
Ramon Nou's avatar
Ramon Nou committed
            "IOPS_CREATE", "IOPS_WRITE",   "IOPS_READ",
            "IOPS_STATS",  "IOPS_DIRENTS", "IOPS_REMOVE"}; ///< Stats Labels
Ramon Nou's avatar
Ramon Nou committed
    const std::vector<std::string> SizeOp_s = {"WRITE_SIZE",
                                               "READ_SIZE"}; ///< Stats Labels
Ramon Nou's avatar
Ramon Nou committed

    std::chrono::time_point<std::chrono::steady_clock>
            start; ///< When we started the server


Ramon Nou's avatar
Ramon Nou committed
    std::map<IopsOp, unsigned long>
Ramon Nou's avatar
Ramon Nou committed
            IOPS; ///< Stores total value for global mean
Ramon Nou's avatar
Ramon Nou committed
    std::map<SizeOp, unsigned long>
Ramon Nou's avatar
Ramon Nou committed
            SIZE; ///< Stores total value for global mean

Ramon Nou's avatar
Ramon Nou committed
    std::map<IopsOp,
Ramon Nou's avatar
Ramon Nou committed
             std::deque<std::chrono::time_point<std::chrono::steady_clock>>>
Ramon Nou's avatar
Ramon Nou committed
            TimeIops; ///< Stores timestamp when an operation comes removes if
                      ///< first operation if > 10 minutes Different means will
                      ///< be stored and cached 1 minuted
Ramon Nou's avatar
Ramon Nou committed

Ramon Nou's avatar
Ramon Nou committed

Ramon Nou's avatar
Ramon Nou committed
    std::map<SizeOp, std::deque<std::pair<
                             std::chrono::time_point<std::chrono::steady_clock>,
                             unsigned long long>>>
            TimeSize; ///< For size operations we need to store the timestamp
                      ///< and the size
Ramon Nou's avatar
Ramon Nou committed

Ramon Nou's avatar
Ramon Nou committed

Ramon Nou's avatar
Ramon Nou committed
    std::thread t_output; ///< Thread that outputs stats info
    bool output_thread_;  ///< Enables or disables the output thread
Ramon Nou's avatar
Ramon Nou committed

Ramon Nou's avatar
Ramon Nou committed
    bool running =
            true; ///< Controls the destruction of the class/stops the thread
Ramon Nou's avatar
Ramon Nou committed
    /**
     * @brief Sends all the stats to the screen
     * Debug Function
     *
     * @param d is the time between output
     * @param file_output is the output file
     */
    void
    output(std::chrono::seconds d, std::string file_output);

    std::map<std::pair<std::string, unsigned long long>, unsigned int>
Ramon Nou's avatar
Ramon Nou committed
            chunkRead; ///< Stores the number of times a chunk/file is read
    std::map<std::pair<std::string, unsigned long long>, unsigned int>
Ramon Nou's avatar
Ramon Nou committed
            chunkWrite; ///< Stores the number of times a chunk/file is write

    /**
     * @brief Called by output to generate CHUNK map
     *
     * @param output is the output stream
     */
    void
    output_map(std::ofstream& output);


    /**
     * @brief Dumps all the means from the stats
     * @param of Output stream
Ramon Nou's avatar
Ramon Nou committed
     */
    void
Ramon Nou's avatar
Ramon Nou committed

Ramon Nou's avatar
Ramon Nou committed

Ramon Nou's avatar
Ramon Nou committed
// Prometheus Push structs
#ifdef GKFS_ENABLE_PROMETHEUS
Ramon Nou's avatar
Ramon Nou committed
    std::shared_ptr<Gateway> gateway;   ///< Prometheus Gateway
    std::shared_ptr<Registry> registry; ///< Prometheus Counters Registry
Ramon Nou's avatar
Ramon Nou committed
    Family<Counter>* family_counter;    ///< Prometheus IOPS counter (managed by
                                        ///< Prometheus cpp)
    Family<Summary>* family_summary;    ///< Prometheus SIZE counter (managed by
                                        ///< Prometheus cpp)
    std::map<IopsOp, Counter*> iops_Prometheus; ///< Prometheus IOPS metrics
    std::map<SizeOp, Summary*> size_Prometheus; ///< Prometheus SIZE metrics
Ramon Nou's avatar
Ramon Nou committed
#endif
Ramon Nou's avatar
Ramon Nou committed

Ramon Nou's avatar
Ramon Nou committed
public:
    /**
     * @brief Starts the Stats module and initializes structures
     * @param output_thread creates an aditional thread that outputs the stats
     * @param filename file where to write the output
Ramon Nou's avatar
Ramon Nou committed
     * @param prometheus_gateway ip:port to expose the metrics
Ramon Nou's avatar
Ramon Nou committed
     */
Ramon Nou's avatar
Ramon Nou committed
    Stats(bool output_thread, const std::string& filename,
          const std::string& prometheus_gateway);
Ramon Nou's avatar
Ramon Nou committed

    /**
     * @brief Destroys the class, and any associated thread
     *
     */
    ~Stats();

Ramon Nou's avatar
Ramon Nou committed

    /**
     * @brief Set the up Prometheus gateway and structures
     *
Ramon Nou's avatar
Ramon Nou committed
     * @param gateway_ip ip of the prometheus gateway
     * @param gateway_port port of the prometheus gateway
Ramon Nou's avatar
Ramon Nou committed
     */
    void
Ramon Nou's avatar
Ramon Nou committed
    setup_Prometheus(const std::string& gateway_ip,
                     const std::string& gateway_port);
    /**
     * @brief Adds a new read access to the chunk/path specified
     *
Ramon Nou's avatar
Ramon Nou committed
     * @param path path of the chunk
     * @param chunk chunk number
Ramon Nou's avatar
Ramon Nou committed
    add_read(const std::string& path, unsigned long long chunk);
    /**
     * @brief Adds a new write access to the chunk/path specified
     *
Ramon Nou's avatar
Ramon Nou committed
     * @param path path of the chunk
     * @param chunk chunk number
Ramon Nou's avatar
Ramon Nou committed
    add_write(const std::string& path, unsigned long long chunk);
Ramon Nou's avatar
Ramon Nou committed
    /**
     * Add a new value for a IOPS, that does not involve any size
     * No value needed as they are simple (1 create, 1 read...)
     * Size operations internally call this operation (read,write)
     *
Ramon Nou's avatar
Ramon Nou committed
     * @param IopsOp Which operation to add
Ramon Nou's avatar
Ramon Nou committed
     */

Ramon Nou's avatar
Ramon Nou committed
    void add_value_iops(enum IopsOp);
Ramon Nou's avatar
Ramon Nou committed

    /**
     * @brief Store a new stat point, with a size value.
     * If it involves a IO operations it will call the corresponding
     * operation
     *
Ramon Nou's avatar
Ramon Nou committed
     * @param SizeOp Which operation we refer
     * @param value to store (SizeOp)
Ramon Nou's avatar
Ramon Nou committed
     */
    void
Ramon Nou's avatar
Ramon Nou committed
    add_value_size(enum SizeOp, unsigned long long value);
Ramon Nou's avatar
Ramon Nou committed

    /**
     * @brief Get the total mean value of the asked stat
     * This can be provided inmediately without cost
Ramon Nou's avatar
Ramon Nou committed
     * @param IopsOp Which operation to get
Ramon Nou's avatar
Ramon Nou committed
     * @return mean value
     */
Ramon Nou's avatar
Ramon Nou committed
    double get_mean(enum IopsOp);
Ramon Nou's avatar
Ramon Nou committed


    /**
     * @brief Get the total mean value of the asked stat
     * This can be provided inmediately without cost
Ramon Nou's avatar
Ramon Nou committed
     * @param SizeOp Which operation to get
Ramon Nou's avatar
Ramon Nou committed
     * @return mean value
     */
Ramon Nou's avatar
Ramon Nou committed
    double get_mean(enum SizeOp);
Ramon Nou's avatar
Ramon Nou committed

    /**
     * @brief Get all the means (total, 1,5 and 10 minutes) for a SIZE_OP
     * Returns precalculated values if we just calculated them 1 minute ago
Ramon Nou's avatar
Ramon Nou committed
     * @param SizeOp Which operation to get
Ramon Nou's avatar
Ramon Nou committed
     *
     * @return std::vector< double > with 4 means
     */
Ramon Nou's avatar
Ramon Nou committed
    std::vector<double> get_four_means(enum SizeOp);
Ramon Nou's avatar
Ramon Nou committed

    /**
     * @brief Get all the means (total, 1,5 and 10 minutes) for a IOPS_OP
     * Returns precalculated values if we just calculated them 1 minute ago
Ramon Nou's avatar
Ramon Nou committed
     * @param IopsOp Which operation to get
Ramon Nou's avatar
Ramon Nou committed
     *
     * @return std::vector< double > with 4 means
     */
Ramon Nou's avatar
Ramon Nou committed
    std::vector<double> get_four_means(enum IopsOp);
Ramon Nou's avatar
Ramon Nou committed
};

} // namespace gkfs::utils

#endif // GKFS_COMMON_STATS_HPP