// Copyright (c) 2006- Facebook
// Distributed under the Thrift Software License
//
// See accompanying file LICENSE or visit the Thrift site at:
// http://developers.facebook.com/thrift/

/**
 * ServiceTracker is a utility class for logging and timing service
 * calls to a fb303 Thrift server.  Currently, ServiceTracker offers
 * the following features:
 *
 *   . Logging of service method start, end (and duration), and
 *     optional steps in between.
 *
 *   . Automatic check of server status via fb303::getStatus()
 *     with a ServiceException thrown if server not alive
 *     (at method start).
 *
 *   . A periodic logged checkpoint reporting lifetime time, lifetime
 *     service count, and per-method statistics since the last checkpoint
 *     time (at method finish).
 *
 *   . Export of fb303 counters for lifetime and checkpoint statistics
 *     (at method finish).
 *
 *   . For TThreadPoolServers, a logged warning when all server threads
 *     are busy (at method start).  (Must call setThreadManager() after
 *     ServiceTracker instantiation for this feature to be enabled.)
 *
 * Individual features may be enabled or disabled by arguments to the
 * constructor.  The constructor also accepts a pointer to a logging
 * method -- if no pointer is passed, the tracker will log to stdout.
 *
 * ServiceTracker defines private methods for service start, finish,
 * and step, which are designed to be accessed by instantiating a
 * friend ServiceMethod object, as in the following example:
 *
 *    #include <ServiceTracker.h>
 *    class MyServiceHandler : virtual public MyServiceIf,
 *                             public facebook::fb303::FacebookBase
 *    {
 *    public:
 *      MyServiceHandler::MyServiceHandler() : mServiceTracker(this) {}
 *      void MyServiceHandler::myServiceMethod(int userId) {
 *        // note: Instantiating a ServiceMethod object starts a timer
 *        // and tells the ServiceTracker to log the start.  Might throw
 *        // a ServiceException.
 *        ServiceMethod serviceMethod(&mServiceTracker,
 *                                   "myServiceMethod",
 *                                   userId);
 *        ...
 *        // note: Calling the step method tells the ServiceTracker to
 *        // log the step, with a time elapsed since start.
 *        serviceMethod.step("post parsing, begin processing");
 *        ...
 *        // note: When the ServiceMethod object goes out of scope, the
 *        // ServiceTracker will log the total elapsed time of the method.
 *      }
 *      ...
 *    private:
 *      ServiceTracker mServiceTracker;
 *    }
 *
 * The step() method call is optional; the startService() and
 * finishService() methods are handled by the object's constructor and
 * destructor.
 *
 * The ServiceTracker is (intended to be) thread-safe.
 *
 * Future:
 *
 *   . Come up with something better for logging than passing a
 *     function pointer to the constructor.
 *
 *   . Add methods for tracking errors from service methods, e.g.
 *     ServiceTracker::reportService().
 */

#ifndef SERVICETRACKER_H
#define SERVICETRACKER_H


#include <iostream>
#include <string>
#include <sstream>
#include <exception>
#include <map>
#include <boost/shared_ptr.hpp>

#include "thrift/concurrency/Mutex.h"


namespace facebook { namespace thrift { namespace concurrency {
  class ThreadManager;
}}}


namespace facebook { namespace fb303 {


class FacebookBase;
class ServiceMethod;


class Stopwatch
{
public:
  enum Unit { UNIT_SECONDS, UNIT_MILLISECONDS, UNIT_MICROSECONDS };
  Stopwatch();
  uint64_t elapsedUnits(Unit unit, std::string *label = NULL) const;
  void reset();
private:
  timeval startTime_;
};


class ServiceTracker
{
  friend class ServiceMethod;

public:

  static uint64_t CHECKPOINT_MINIMUM_INTERVAL_SECONDS;
  static int LOG_LEVEL;

  ServiceTracker(facebook::fb303::FacebookBase *handler,
                 void (*logMethod)(int, const std::string &)
                 = &ServiceTracker::defaultLogMethod,
                 bool featureCheckpoint = true,
                 bool featureStatusCheck = true,
                 bool featureThreadCheck = true,
                 Stopwatch::Unit stopwatchUnit
                 = Stopwatch::UNIT_MILLISECONDS);

  void setThreadManager(boost::shared_ptr<facebook::thrift::concurrency::ThreadManager> threadManager);

private:

  facebook::fb303::FacebookBase *handler_;
  void (*logMethod_)(int, const std::string &);
  boost::shared_ptr<facebook::thrift::concurrency::ThreadManager> threadManager_;

  bool featureCheckpoint_;
  bool featureStatusCheck_;
  bool featureThreadCheck_;
  Stopwatch::Unit stopwatchUnit_;

  facebook::thrift::concurrency::Mutex statisticsMutex_;
  time_t checkpointTime_;
  uint64_t checkpointServices_;
  uint64_t checkpointDuration_;
  std::map<std::string, std::pair<uint64_t, uint64_t> > checkpointServiceDuration_;

  void startService(const ServiceMethod &serviceMethod);
  int64_t stepService(const ServiceMethod &serviceMethod,
                      const std::string &stepName);
  void finishService(const ServiceMethod &serviceMethod);
  void reportCheckpoint();
  static void defaultLogMethod(int level, const std::string &message);
};


class ServiceMethod
{
  friend class ServiceTracker;
public:
  ServiceMethod(ServiceTracker *tracker,
                const std::string &name,
                const std::string &signature,
                bool featureLogOnly = false);
  ServiceMethod(ServiceTracker *tracker,
                const std::string &name,
                uint64_t id,
                bool featureLogOnly = false);
  ~ServiceMethod();
  uint64_t step(const std::string &stepName);
private:
  ServiceTracker *tracker_;
  std::string name_;
  std::string signature_;
  bool featureLogOnly_;
  Stopwatch timer_;
};


class ServiceException : public std::exception
{
public:
  explicit ServiceException(const std::string &message, int code = 0)
    : message_(message), code_(code) {}
  ~ServiceException() throw() {}
  virtual const char *what() const throw() { return message_.c_str(); }
  int code() const throw() { return code_; }
private:
  std::string message_;
  int code_;
};


}} // facebook::fb303

#endif
