diff --git a/Include/osrm/RouteParameters.h b/Include/osrm/RouteParameters.h index b35a0cf60bf..f95d7aa651f 100644 --- a/Include/osrm/RouteParameters.h +++ b/Include/osrm/RouteParameters.h @@ -45,6 +45,7 @@ struct RouteParameters { geometry(true), compression(true), deprecatedAPI(false), + measurement(false), checkSum(-1) { } @@ -54,6 +55,7 @@ struct RouteParameters { bool geometry; bool compression; bool deprecatedAPI; + bool measurement; unsigned checkSum; std::string service; std::string outputFormat; @@ -76,6 +78,10 @@ struct RouteParameters { deprecatedAPI = true; } + void setMeasurementFlag(const bool b) { + measurement = b; + } + void setChecksum(const unsigned c) { checkSum = c; } diff --git a/Plugins/NearestPlugin.h b/Plugins/NearestPlugin.h index 5a4bcbab72e..ab4e3917aac 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/TimeMeasurement.h" #include @@ -65,6 +66,7 @@ class NearestPlugin : public BasePlugin { return; } + TimeMeasurement measure; PhantomNode result; facade->FindPhantomNodeForCoordinate( routeParameters.coordinates[0], @@ -72,6 +74,8 @@ class NearestPlugin : public BasePlugin { routeParameters.zoomLevel ); + int64_t time_ms = measure.toNow(); + std::string temp_string; //json @@ -87,6 +91,10 @@ class NearestPlugin : public BasePlugin { } else { reply.content.push_back("207,"); } + if (routeParameters.measurement) { + int64ToString(time_ms, temp_string); + reply.content.push_back("\"measurement_ms\":" + temp_string + ","); + } reply.content.push_back("\"mapped_coordinate\":["); if(UINT_MAX != result.edgeBasedNode) { FixedPointCoordinate::convertInternalLatLonToString(result.location.lat, temp_string); diff --git a/Plugins/ViaRoutePlugin.h b/Plugins/ViaRoutePlugin.h index 6f2880e0433..9dc6a73f273 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/TimeMeasurement.h" #include @@ -46,6 +47,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +static bool IsTransactionStr (const std::string &s) { + static std::string trans("transactionId"); + if (s.size() < trans.size()) { + return false; + } + return (0 == s.compare(1, trans.size(), trans)); +} + template class ViaRoutePlugin : public BasePlugin { private: @@ -81,6 +90,7 @@ class ViaRoutePlugin : public BasePlugin { return; } + TimeMeasurement measure; RawRouteData rawRoute; rawRoute.checkSum = facade->GetCheckSum(); const bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum); @@ -177,6 +187,16 @@ class ViaRoutePlugin : public BasePlugin { desc->SetConfig(descriptorConfig); desc->Run(rawRoute, phantomNodes, facade, reply); + + if (routeParameters.measurement) { + int64_t time_ms = measure.toNow(); + std::vector::iterator it = std::find_if(reply.content.begin(), reply.content.end(), IsTransactionStr); + if (it != reply.content.end()) { + std::string temp_string; + int64ToString(time_ms, temp_string); + reply.content.insert(it, "\"measurement_ms\":" + temp_string + ","); + } + } if("" != routeParameters.jsonpParameter) { reply.content.push_back(")\n"); } diff --git a/Server/APIGrammar.h b/Server/APIGrammar.h index f377e6f1006..9f37208a18b 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 | measurement) ) ; 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)]; + measurement = (-qi::lit('&')) >> qi::lit("measurement") >> '=' >> qi::bool_[boost::bind(&HandlerT::setMeasurementFlag, 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, measurement; HandlerT * handler; }; diff --git a/Util/TimeMeasurement.h b/Util/TimeMeasurement.h new file mode 100644 index 00000000000..044a6d0835b --- /dev/null +++ b/Util/TimeMeasurement.h @@ -0,0 +1,51 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TIME_MEASUREMENT_H_ +#define TIME_MEASUREMENT_H_ + +#include "../typedefs.h" + +#include + +class TimeMeasurement { +public: + TimeMeasurement() throw() { + fromNow(); + } + inline void fromNow() throw() { + _from = boost::posix_time::microsec_clock::local_time(); + } + inline int64_t toNow() const throw() { + boost::posix_time::time_duration diff = boost::posix_time::microsec_clock::local_time() - _from; + return diff.total_milliseconds(); + } +private: + boost::posix_time::ptime _from; +}; + +#endif // TIME_MEASUREMENT_H_