blob: 5711da7c28393004e086f5c3842e358f8637c4c1 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// 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.
//
////////////////////////////////////////////////////////////////////////////////
package mx.messaging.messages
{
import mx.messaging.messages.MessagePerformanceInfo;
/**
* The MessagePerformanceUtils utility class is used to retrieve various metrics about
* the sizing and timing of a message sent from a client to the server and its
* response message, as well as pushed messages from the server to the client.
* Metrics are gathered when corresponding properties on the channel used are enabled:
* <record-message-times> denotes capturing of timing information,
* <record-message-sizes> denotes capturing of sizing information.
*
* <p>You can then use methods of this utility class to retrieve various performance information
* about the message that you have just received.</p>
*
* <p>When these metrics are enabled an instance of this class should be created from
* a response, acknowledgement, or message handler using code such as below: </p>
*
* <pre>
* var mpiutil:MessagePerformanceUtils = new MessagePerformanceUtils(event.message);
* </pre>
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*
* @royalesuppresspublicvarwarning
*/
public class MessagePerformanceUtils
{
/**
* @private
*
* Information about the original message sent out by the client
*/
public var mpii:MessagePerformanceInfo;
/**
* @private
*
* Information about the response message sent back to the client
*/
public var mpio:MessagePerformanceInfo;
/**
* @private
*
* If this is a pushed message, information about the original message
* that caused the push
*/
public var mpip:MessagePerformanceInfo;
/**
* @private
*
* Header for MPI of original message sent by client
*/
public static const MPI_HEADER_IN:String = "DSMPII";
/**
* @private
*
* Header for MPI of response message sent to the client
*/
public static const MPI_HEADER_OUT:String = "DSMPIO";
/**
* @private
*
* Header for MPI of a message that caused a pushed message
*/
public static const MPI_HEADER_PUSH:String = "DSMPIP";
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor
*
* Creates an MPUtils instance with information from the MPI headers
* of the passed in message
*
* @param message The message whose MPI headers will be used in retrieving
* MPI information
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function MessagePerformanceUtils(message:Object):void
{
super();
this.mpii=message.headers[MPI_HEADER_IN] as MessagePerformanceInfo;
this.mpio=message.headers[MPI_HEADER_OUT] as MessagePerformanceInfo;
// it is possible that if not all participants have mpi enabled we might be missing parts here
if (mpio == null || (mpii == null && message.headers[MPI_HEADER_PUSH] == null))
{
throw new Error("Message is missing MPI headers. Verify that all participants have it enabled.");
}
if (pushedMessageFlag)
this.mpip = message.headers[MPI_HEADER_PUSH] as MessagePerformanceInfo;
}
//--------------------------------------------------------------------------
//
// Public Methods
//
//--------------------------------------------------------------------------
/**
* Time between this client sending a message and receiving a response
* for it from the server
*
* @return Total time in milliseconds
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get totalTime():Number
{
if (mpii == null)
return 0;
else
return mpio.receiveTime - mpii.sendTime;
}
/**
* Time between server receiving the client message and either the time
* the server responded to the received message or had the pushed message ready
* to be sent to the receiving client.
*
* @return Server processing time in milliseconds
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get serverProcessingTime():Number
{
if (pushedMessageFlag)
{
return mpip.serverPrePushTime - mpip.receiveTime;
}
else
{
return mpio.sendTime - mpii.receiveTime;
}
}
/**
* Time between server receiving the client message and the server beginning to push
* messages out to other clients as a result of the original message.
*
* @return Server pre-push processing time in milliseconds
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get serverPrePushTime():Number
{
if (mpii == null)
return 0;
if (mpii.serverPrePushTime == 0)
return serverProcessingTime;
return mpii.serverPrePushTime - mpii.receiveTime;
}
/**
* Time spent in the adapter associated with the destination for this message before
* either the response to the message was ready or the message had been prepared
* to be pushed to the receiving client.
*
* @return Server adapter processing time in milliseconds
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get serverAdapterTime():Number
{
if (pushedMessageFlag)
{
if (mpip == null)
return 0;
if (mpip.serverPreAdapterTime == 0 || mpip.serverPostAdapterTime == 0)
return 0;
return mpip.serverPostAdapterTime - mpip.serverPreAdapterTime;
}
else
{
if (mpii == null)
return 0;
if (mpii.serverPreAdapterTime == 0 || mpii.serverPostAdapterTime == 0)
return 0;
return mpii.serverPostAdapterTime - mpii.serverPreAdapterTime;
}
}
/**
* Time spent in a module invoked from the adapter associated with the destination for this message
* but external to it, before either the response to the message was ready or the message had been
* prepared to be pushed to the receiving client.
*
* @return Server adapter-external processing time in milliseconds
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get serverAdapterExternalTime():Number
{
if (pushedMessageFlag)
{
if (mpip == null)
return 0;
if (mpip.serverPreAdapterExternalTime == 0 || mpip.serverPostAdapterExternalTime == 0)
return 0;
return mpip.serverPostAdapterExternalTime - mpip.serverPreAdapterExternalTime;
}
else
{
if (mpii == null)
return 0;
if (mpii.serverPreAdapterExternalTime == 0 || mpii.serverPostAdapterExternalTime == 0)
return 0;
return mpii.serverPostAdapterExternalTime - mpii.serverPreAdapterExternalTime;
}
}
/**
* Time that the message waited on the server after it was ready to be pushed to the client
* but had not yet been polled for.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get serverPollDelay():Number
{
if (mpip == null)
return 0;
if (mpip.serverPrePushTime == 0 || mpio.sendTime == 0)
return 0;
return mpio.sendTime - mpip.serverPrePushTime;
}
/**
* Server processing time spent outside of the adapter associated with the destination of this message.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get serverNonAdapterTime():Number
{
return serverProcessingTime - serverAdapterTime;
}
/**
* The network round trip time for a client message and the server response to it,
* calculated by the difference between total time and server processing time.
*
* @return Network round trip time in milliseconds
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get networkRTT():Number
{
if (!pushedMessageFlag)
return totalTime - serverProcessingTime;
else
return 0;
}
/**
* Timestamp in milliseconds since epoch of when the server sent a response message back
* to the client.
*
* @return Timestamp in milliseconds since epoch
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get serverSendTime():Number
{
return mpio.sendTime;
}
/**
* Timestamp in milliseconds since epoch of when the client received response message from
* the server.
*
* @return Timestamp in milliseconds since epoch
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get clientReceiveTime():Number
{
return mpio.receiveTime;
}
/**
* The size of the original client message as measured during deserialization by the server
* endpoint.
*
* @return Message size in Bytes
*/
public function get messageSize():int
{
if (mpii == null)
return 0;
else
return mpii.messageSize;
}
/**
* The size of the response message sent to the client by the server as measured during serialization
* at the server endpoint.
*
* @return Message size in Bytes
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get responseMessageSize():int
{
return mpio.messageSize;
}
/**
* Returns true if message was pushed to the client and is not a response to a message that
* originated on the client.
*
* @return true if this message was pushed to the client and is not a response to a message that
* originated on the client
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get pushedMessageFlag():Boolean
{
return mpio.pushedFlag;
}
/**
* Only populated in the case of a pushed message, this is the time between the push causing client
* sending its message and the push receving client receiving it. Note that the two clients'
* clocks must be in sync for this to be meaningful.
*
* @return Total push time in milliseconds
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get totalPushTime():Number
{
return clientReceiveTime - originatingMessageSentTime - pushedOverheadTime;
}
/**
* Only populated in the case of a pushed message, this is the network time between
* the server pushing the message and the client receiving it. Note that the server
* and client clocks must be in sync for this to be meaningful.
*
* @return One way server push time in milliseconds
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get pushOneWayTime():Number
{
return clientReceiveTime - serverSendTime;
}
/**
* Only populated in the case of a pushed message, timestamp in milliseconds since epoch of
* when the client that caused a push message sent its message.
*
* @return Timestamp in milliseconds since epoch
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get originatingMessageSentTime():Number
{
return mpip.sendTime;
}
/**
* Only populated in the case of a pushed message, size in Bytes of the message that originally
* caused this pushed message.
*
* @return Pushed causer message size in Bytes
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function get originatingMessageSize():Number
{
return mpip.messageSize;
}
/**
* Returns a summary of all information available in MPI.
* For example:
*
* <pre>
* var mpiutil:MessagePerformanceUtils = new MessagePerformanceUtils(message);
* Alert.show(mpiutil.prettyPrint(), "MPI Output", Alert.NONMODAL);
* </pre>
*
* @return String containing a summary of all information available in MPI
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion BlazeDS 4
* @productversion LCDS 3
*/
public function prettyPrint():String
{
var alertString:String = new String("");
if (messageSize != 0)
alertString +="Original message size(B): " + messageSize + "\n";
if (responseMessageSize != 0)
alertString +="Response message size(B): " + responseMessageSize + "\n";
if (totalTime != 0)
alertString +="Total time (s): " + (totalTime / 1000) + "\n";
if (networkRTT != 0)
alertString +="Network Roundtrip time (s): " + (networkRTT / 1000) + "\n";
if (serverProcessingTime != 0)
alertString +="Server processing time (s): " + (serverProcessingTime / 1000) + "\n";
if (serverAdapterTime != 0)
alertString +="Server adapter time (s): " + (serverAdapterTime / 1000) + "\n";
if (serverNonAdapterTime != 0)
alertString +="Server non-adapter time (s): " + (serverNonAdapterTime / 1000) + "\n"
if (serverAdapterExternalTime != 0)
alertString +="Server adapter external time (s): " + (serverAdapterExternalTime / 1000) + "\n";
if (pushedMessageFlag)
{
alertString += "PUSHED MESSAGE INFORMATION:\n";
if (totalPushTime != 0)
alertString += "Total push time (s): " + (totalPushTime / 1000) + "\n";
if (pushOneWayTime != 0)
alertString += "Push one way time (s): " + (pushOneWayTime / 1000) + "\n";
if (originatingMessageSize != 0)
alertString += "Originating Message size (B): " + originatingMessageSize + "\n";
if (serverPollDelay != 0)
alertString +="Server poll delay (s): " + (serverPollDelay / 1000) + "\n";
}
return alertString;
}
//--------------------------------------------------------------------------
//
// Private Methods
//
//--------------------------------------------------------------------------
/**
* @private
*
* Overhead time in milliseconds for processing of the push causer message
*/
private function get pushedOverheadTime():Number
{
return mpip.overheadTime;
}
}
}