/*
 * 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 "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 = 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<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
