/*
 * 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.
 */

/**
 * 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 apache { 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 = nullptr) 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<apache::thrift::concurrency::ThreadManager> threadManager);

private:

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

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

  apache::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
