diff --git a/Descriptors/GPXDescriptor.h b/Descriptors/GPXDescriptor.h index 105a09abf67..47041deb236 100644 --- a/Descriptors/GPXDescriptor.h +++ b/Descriptors/GPXDescriptor.h @@ -56,8 +56,9 @@ class GPXDescriptor : public BaseDescriptor { "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " "xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd" "\">"); + reply.content.push_back(""); reply.content.push_back( - "Data (c)" + "Data (c)" " OpenStreetMap contributors (ODbL)" ""); reply.content.push_back(""); diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h index c42482c23cb..8952cf34a54 100644 --- a/Descriptors/JSONDescriptor.h +++ b/Descriptors/JSONDescriptor.h @@ -115,9 +115,8 @@ class JSONDescriptor : public BaseDescriptor { http::Reply & reply ) { facade = f; - reply.content.push_back( - "{\"status\":" - ); + reply.content.push_back("{"); + reply.content.push_back("\"status\":"); if(INT_MAX == raw_route.lengthOfShortestPath) { //We do not need to do much, if there is no route ;-) diff --git a/Include/osrm/RouteParameters.h b/Include/osrm/RouteParameters.h index b35a0cf60bf..97fff384e0a 100644 --- a/Include/osrm/RouteParameters.h +++ b/Include/osrm/RouteParameters.h @@ -45,6 +45,7 @@ struct RouteParameters { geometry(true), compression(true), deprecatedAPI(false), + exec_time(false), checkSum(-1) { } @@ -54,6 +55,7 @@ struct RouteParameters { bool geometry; bool compression; bool deprecatedAPI; + bool exec_time; unsigned checkSum; std::string service; std::string outputFormat; @@ -76,6 +78,10 @@ struct RouteParameters { deprecatedAPI = true; } + void setExecTimeFlag(const bool b) { + exec_time = b; + } + void setChecksum(const unsigned c) { checkSum = c; } diff --git a/Plugins/NearestPlugin.h b/Plugins/NearestPlugin.h index 5a4bcbab72e..b516a9c6994 100644 --- a/Plugins/NearestPlugin.h +++ b/Plugins/NearestPlugin.h @@ -31,6 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BasePlugin.h" #include "../DataStructures/PhantomNodes.h" #include "../Util/StringUtil.h" +#include "../Util/TimingUtil.h" #include @@ -65,6 +66,7 @@ class NearestPlugin : public BasePlugin { return; } + TimeMeasurement exec_time; PhantomNode result; facade->FindPhantomNodeForCoordinate( routeParameters.coordinates[0], @@ -72,6 +74,8 @@ class NearestPlugin : public BasePlugin { routeParameters.zoomLevel ); + int64_t time_ms = exec_time.toNowInMs(); + std::string temp_string; //json @@ -81,7 +85,12 @@ class NearestPlugin : public BasePlugin { } reply.status = http::Reply::ok; - reply.content.push_back("{\"status\":"); + reply.content.push_back("{"); + if (routeParameters.exec_time) { + int64ToString(time_ms, temp_string); + reply.content.push_back("\"exec_time_ms\":" + temp_string + ","); + } + reply.content.push_back("\"status\":"); if(UINT_MAX != result.edgeBasedNode) { reply.content.push_back("0,"); } else { diff --git a/Plugins/ViaRoutePlugin.h b/Plugins/ViaRoutePlugin.h index 6f2880e0433..ef42353b02b 100644 --- a/Plugins/ViaRoutePlugin.h +++ b/Plugins/ViaRoutePlugin.h @@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../Descriptors/JSONDescriptor.h" #include "../Util/SimpleLogger.h" #include "../Util/StringUtil.h" +#include "../Util/TimingUtil.h" #include @@ -81,6 +82,7 @@ class ViaRoutePlugin : public BasePlugin { return; } + TimeMeasurement exec_time; RawRouteData rawRoute; rawRoute.checkSum = facade->GetCheckSum(); const bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum); @@ -156,17 +158,16 @@ class ViaRoutePlugin : public BasePlugin { descriptorConfig.geometry = routeParameters.geometry; descriptorConfig.encode_geometry = routeParameters.compression; + std::string exec_time_token; switch(descriptorType){ - case 0: - desc = new JSONDescriptor(); - - break; case 1: desc = new GPXDescriptor(); - + exec_time_token = ""; break; + case 0: default: desc = new JSONDescriptor(); + exec_time_token = "{"; break; } @@ -177,6 +178,25 @@ class ViaRoutePlugin : public BasePlugin { desc->SetConfig(descriptorConfig); desc->Run(rawRoute, phantomNodes, facade, reply); + + if (routeParameters.exec_time) { + int64_t time_ms = exec_time.toNowInMs(); + std::vector::iterator it = reply.content.begin(); + for (; it != reply.content.end(); ++it) { + if (0 == (*it).compare(0, exec_time_token.size(), exec_time_token)) { + break; // we have found place to insert exec time metric + } + } + if (it != reply.content.end()) { + std::string temp_string; + int64ToString(time_ms, temp_string); + reply.content.insert(++it, (1 == descriptorType)? + "" + temp_string + "" : "\"exec_time_ms\":" + temp_string + "," + ); + } else { + SimpleLogger().Write(logDEBUG) << "Can't find place to insert exec time metric"; + } + } if("" != routeParameters.jsonpParameter) { reply.content.push_back(")\n"); } diff --git a/Server/APIGrammar.h b/Server/APIGrammar.h index f377e6f1006..ce4e345b4d8 100644 --- a/Server/APIGrammar.h +++ b/Server/APIGrammar.h @@ -38,7 +38,7 @@ template struct APIGrammar : qi::grammar { APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) { api_call = qi::lit('/') >> string[boost::bind(&HandlerT::setService, handler, ::_1)] >> *(query); - query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API) ) ; + query = ('?') >> (+(zoom | output | jsonp | checksum | location | hint | cmp | language | instruction | geometry | alt_route | old_API | exec_time) ) ; zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)]; output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)]; @@ -52,6 +52,7 @@ struct APIGrammar : qi::grammar { language = (-qi::lit('&')) >> qi::lit("hl") >> '=' >> string[boost::bind(&HandlerT::setLanguage, handler, ::_1)]; alt_route = (-qi::lit('&')) >> qi::lit("alt") >> '=' >> qi::bool_[boost::bind(&HandlerT::setAlternateRouteFlag, handler, ::_1)]; old_API = (-qi::lit('&')) >> qi::lit("geomformat") >> '=' >> string[boost::bind(&HandlerT::setDeprecatedAPIFlag, handler, ::_1)]; + exec_time = (-qi::lit('&')) >> qi::lit("exec_time") >> '=' >> qi::bool_[boost::bind(&HandlerT::setExecTimeFlag, handler, ::_1)]; string = +(qi::char_("a-zA-Z")); stringwithDot = +(qi::char_("a-zA-Z0-9_.-")); @@ -61,7 +62,7 @@ struct APIGrammar : qi::grammar { qi::rule api_call, query; qi::rule service, zoom, output, string, jsonp, checksum, location, hint, stringwithDot, stringwithPercent, language, instruction, geometry, - cmp, alt_route, old_API; + cmp, alt_route, old_API, exec_time; HandlerT * handler; }; diff --git a/Util/TimingUtil.h b/Util/TimingUtil.h index 290d37799f9..7d36d601021 100644 --- a/Util/TimingUtil.h +++ b/Util/TimingUtil.h @@ -28,6 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef TIMINGUTIL_H_ #define TIMINGUTIL_H_ +#include "../typedefs.h" + +#include + // excluded as this requires boost 1.47 (for now) // #include // #include @@ -68,4 +72,25 @@ static inline double get_timestamp() { return double(tp.tv_sec) + tp.tv_usec / 1000000.; } +class TimeMeasurement { +public: + TimeMeasurement() throw() { fromNow(); } + inline void fromNow() throw() { + m_from = boost::posix_time::microsec_clock::local_time(); + } + // get time period from the fromNow() func. calling to now in milliseconds + inline int64_t toNowInMs() const throw() { + boost::posix_time::time_duration diff = boost::posix_time::microsec_clock::local_time() - m_from; + return diff.total_milliseconds(); + } + // get time period from the fromNow() func. calling to now in seconds + inline int64_t toNowInSec() const throw() { + boost::posix_time::time_duration diff = boost::posix_time::microsec_clock::local_time() - m_from; + return diff.total_seconds(); + } + +private: + boost::posix_time::ptime m_from; +}; + #endif /* TIMINGUTIL_H_ */