mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 04:27:41 +00:00
fixes bug 308371 "Add additional instrumentation to Http protocol" patch by LeRoy Krueger (leroyk@attglobal.net), r+sr=darin
This commit is contained in:
parent
135baa7fce
commit
cb43666976
@ -58,6 +58,7 @@ XPIDLSRCS = \
|
||||
nsIHttpEventSink.idl \
|
||||
nsIHttpAuthenticator.idl \
|
||||
nsIHttpAuthManager.idl \
|
||||
nsIHttpActivityObserver.idl \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
153
netwerk/protocol/http/public/nsIHttpActivityObserver.idl
Normal file
153
netwerk/protocol/http/public/nsIHttpActivityObserver.idl
Normal file
@ -0,0 +1,153 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla.
|
||||
*
|
||||
* The Initial Developer of the Original Code is IBM Corporation.
|
||||
* Portions created by IBM Corporation are Copyright (C) 2003
|
||||
* IBM Corporation. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* IBM Corp.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
|
||||
/**
|
||||
* nsIHttpActivityObserver
|
||||
*
|
||||
* This interface provides a way for http activities to be reported
|
||||
* to observers.
|
||||
*/
|
||||
[scriptable, uuid(412880C8-6C36-48d8-BF8F-84F91F892503)]
|
||||
interface nsIHttpActivityObserver : nsISupports
|
||||
{
|
||||
/**
|
||||
* observe activity from the http transport
|
||||
*
|
||||
* @param aHttpChannel
|
||||
* nsISupports interface for the the http channel that
|
||||
* generated this activity
|
||||
* @param aActivityType
|
||||
* The value of this aActivityType will be one of
|
||||
* ACTIVITY_TYPE_SOCKET_TRANSPORT or
|
||||
* ACTIVITY_TYPE_HTTP_TRANSACTION
|
||||
* @param aActivitySubtype
|
||||
* The value of this aActivitySubtype, will be depend
|
||||
* on the value of aActivityType. When aActivityType
|
||||
* is ACTIVITY_TYPE_SOCKET_TRANSPORT
|
||||
* aActivitySubtype will be one of the
|
||||
* nsISocketTransport::STATUS_???? values defined in
|
||||
* nsISocketTransport.idl
|
||||
* OR when aActivityType
|
||||
* is ACTIVITY_TYPE_HTTP_TRANSACTION
|
||||
* aActivitySubtype will be one of the
|
||||
* nsIHttpActivityObserver::ACTIVITY_SUBTYPE_???? values
|
||||
* defined below
|
||||
* @param aTimestamp
|
||||
* microseconds past the epoch of Jan 1, 1970
|
||||
* @param aExtraSizeData
|
||||
* Any extra size data optionally available with
|
||||
* this activity
|
||||
* @param aExtraStringData
|
||||
* Any extra string data optionally available with
|
||||
* this activity
|
||||
*/
|
||||
void observeActivity(in nsISupports aHttpChannel,
|
||||
in PRUint32 aActivityType,
|
||||
in PRUint32 aActivitySubtype,
|
||||
in PRTime aTimestamp,
|
||||
in PRUint64 aExtraSizeData,
|
||||
in ACString aExtraStringData);
|
||||
|
||||
/**
|
||||
* This attribute is true when this interface is active and should
|
||||
* observe http activities. When false, observeActivity() should not
|
||||
* be called.
|
||||
*/
|
||||
readonly attribute boolean isActive;
|
||||
|
||||
const unsigned long ACTIVITY_TYPE_SOCKET_TRANSPORT = 0x0001;
|
||||
const unsigned long ACTIVITY_TYPE_HTTP_TRANSACTION = 0x0002;
|
||||
|
||||
const unsigned long ACTIVITY_SUBTYPE_REQUEST_HEADER = 0x5001;
|
||||
const unsigned long ACTIVITY_SUBTYPE_REQUEST_BODY_SENT = 0x5002;
|
||||
const unsigned long ACTIVITY_SUBTYPE_RESPONSE_START = 0x5003;
|
||||
const unsigned long ACTIVITY_SUBTYPE_RESPONSE_HEADER = 0x5004;
|
||||
const unsigned long ACTIVITY_SUBTYPE_RESPONSE_COMPLETE = 0x5005;
|
||||
const unsigned long ACTIVITY_SUBTYPE_TRANSACTION_CLOSE = 0x5006;
|
||||
|
||||
/**
|
||||
* When aActivityType is ACTIVITY_TYPE_SOCKET_TRANSPORT
|
||||
* and aActivitySubtype is STATUS_SENDING_TO
|
||||
* aExtraSizeData will contain the count of bytes sent
|
||||
* There may be more than one of these activities reported
|
||||
* for a single http transaction, each aExtraSizeData
|
||||
* represents only that portion of the total bytes sent
|
||||
*
|
||||
* When aActivityType is ACTIVITY_TYPE_HTTP_TRANSACTION
|
||||
* and aActivitySubtype is ACTIVITY_SUBTYPE_REQUEST_HEADER
|
||||
* aExtraStringData will contain the text of the header
|
||||
*
|
||||
* When aActivityType is ACTIVITY_TYPE_HTTP_TRANSACTION
|
||||
* and aActivitySubtype is ACTIVITY_SUBTYPE_RESPONSE_HEADER
|
||||
* aExtraStringData will contain the text of the header
|
||||
*
|
||||
* When aActivityType is ACTIVITY_TYPE_HTTP_TRANSACTION
|
||||
* and aActivitySubtype is ACTIVITY_SUBTYPE_RESPONSE_COMPLETE
|
||||
* aExtraSizeData will contain the count of total bytes received
|
||||
*/
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
||||
#define NS_HTTPACTIVITYOBSERVER_TOPIC \
|
||||
"http-activity-observer"
|
||||
|
||||
#define NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID \
|
||||
"@mozilla.org/netwerk/protocol/http/http-activity-distributor;1"
|
||||
|
||||
#define NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT \
|
||||
nsIHttpActivityObserver::ACTIVITY_TYPE_SOCKET_TRANSPORT
|
||||
#define NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION \
|
||||
nsIHttpActivityObserver::ACTIVITY_TYPE_HTTP_TRANSACTION
|
||||
|
||||
#define NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER \
|
||||
nsIHttpActivityObserver::ACTIVITY_SUBTYPE_REQUEST_HEADER
|
||||
#define NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_BODY_SENT \
|
||||
nsIHttpActivityObserver::ACTIVITY_SUBTYPE_REQUEST_BODY_SENT
|
||||
#define NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_START \
|
||||
nsIHttpActivityObserver::ACTIVITY_SUBTYPE_RESPONSE_START
|
||||
#define NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_HEADER \
|
||||
nsIHttpActivityObserver::ACTIVITY_SUBTYPE_RESPONSE_HEADER
|
||||
#define NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_COMPLETE \
|
||||
nsIHttpActivityObserver::ACTIVITY_SUBTYPE_RESPONSE_COMPLETE
|
||||
#define NS_HTTP_ACTIVITY_SUBTYPE_TRANSACTION_CLOSE \
|
||||
nsIHttpActivityObserver::ACTIVITY_SUBTYPE_TRANSACTION_CLOSE
|
||||
|
||||
%}
|
||||
|
@ -58,6 +58,8 @@
|
||||
#include "nsStringStream.h"
|
||||
|
||||
#include "nsComponentManagerUtils.h" // do_CreateInstance
|
||||
#include "nsServiceManagerUtils.h" // do_GetService
|
||||
#include "nsIHttpActivityObserver.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@ -183,6 +185,26 @@ nsHttpTransaction::Init(PRUint8 caps,
|
||||
eventsink, target, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// try to get the nsIHttpActivityObserver distributor
|
||||
mActivityDistributor = do_GetService(NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID, &rv);
|
||||
|
||||
// mActivityDistributor may not be valid
|
||||
if (NS_SUCCEEDED(rv) && mActivityDistributor) {
|
||||
// the service is valid, now check if it is active
|
||||
PRBool active;
|
||||
rv = mActivityDistributor->GetIsActive(&active);
|
||||
if (NS_SUCCEEDED(rv) && active) {
|
||||
// the service is valid and active, gather nsISupports
|
||||
// for the channel that called Init()
|
||||
mChannel = do_QueryInterface(eventsink);
|
||||
LOG(("nsHttpTransaction::Init() " \
|
||||
"mActivityDistributor is active " \
|
||||
"this=%x", this));
|
||||
} else
|
||||
// the interface in valid but not active, so don't use it
|
||||
mActivityDistributor = nsnull;
|
||||
}
|
||||
|
||||
NS_ADDREF(mConnInfo = cinfo);
|
||||
mCallbacks = callbacks;
|
||||
mConsumerTarget = target;
|
||||
@ -214,6 +236,15 @@ nsHttpTransaction::Init(PRUint8 caps,
|
||||
if (!requestBodyHasHeaders || !requestBody)
|
||||
mReqHeaderBuf.AppendLiteral("\r\n");
|
||||
|
||||
// report the request header
|
||||
if (mActivityDistributor)
|
||||
mActivityDistributor->ObserveActivity(
|
||||
mChannel,
|
||||
NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
|
||||
NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER,
|
||||
LL_ZERO, LL_ZERO,
|
||||
mReqHeaderBuf);
|
||||
|
||||
// Create a string stream for the request header buf (the stream holds
|
||||
// a non-owning reference to the request header data, so we MUST keep
|
||||
// mReqHeaderBuf around).
|
||||
@ -308,6 +339,26 @@ nsHttpTransaction::OnTransportStatus(nsresult status, PRUint64 progress)
|
||||
if (status == nsISocketTransport::STATUS_RECEIVING_FROM)
|
||||
return;
|
||||
|
||||
if (mActivityDistributor) {
|
||||
// upon STATUS_WAITING_FOR; report request body sent
|
||||
if ((mHasRequestBody) &&
|
||||
(status == nsISocketTransport::STATUS_WAITING_FOR))
|
||||
mActivityDistributor->ObserveActivity(
|
||||
mChannel,
|
||||
NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
|
||||
NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_BODY_SENT,
|
||||
LL_ZERO, LL_ZERO, EmptyCString());
|
||||
|
||||
// report the status and progress
|
||||
mActivityDistributor->ObserveActivity(
|
||||
mChannel,
|
||||
NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT,
|
||||
NS_STATIC_CAST(PRUint32, status),
|
||||
LL_ZERO,
|
||||
progress,
|
||||
EmptyCString());
|
||||
}
|
||||
|
||||
nsUint64 progressMax;
|
||||
|
||||
if (status == nsISocketTransport::STATUS_SENDING_TO) {
|
||||
@ -481,6 +532,25 @@ nsHttpTransaction::Close(nsresult reason)
|
||||
return;
|
||||
}
|
||||
|
||||
if (mActivityDistributor) {
|
||||
// report the reponse is complete if not already reported
|
||||
if (!mResponseIsComplete)
|
||||
mActivityDistributor->ObserveActivity(
|
||||
mChannel,
|
||||
NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
|
||||
NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_COMPLETE,
|
||||
LL_ZERO,
|
||||
NS_STATIC_CAST(PRUint64, mContentRead.mValue),
|
||||
EmptyCString());
|
||||
|
||||
// report that this transaction is closing
|
||||
mActivityDistributor->ObserveActivity(
|
||||
mChannel,
|
||||
NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
|
||||
NS_HTTP_ACTIVITY_SUBTYPE_TRANSACTION_CLOSE,
|
||||
LL_ZERO, LL_ZERO, EmptyCString());
|
||||
}
|
||||
|
||||
// we must no longer reference the connection! find out if the
|
||||
// connection was being reused before letting it go.
|
||||
PRBool connReused = PR_FALSE;
|
||||
@ -661,6 +731,14 @@ nsHttpTransaction::ParseHead(char *buf,
|
||||
mResponseHead = new nsHttpResponseHead();
|
||||
if (!mResponseHead)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// report that we have a least some of the response
|
||||
if (mActivityDistributor)
|
||||
mActivityDistributor->ObserveActivity(
|
||||
mChannel,
|
||||
NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
|
||||
NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_START,
|
||||
LL_ZERO, LL_ZERO, EmptyCString());
|
||||
}
|
||||
|
||||
// if we don't have a status line and the line buf is empty, then
|
||||
@ -871,6 +949,16 @@ nsHttpTransaction::HandleContent(char *buf,
|
||||
// the transaction is done with a complete response.
|
||||
mTransactionDone = PR_TRUE;
|
||||
mResponseIsComplete = PR_TRUE;
|
||||
|
||||
// report the entire response has arrived
|
||||
if (mActivityDistributor)
|
||||
mActivityDistributor->ObserveActivity(
|
||||
mChannel,
|
||||
NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
|
||||
NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_COMPLETE,
|
||||
LL_ZERO,
|
||||
NS_STATIC_CAST(PRUint64, mContentRead.mValue),
|
||||
EmptyCString());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -897,6 +985,19 @@ nsHttpTransaction::ProcessData(char *buf, PRUint32 count, PRUint32 *countRead)
|
||||
// if buf has some content in it, shift bytes to top of buf.
|
||||
if (count && bytesConsumed)
|
||||
memmove(buf, buf + bytesConsumed, count);
|
||||
|
||||
// report the completed response header
|
||||
if (mActivityDistributor && mResponseHead && mHaveAllHeaders) {
|
||||
nsCAutoString completeResponseHeaders;
|
||||
mResponseHead->Flatten(completeResponseHeaders, PR_FALSE);
|
||||
completeResponseHeaders.AppendLiteral("\r\n");
|
||||
mActivityDistributor->ObserveActivity(
|
||||
mChannel,
|
||||
NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
|
||||
NS_HTTP_ACTIVITY_SUBTYPE_RESPONSE_HEADER,
|
||||
LL_ZERO, LL_ZERO,
|
||||
completeResponseHeaders);
|
||||
}
|
||||
}
|
||||
|
||||
// even though count may be 0, we still want to call HandleContent
|
||||
|
@ -60,6 +60,7 @@ class nsHttpTransaction;
|
||||
class nsHttpRequestHead;
|
||||
class nsHttpResponseHead;
|
||||
class nsHttpChunkedDecoder;
|
||||
class nsIHttpActivityObserver;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpTransaction represents a single HTTP transaction. It is thread-safe,
|
||||
@ -159,6 +160,9 @@ private:
|
||||
nsCOMPtr<nsIAsyncInputStream> mPipeIn;
|
||||
nsCOMPtr<nsIAsyncOutputStream> mPipeOut;
|
||||
|
||||
nsCOMPtr<nsISupports> mChannel;
|
||||
nsCOMPtr<nsIHttpActivityObserver> mActivityDistributor;
|
||||
|
||||
nsCString mReqHeaderBuf; // flattened request headers
|
||||
nsCOMPtr<nsIInputStream> mRequestStream;
|
||||
PRUint32 mRequestSize;
|
||||
|
Loading…
x
Reference in New Issue
Block a user