| // Copyright 2013 The Closure Library Authors. All Rights Reserved. |
| // |
| // Licensed 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. |
| |
| /** |
| * @fileoverview Static utilities for collecting stats associated with |
| * ChannelRequest. |
| * |
| * @visibility {:internal} |
| */ |
| |
| |
| goog.provide('goog.labs.net.webChannel.requestStats'); |
| goog.provide('goog.labs.net.webChannel.requestStats.Event'); |
| goog.provide('goog.labs.net.webChannel.requestStats.ServerReachability'); |
| goog.provide('goog.labs.net.webChannel.requestStats.ServerReachabilityEvent'); |
| goog.provide('goog.labs.net.webChannel.requestStats.Stat'); |
| goog.provide('goog.labs.net.webChannel.requestStats.StatEvent'); |
| goog.provide('goog.labs.net.webChannel.requestStats.TimingEvent'); |
| |
| goog.require('goog.events.Event'); |
| goog.require('goog.events.EventTarget'); |
| |
| |
| goog.scope(function() { |
| var requestStats = goog.labs.net.webChannel.requestStats; |
| |
| |
| /** |
| * Events fired. |
| * @const |
| */ |
| requestStats.Event = {}; |
| |
| |
| /** |
| * Singleton event target for firing stat events |
| * @type {goog.events.EventTarget} |
| * @private |
| */ |
| requestStats.statEventTarget_ = new goog.events.EventTarget(); |
| |
| |
| /** |
| * The type of event that occurs every time some information about how reachable |
| * the server is is discovered. |
| */ |
| requestStats.Event.SERVER_REACHABILITY_EVENT = 'serverreachability'; |
| |
| |
| /** |
| * Types of events which reveal information about the reachability of the |
| * server. |
| * @enum {number} |
| */ |
| requestStats.ServerReachability = { |
| REQUEST_MADE: 1, |
| REQUEST_SUCCEEDED: 2, |
| REQUEST_FAILED: 3, |
| BACK_CHANNEL_ACTIVITY: 4 |
| }; |
| |
| |
| |
| /** |
| * Event class for SERVER_REACHABILITY_EVENT. |
| * |
| * @param {goog.events.EventTarget} target The stat event target for |
| the channel. |
| * @param {requestStats.ServerReachability} reachabilityType |
| * The reachability event type. |
| * @constructor |
| * @extends {goog.events.Event} |
| */ |
| requestStats.ServerReachabilityEvent = function(target, reachabilityType) { |
| goog.events.Event.call(this, |
| requestStats.Event.SERVER_REACHABILITY_EVENT, target); |
| |
| /** |
| * @type {requestStats.ServerReachability} |
| */ |
| this.reachabilityType = reachabilityType; |
| }; |
| goog.inherits(requestStats.ServerReachabilityEvent, goog.events.Event); |
| |
| |
| /** |
| * Notify the channel that a particular fine grained network event has occurred. |
| * Should be considered package-private. |
| * @param {requestStats.ServerReachability} reachabilityType |
| * The reachability event type. |
| */ |
| requestStats.notifyServerReachabilityEvent = function(reachabilityType) { |
| var target = requestStats.statEventTarget_; |
| target.dispatchEvent( |
| new requestStats.ServerReachabilityEvent(target, reachabilityType)); |
| }; |
| |
| |
| /** |
| * Stat Event that fires when things of interest happen that may be useful for |
| * applications to know about for stats or debugging purposes. |
| */ |
| requestStats.Event.STAT_EVENT = 'statevent'; |
| |
| |
| /** |
| * Enum that identifies events for statistics that are interesting to track. |
| * @enum {number} |
| */ |
| requestStats.Stat = { |
| /** Event indicating a new connection attempt. */ |
| CONNECT_ATTEMPT: 0, |
| |
| /** Event indicating a connection error due to a general network problem. */ |
| ERROR_NETWORK: 1, |
| |
| /** |
| * Event indicating a connection error that isn't due to a general network |
| * problem. |
| */ |
| ERROR_OTHER: 2, |
| |
| /** Event indicating the start of test stage one. */ |
| TEST_STAGE_ONE_START: 3, |
| |
| /** Event indicating the start of test stage two. */ |
| TEST_STAGE_TWO_START: 4, |
| |
| /** Event indicating the first piece of test data was received. */ |
| TEST_STAGE_TWO_DATA_ONE: 5, |
| |
| /** |
| * Event indicating that the second piece of test data was received and it was |
| * recieved separately from the first. |
| */ |
| TEST_STAGE_TWO_DATA_TWO: 6, |
| |
| /** Event indicating both pieces of test data were received simultaneously. */ |
| TEST_STAGE_TWO_DATA_BOTH: 7, |
| |
| /** Event indicating stage one of the test request failed. */ |
| TEST_STAGE_ONE_FAILED: 8, |
| |
| /** Event indicating stage two of the test request failed. */ |
| TEST_STAGE_TWO_FAILED: 9, |
| |
| /** |
| * Event indicating that a buffering proxy is likely between the client and |
| * the server. |
| */ |
| PROXY: 10, |
| |
| /** |
| * Event indicating that no buffering proxy is likely between the client and |
| * the server. |
| */ |
| NOPROXY: 11, |
| |
| /** Event indicating an unknown SID error. */ |
| REQUEST_UNKNOWN_SESSION_ID: 12, |
| |
| /** Event indicating a bad status code was received. */ |
| REQUEST_BAD_STATUS: 13, |
| |
| /** Event indicating incomplete data was received */ |
| REQUEST_INCOMPLETE_DATA: 14, |
| |
| /** Event indicating bad data was received */ |
| REQUEST_BAD_DATA: 15, |
| |
| /** Event indicating no data was received when data was expected. */ |
| REQUEST_NO_DATA: 16, |
| |
| /** Event indicating a request timeout. */ |
| REQUEST_TIMEOUT: 17, |
| |
| /** |
| * Event indicating that the server never received our hanging GET and so it |
| * is being retried. |
| */ |
| BACKCHANNEL_MISSING: 18, |
| |
| /** |
| * Event indicating that we have determined that our hanging GET is not |
| * receiving data when it should be. Thus it is dead dead and will be retried. |
| */ |
| BACKCHANNEL_DEAD: 19, |
| |
| /** |
| * The browser declared itself offline during the lifetime of a request, or |
| * was offline when a request was initially made. |
| */ |
| BROWSER_OFFLINE: 20 |
| }; |
| |
| |
| |
| /** |
| * Event class for STAT_EVENT. |
| * |
| * @param {goog.events.EventTarget} eventTarget The stat event target for |
| the channel. |
| * @param {requestStats.Stat} stat The stat. |
| * @constructor |
| * @extends {goog.events.Event} |
| */ |
| requestStats.StatEvent = function(eventTarget, stat) { |
| goog.events.Event.call(this, requestStats.Event.STAT_EVENT, eventTarget); |
| |
| /** |
| * The stat |
| * @type {requestStats.Stat} |
| */ |
| this.stat = stat; |
| |
| }; |
| goog.inherits(requestStats.StatEvent, goog.events.Event); |
| |
| |
| /** |
| * Returns the singleton event target for stat events. |
| * @return {goog.events.EventTarget} The event target for stat events. |
| */ |
| requestStats.getStatEventTarget = function() { |
| return requestStats.statEventTarget_; |
| }; |
| |
| |
| /** |
| * Helper function to call the stat event callback. |
| * @param {requestStats.Stat} stat The stat. |
| */ |
| requestStats.notifyStatEvent = function(stat) { |
| var target = requestStats.statEventTarget_; |
| target.dispatchEvent(new requestStats.StatEvent(target, stat)); |
| }; |
| |
| |
| /** |
| * An event that fires when POST requests complete successfully, indicating |
| * the size of the POST and the round trip time. |
| */ |
| requestStats.Event.TIMING_EVENT = 'timingevent'; |
| |
| |
| |
| /** |
| * Event class for requestStats.Event.TIMING_EVENT |
| * |
| * @param {goog.events.EventTarget} target The stat event target for |
| the channel. |
| * @param {number} size The number of characters in the POST data. |
| * @param {number} rtt The total round trip time from POST to response in MS. |
| * @param {number} retries The number of times the POST had to be retried. |
| * @constructor |
| * @extends {goog.events.Event} |
| */ |
| requestStats.TimingEvent = function(target, size, rtt, retries) { |
| goog.events.Event.call(this, |
| requestStats.Event.TIMING_EVENT, target); |
| |
| /** |
| * @type {number} |
| */ |
| this.size = size; |
| |
| /** |
| * @type {number} |
| */ |
| this.rtt = rtt; |
| |
| /** |
| * @type {number} |
| */ |
| this.retries = retries; |
| |
| }; |
| goog.inherits(requestStats.TimingEvent, goog.events.Event); |
| |
| |
| /** |
| * Helper function to notify listeners about POST request performance. |
| * |
| * @param {number} size Number of characters in the POST data. |
| * @param {number} rtt The amount of time from POST start to response. |
| * @param {number} retries The number of times the POST had to be retried. |
| */ |
| requestStats.notifyTimingEvent = function(size, rtt, retries) { |
| var target = requestStats.statEventTarget_; |
| target.dispatchEvent( |
| new requestStats.TimingEvent( |
| target, size, rtt, retries)); |
| }; |
| |
| |
| /** |
| * Allows the application to set an execution hooks for when a channel |
| * starts processing requests. This is useful to track timing or logging |
| * special information. The function takes no parameters and return void. |
| * @param {Function} startHook The function for the start hook. |
| */ |
| requestStats.setStartThreadExecutionHook = function(startHook) { |
| requestStats.startExecutionHook_ = startHook; |
| }; |
| |
| |
| /** |
| * Allows the application to set an execution hooks for when a channel |
| * stops processing requests. This is useful to track timing or logging |
| * special information. The function takes no parameters and return void. |
| * @param {Function} endHook The function for the end hook. |
| */ |
| requestStats.setEndThreadExecutionHook = function(endHook) { |
| requestStats.endExecutionHook_ = endHook; |
| }; |
| |
| |
| /** |
| * Application provided execution hook for the start hook. |
| * |
| * @type {Function} |
| * @private |
| */ |
| requestStats.startExecutionHook_ = function() { }; |
| |
| |
| /** |
| * Application provided execution hook for the end hook. |
| * |
| * @type {Function} |
| * @private |
| */ |
| requestStats.endExecutionHook_ = function() { }; |
| |
| |
| /** |
| * Helper function to call the start hook |
| */ |
| requestStats.onStartExecution = function() { |
| requestStats.startExecutionHook_(); |
| }; |
| |
| |
| /** |
| * Helper function to call the end hook |
| */ |
| requestStats.onEndExecution = function() { |
| requestStats.endExecutionHook_(); |
| }; |
| |
| |
| /** |
| * Wrapper around SafeTimeout which calls the start and end execution hooks |
| * with a try...finally block. |
| * @param {Function} fn The callback function. |
| * @param {number} ms The time in MS for the timer. |
| * @return {number} The ID of the timer. |
| */ |
| requestStats.setTimeout = function(fn, ms) { |
| if (!goog.isFunction(fn)) { |
| throw Error('Fn must not be null and must be a function'); |
| } |
| return goog.global.setTimeout(function() { |
| requestStats.onStartExecution(); |
| try { |
| fn(); |
| } finally { |
| requestStats.onEndExecution(); |
| } |
| }, ms); |
| }; |
| }); // goog.scope |