requeststats.js 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. // Copyright 2013 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Static utilities for collecting stats associated with
  16. * ChannelRequest.
  17. *
  18. * @visibility {:internal}
  19. * @visibility {:legacy_users}
  20. */
  21. goog.provide('goog.labs.net.webChannel.requestStats');
  22. goog.provide('goog.labs.net.webChannel.requestStats.Event');
  23. goog.provide('goog.labs.net.webChannel.requestStats.ServerReachability');
  24. goog.provide('goog.labs.net.webChannel.requestStats.ServerReachabilityEvent');
  25. goog.provide('goog.labs.net.webChannel.requestStats.Stat');
  26. goog.provide('goog.labs.net.webChannel.requestStats.StatEvent');
  27. goog.provide('goog.labs.net.webChannel.requestStats.TimingEvent');
  28. goog.require('goog.events.Event');
  29. goog.require('goog.events.EventTarget');
  30. goog.scope(function() {
  31. var requestStats = goog.labs.net.webChannel.requestStats;
  32. /**
  33. * Events fired.
  34. * @const
  35. */
  36. requestStats.Event = {};
  37. /**
  38. * Singleton event target for firing stat events
  39. * @type {goog.events.EventTarget}
  40. * @private
  41. */
  42. requestStats.statEventTarget_ = new goog.events.EventTarget();
  43. /**
  44. * The type of event that occurs every time some information about how reachable
  45. * the server is is discovered.
  46. */
  47. requestStats.Event.SERVER_REACHABILITY_EVENT = 'serverreachability';
  48. /**
  49. * Types of events which reveal information about the reachability of the
  50. * server.
  51. * @enum {number}
  52. */
  53. requestStats.ServerReachability = {
  54. REQUEST_MADE: 1,
  55. REQUEST_SUCCEEDED: 2,
  56. REQUEST_FAILED: 3,
  57. BACK_CHANNEL_ACTIVITY: 4
  58. };
  59. /**
  60. * Event class for SERVER_REACHABILITY_EVENT.
  61. *
  62. * @param {goog.events.EventTarget} target The stat event target for
  63. the channel.
  64. * @param {requestStats.ServerReachability} reachabilityType
  65. * The reachability event type.
  66. * @constructor
  67. * @extends {goog.events.Event}
  68. */
  69. requestStats.ServerReachabilityEvent = function(target, reachabilityType) {
  70. goog.events.Event.call(
  71. this, requestStats.Event.SERVER_REACHABILITY_EVENT, target);
  72. /**
  73. * @type {requestStats.ServerReachability}
  74. */
  75. this.reachabilityType = reachabilityType;
  76. };
  77. goog.inherits(requestStats.ServerReachabilityEvent, goog.events.Event);
  78. /**
  79. * Notify the channel that a particular fine grained network event has occurred.
  80. * Should be considered package-private.
  81. * @param {requestStats.ServerReachability} reachabilityType
  82. * The reachability event type.
  83. */
  84. requestStats.notifyServerReachabilityEvent = function(reachabilityType) {
  85. var target = requestStats.statEventTarget_;
  86. target.dispatchEvent(
  87. new requestStats.ServerReachabilityEvent(target, reachabilityType));
  88. };
  89. /**
  90. * Stat Event that fires when things of interest happen that may be useful for
  91. * applications to know about for stats or debugging purposes.
  92. */
  93. requestStats.Event.STAT_EVENT = 'statevent';
  94. /**
  95. * Enum that identifies events for statistics that are interesting to track.
  96. * @enum {number}
  97. */
  98. requestStats.Stat = {
  99. /** Event indicating a new connection attempt. */
  100. CONNECT_ATTEMPT: 0,
  101. /** Event indicating a connection error due to a general network problem. */
  102. ERROR_NETWORK: 1,
  103. /**
  104. * Event indicating a connection error that isn't due to a general network
  105. * problem.
  106. */
  107. ERROR_OTHER: 2,
  108. /** Event indicating the start of test stage one. */
  109. TEST_STAGE_ONE_START: 3,
  110. /** Event indicating the start of test stage two. */
  111. TEST_STAGE_TWO_START: 4,
  112. /** Event indicating the first piece of test data was received. */
  113. TEST_STAGE_TWO_DATA_ONE: 5,
  114. /**
  115. * Event indicating that the second piece of test data was received and it was
  116. * received separately from the first.
  117. */
  118. TEST_STAGE_TWO_DATA_TWO: 6,
  119. /** Event indicating both pieces of test data were received simultaneously. */
  120. TEST_STAGE_TWO_DATA_BOTH: 7,
  121. /** Event indicating stage one of the test request failed. */
  122. TEST_STAGE_ONE_FAILED: 8,
  123. /** Event indicating stage two of the test request failed. */
  124. TEST_STAGE_TWO_FAILED: 9,
  125. /**
  126. * Event indicating that a buffering proxy is likely between the client and
  127. * the server.
  128. */
  129. PROXY: 10,
  130. /**
  131. * Event indicating that no buffering proxy is likely between the client and
  132. * the server.
  133. */
  134. NOPROXY: 11,
  135. /** Event indicating an unknown SID error. */
  136. REQUEST_UNKNOWN_SESSION_ID: 12,
  137. /** Event indicating a bad status code was received. */
  138. REQUEST_BAD_STATUS: 13,
  139. /** Event indicating incomplete data was received */
  140. REQUEST_INCOMPLETE_DATA: 14,
  141. /** Event indicating bad data was received */
  142. REQUEST_BAD_DATA: 15,
  143. /** Event indicating no data was received when data was expected. */
  144. REQUEST_NO_DATA: 16,
  145. /** Event indicating a request timeout. */
  146. REQUEST_TIMEOUT: 17,
  147. /**
  148. * Event indicating that the server never received our hanging GET and so it
  149. * is being retried.
  150. */
  151. BACKCHANNEL_MISSING: 18,
  152. /**
  153. * Event indicating that we have determined that our hanging GET is not
  154. * receiving data when it should be. Thus it is dead dead and will be retried.
  155. */
  156. BACKCHANNEL_DEAD: 19,
  157. /**
  158. * The browser declared itself offline during the lifetime of a request, or
  159. * was offline when a request was initially made.
  160. */
  161. BROWSER_OFFLINE: 20
  162. };
  163. /**
  164. * Event class for STAT_EVENT.
  165. *
  166. * @param {goog.events.EventTarget} eventTarget The stat event target for
  167. the channel.
  168. * @param {requestStats.Stat} stat The stat.
  169. * @constructor
  170. * @extends {goog.events.Event}
  171. */
  172. requestStats.StatEvent = function(eventTarget, stat) {
  173. goog.events.Event.call(this, requestStats.Event.STAT_EVENT, eventTarget);
  174. /**
  175. * The stat
  176. * @type {requestStats.Stat}
  177. */
  178. this.stat = stat;
  179. };
  180. goog.inherits(requestStats.StatEvent, goog.events.Event);
  181. /**
  182. * Returns the singleton event target for stat events.
  183. * @return {goog.events.EventTarget} The event target for stat events.
  184. */
  185. requestStats.getStatEventTarget = function() {
  186. return requestStats.statEventTarget_;
  187. };
  188. /**
  189. * Helper function to call the stat event callback.
  190. * @param {requestStats.Stat} stat The stat.
  191. */
  192. requestStats.notifyStatEvent = function(stat) {
  193. var target = requestStats.statEventTarget_;
  194. target.dispatchEvent(new requestStats.StatEvent(target, stat));
  195. };
  196. /**
  197. * An event that fires when POST requests complete successfully, indicating
  198. * the size of the POST and the round trip time.
  199. */
  200. requestStats.Event.TIMING_EVENT = 'timingevent';
  201. /**
  202. * Event class for requestStats.Event.TIMING_EVENT
  203. *
  204. * @param {goog.events.EventTarget} target The stat event target for
  205. the channel.
  206. * @param {number} size The number of characters in the POST data.
  207. * @param {number} rtt The total round trip time from POST to response in MS.
  208. * @param {number} retries The number of times the POST had to be retried.
  209. * @constructor
  210. * @extends {goog.events.Event}
  211. */
  212. requestStats.TimingEvent = function(target, size, rtt, retries) {
  213. goog.events.Event.call(this, requestStats.Event.TIMING_EVENT, target);
  214. /**
  215. * @type {number}
  216. */
  217. this.size = size;
  218. /**
  219. * @type {number}
  220. */
  221. this.rtt = rtt;
  222. /**
  223. * @type {number}
  224. */
  225. this.retries = retries;
  226. };
  227. goog.inherits(requestStats.TimingEvent, goog.events.Event);
  228. /**
  229. * Helper function to notify listeners about POST request performance.
  230. *
  231. * @param {number} size Number of characters in the POST data.
  232. * @param {number} rtt The amount of time from POST start to response.
  233. * @param {number} retries The number of times the POST had to be retried.
  234. */
  235. requestStats.notifyTimingEvent = function(size, rtt, retries) {
  236. var target = requestStats.statEventTarget_;
  237. target.dispatchEvent(
  238. new requestStats.TimingEvent(target, size, rtt, retries));
  239. };
  240. /**
  241. * Allows the application to set an execution hooks for when a channel
  242. * starts processing requests. This is useful to track timing or logging
  243. * special information. The function takes no parameters and return void.
  244. * @param {Function} startHook The function for the start hook.
  245. */
  246. requestStats.setStartThreadExecutionHook = function(startHook) {
  247. requestStats.startExecutionHook_ = startHook;
  248. };
  249. /**
  250. * Allows the application to set an execution hooks for when a channel
  251. * stops processing requests. This is useful to track timing or logging
  252. * special information. The function takes no parameters and return void.
  253. * @param {Function} endHook The function for the end hook.
  254. */
  255. requestStats.setEndThreadExecutionHook = function(endHook) {
  256. requestStats.endExecutionHook_ = endHook;
  257. };
  258. /**
  259. * Application provided execution hook for the start hook.
  260. *
  261. * @type {Function}
  262. * @private
  263. */
  264. requestStats.startExecutionHook_ = function() {};
  265. /**
  266. * Application provided execution hook for the end hook.
  267. *
  268. * @type {Function}
  269. * @private
  270. */
  271. requestStats.endExecutionHook_ = function() {};
  272. /**
  273. * Helper function to call the start hook
  274. */
  275. requestStats.onStartExecution = function() {
  276. requestStats.startExecutionHook_();
  277. };
  278. /**
  279. * Helper function to call the end hook
  280. */
  281. requestStats.onEndExecution = function() {
  282. requestStats.endExecutionHook_();
  283. };
  284. /**
  285. * Wrapper around SafeTimeout which calls the start and end execution hooks
  286. * with a try...finally block.
  287. * @param {Function} fn The callback function.
  288. * @param {number} ms The time in MS for the timer.
  289. * @return {number} The ID of the timer.
  290. */
  291. requestStats.setTimeout = function(fn, ms) {
  292. if (!goog.isFunction(fn)) {
  293. throw Error('Fn must not be null and must be a function');
  294. }
  295. return goog.global.setTimeout(function() {
  296. requestStats.onStartExecution();
  297. try {
  298. fn();
  299. } finally {
  300. requestStats.onEndExecution();
  301. }
  302. }, ms);
  303. };
  304. }); // goog.scope