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