fixes bug 324558 "Build data collection service to gather browser metrics" r=bryner

git-svn-id: svn://10.0.0.236/trunk@188800 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
darin%meer.net 2006-02-03 00:32:50 +00:00
parent 6a8e678d4f
commit b2ccd6ec16
13 changed files with 1132 additions and 0 deletions

View File

@ -902,6 +902,11 @@ extensions/typeaheadfind/src/Makefile
extensions/typeaheadfind/Makefile
"
MAKEFILES_metrics="
extensions/metrics/Makefile
extensions/metrics/src/Makefile
"
MAKEFILES_phoenix="
browser/Makefile
browser/app/Makefile

View File

@ -0,0 +1,49 @@
# vim:set ts=8 sw=8 sts=8 noet:
# ***** 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 the Metrics extension.
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Darin Fisher <darin@meer.net>
#
# 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 *****
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src tool
PREF_JS_EXPORTS = $(srcdir)/metrics.js
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,3 @@
pref("metrics.upload.interval", 86400000); // 24 hrs in msec
pref("metrics.upload.enable", false);
pref("metrics.upload.uri", "");

View File

@ -0,0 +1,54 @@
# vim:set ts=8 sw=8 sts=8 noet:
# ***** 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 the Metrics extension.
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Darin Fisher <darin@meer.net>
#
# 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 *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = metrics
XPIDLSRCS = nsIMetricsService.idl
EXPORTS = \
nsMetricsEvent.h \
nsMetricsModule.h \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** 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 the Metrics extension.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* 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"
[ref] native nsMetricsEvent(const class nsMetricsEvent);
[scriptable, uuid(614a8246-5c83-422c-8147-28b8a2946b58)]
interface nsIMetricsService : nsISupports
{
/**
* Log a custom event. The event is recorded with a timestamp generated at
* the time at which this method is called.
*
* @param aEventData
* The data to be logged with this event.
*/
void logCustomEvent(in ACString aEventData);
/**
* Log a raw metrics event.
*/
[noscript] void logEvent(in nsMetricsEvent aEvent);
/**
* Initiate the upload of the current event log. This causes the current
* event log to be truncated once the upload completes.
*/
void upload();
/**
* Suspend log collection. LogEvent calls will be silently ignored while log
* collection is suspended. For each call to suspend, resume must be called
* to re-enable log collection.
*/
void suspend();
/**
* Resume log collection. Call this method once per call to suspend to
* re-enable log collection.
*/
void resume();
};

View File

@ -0,0 +1,99 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** 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 the Metrics extension.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* 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 ***** */
#ifndef nsMetricsEvent_h__
#define nsMetricsEvent_h__
#include "nsTArray.h"
/**
* Every metrics event has a unique type. This value is constrained to 16-bits.
*/
enum nsMetricsEventType {
NS_METRICS_PROFILE_EVENT,
NS_METRICS_CUSTOM_EVENT,
NS_METRICS_LOAD_EVENT,
NS_METRICS_UI_EVENT,
// Insert additional event types here
NS_METRICS_EVENT_MAX
};
/**
* Base class for metric events. This class provides basic structure for each
* event and methods to pack integers and byte arrays into the event.
*/
class nsMetricsEvent {
public:
nsMetricsEvent(nsMetricsEventType type) : mType(type) {
mBuf.SetCapacity(16);
}
void PutInt8(PRUint8 val) {
mBuf.AppendElement(val);
}
void PutInt16(PRUint16 val) {
mBuf.AppendElements((PRUint8 *) &val, sizeof(val));
}
void PutInt32(PRUint32 val) {
mBuf.AppendElements((PRUint8 *) &val, sizeof(val));
}
void PutBytes(const void *ptr, PRUint32 num) {
mBuf.AppendElements((PRUint8 *) ptr, num);
}
nsMetricsEventType Type() const {
return mType;
}
const PRUint8 *Buffer() const {
return mBuf.Elements();
}
PRUint32 BufferLength() const {
return mBuf.Length();
}
private:
nsMetricsEventType mType;
nsTArray<PRUint8> mBuf;
};
#endif // nsMetricsEvent_h__

View File

@ -0,0 +1,52 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** 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 the Metrics extension.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* 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 ***** */
#ifndef nsMetricsModule_h__
#define nsMetricsModule_h__
#define NS_METRICSSERVICE_CLASSNAME "nsMetricsService"
#define NS_METRICSSERVICE_CID \
{ /* 6f72134c-8855-4c07-b181-90d22bf7a0aa */ \
0x6f72134c, \
0x8855, \
0x4c07, \
{0xb1, 0x81, 0x90, 0xd2, 0x2b, 0xf7, 0xa0, 0xaa} \
}
#define NS_METRICSSERVICE_CONTRACTID "@mozilla.org/metrics/service;1"
#endif // nsMetricsModule_h__

View File

@ -0,0 +1,66 @@
# vim:set ts=8 sw=8 sts=8 noet:
# ***** 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 the Metrics extension.
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Darin Fisher <darin@meer.net>
#
# 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 *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = metrics
LIBRARY_NAME = metrics
SHORT_LIBNAME = metrics
IS_COMPONENT = 1
MOZILLA_INTERNAL_API = 1
REQUIRES = xpcom \
string \
necko \
pref \
update \
$(NULL)
CPPSRCS = \
nsMetricsService.cpp \
nsMetricsModule.cpp \
$(NULL)
EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,85 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** 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 the Metrics extension.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* 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 "nsMetricsModule.h"
#include "nsMetricsService.h"
#include "nsMetricsEvent.h"
#include "nsIGenericFactory.h"
#include "nsICategoryManager.h"
#include "nsServiceManagerUtils.h"
#include "nsCOMPtr.h"
#include "nsXPCOMCID.h"
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMetricsService, Init)
NS_DECL_CLASSINFO(nsMetricsService)
static NS_METHOD
nsMetricsServiceRegisterSelf(nsIComponentManager *compMgr,
nsIFile *path,
const char *loaderStr,
const char *type,
const nsModuleComponentInfo *info)
{
nsCOMPtr<nsICategoryManager> cat =
do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
NS_ENSURE_STATE(cat);
cat->AddCategoryEntry("app-startup",
NS_METRICSSERVICE_CLASSNAME,
NS_METRICSSERVICE_CONTRACTID,
PR_TRUE, PR_TRUE, nsnull);
return NS_OK;
}
static const nsModuleComponentInfo components[] = {
{
NS_METRICSSERVICE_CLASSNAME,
NS_METRICSSERVICE_CID,
NS_METRICSSERVICE_CONTRACTID,
nsMetricsServiceConstructor,
nsMetricsServiceRegisterSelf,
NULL,
NULL,
NS_CI_INTERFACE_GETTER_NAME(nsMetricsService),
NULL,
&NS_CLASSINFO_NAME(nsMetricsService),
nsIClassInfo::MAIN_THREAD_ONLY | nsIClassInfo::SINGLETON
}
};
NS_IMPL_NSGETMODULE(metrics, components)

View File

@ -0,0 +1,313 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** 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 the Metrics extension.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* 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 "nsMetricsService.h"
#include "nsMetricsEvent.h"
#include "nsXPCOM.h"
#include "nsServiceManagerUtils.h"
#include "nsDirectoryServiceUtils.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsNetUtil.h"
#include "nsIObserverService.h"
#include "nsIUpdateService.h"
#include "nsIUploadChannel.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIObserver.h"
#include "nsILocalFile.h"
// Flush the event log whenever its size exceeds this amount of bytes.
#define NS_EVENTLOG_FLUSH_POINT 4096
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS5_CI(nsMetricsService, nsIMetricsService,
nsIStreamListener, nsIRequestObserver,
nsIObserver, nsITimerCallback)
NS_IMETHODIMP
nsMetricsService::LogCustomEvent(const nsACString &data)
{
nsMetricsEvent event(NS_METRICS_CUSTOM_EVENT);
PRUint32 len = data.Length();
NS_ENSURE_ARG(len < PR_UINT16_MAX);
event.PutInt16(len);
event.PutBytes(data.BeginReading(), len);
return LogEvent(event);
}
NS_IMETHODIMP
nsMetricsService::LogEvent(const nsMetricsEvent &event)
{
if (mSuspendCount != 0) // Ignore events while suspended
return NS_OK;
NS_ENSURE_ARG(PRUint32(event.Type()) < PR_UINT8_MAX);
// The event header consists of the following fields:
PRUint8 type; // 8-bit event type
PRUint32 timestamp; // 32-bit timestamp (seconds since the epoch)
type = (PRUint8) event.Type();
timestamp = PRUint32(PR_Now() / PR_USEC_PER_SEC);
mEventLog.AppendElement(type);
mEventLog.AppendElements((PRUint8 *) &timestamp, sizeof(timestamp));
mEventLog.AppendElements(event.Buffer(), event.BufferLength());
if (mEventLog.Length() > NS_EVENTLOG_FLUSH_POINT)
FlushData();
return NS_OK;
}
NS_IMETHODIMP
nsMetricsService::Upload()
{
if (mUploading) // Ignore new uploads issued while uploading.
return NS_OK;
// We suspend logging until the upload completes.
nsresult rv = FlushData();
NS_ENSURE_SUCCESS(rv, rv);
rv = UploadData();
if (NS_SUCCEEDED(rv)) {
mUploading = PR_TRUE;
Suspend();
}
return NS_OK;
}
NS_IMETHODIMP
nsMetricsService::Suspend()
{
mSuspendCount++;
return NS_OK;
}
NS_IMETHODIMP
nsMetricsService::Resume()
{
if (mSuspendCount > 0)
mSuspendCount--;
return NS_OK;
}
NS_IMETHODIMP
nsMetricsService::OnStartRequest(nsIRequest *request, nsISupports *context)
{
return NS_OK;
}
NS_IMETHODIMP
nsMetricsService::OnStopRequest(nsIRequest *request, nsISupports *context,
nsresult status)
{
nsCOMPtr<nsILocalFile> dataFile;
GetDataFile(&dataFile);
if (dataFile)
dataFile->Remove(PR_FALSE);
Resume();
mUploading = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsMetricsService::OnDataAvailable(nsIRequest *request, nsISupports *context,
nsIInputStream *stream, PRUint32 offset,
PRUint32 count)
{
// We don't expect to receive any data from an upload.
return NS_ERROR_ABORT;
}
NS_IMETHODIMP
nsMetricsService::Observe(nsISupports *subject, const char *topic,
const PRUnichar *data)
{
if (strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
FlushData();
} else if (strcmp(topic, "app-startup") == 0) {
PRInt32 interval = 86400000; // 24 hours
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs)
prefs->GetIntPref("metrics.upload.interval", &interval);
nsCOMPtr<nsIUpdateTimerManager> mgr =
do_GetService("@mozilla.org/updates/timer-manager;1");
if (mgr)
mgr->RegisterTimer(NS_LITERAL_STRING("metrics-upload"), this, interval);
}
return NS_OK;
}
NS_IMETHODIMP
nsMetricsService::Notify(nsITimer *timer)
{
// OK, we are ready to upload!
Upload();
return NS_OK;
}
nsresult
nsMetricsService::Init()
{
nsresult rv;
// Hook ourselves up to receive the xpcom shutdown event so we can properly
// flush our data to disk.
nsCOMPtr<nsIObserverService> obsSvc =
do_GetService("@mozilla.org/observer-service;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = obsSvc->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
nsMetricsService::GetDataFile(nsCOMPtr<nsILocalFile> *result)
{
nsCOMPtr<nsIFile> file;
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, rv);
rv = file->AppendNative(NS_LITERAL_CSTRING("metrics.dat"));
NS_ENSURE_SUCCESS(rv, rv);
*result = do_QueryInterface(file, &rv);
return rv;
}
nsresult
nsMetricsService::OpenDataFile(PRUint32 flags, PRFileDesc **fd)
{
nsCOMPtr<nsILocalFile> dataFile;
nsresult rv = GetDataFile(&dataFile);
NS_ENSURE_SUCCESS(rv, rv);
return dataFile->OpenNSPRFileDesc(flags, 0600, fd);
}
nsresult
nsMetricsService::FlushData()
{
nsresult rv;
PRFileDesc *fd;
rv = OpenDataFile(PR_WRONLY | PR_APPEND | PR_CREATE_FILE, &fd);
NS_ENSURE_SUCCESS(rv, rv);
PRInt32 num = mEventLog.Length();
PRBool succeeded = ( PR_Write(fd, mEventLog.Elements(), num) == num );
PR_Close(fd);
NS_ENSURE_STATE(succeeded);
mEventLog.SetLength(0);
return NS_OK;
}
nsresult
nsMetricsService::UploadData()
{
// TODO: 1) Submit a request to the server to figure out how much data to
// upload. For now, we just submit all of the data.
// 2) Prepare a data stream for upload that is prefixed with a PROFILE
// event.
PRBool enable = PR_FALSE;
nsXPIDLCString spec;
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
if (prefs) {
prefs->GetBoolPref("metrics.upload.enable", &enable);
prefs->GetCharPref("metrics.upload.uri", getter_Copies(spec));
}
if (!enable || spec.IsEmpty())
return NS_ERROR_ABORT;
nsCOMPtr<nsILocalFile> file;
nsresult rv = GetDataFile(&file);
NS_ENSURE_SUCCESS(rv, rv);
// NOTE: nsIUploadChannel requires a buffered stream to upload...
nsCOMPtr<nsIInputStream> fileStream;
NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file);
NS_ENSURE_STATE(fileStream);
PRUint32 streamLen;
rv = fileStream->Available(&streamLen);
NS_ENSURE_SUCCESS(rv, rv);
if (streamLen == 0)
return NS_ERROR_ABORT;
nsCOMPtr<nsIInputStream> uploadStream;
NS_NewBufferedInputStream(getter_AddRefs(uploadStream), fileStream, 4096);
NS_ENSURE_STATE(uploadStream);
nsCOMPtr<nsIIOService> ios = do_GetIOService();
NS_ENSURE_STATE(ios);
nsCOMPtr<nsIChannel> channel;
ios->NewChannel(spec, nsnull, nsnull, getter_AddRefs(channel));
NS_ENSURE_STATE(channel);
nsCOMPtr<nsIUploadChannel> uploadChannel = do_QueryInterface(channel);
NS_ENSURE_STATE(uploadChannel);
NS_NAMED_LITERAL_CSTRING(binaryType, "application/vnd.mozilla.metrics");
rv = uploadChannel->SetUploadStream(uploadStream, binaryType, -1);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
NS_ENSURE_STATE(httpChannel);
rv = httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
NS_ENSURE_SUCCESS(rv, rv);
rv = channel->AsyncOpen(this, nsnull);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}

View File

@ -0,0 +1,88 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** 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 the Metrics extension.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* 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 ***** */
#ifndef nsMetricsService_h__
#define nsMetricsService_h__
#include "nsIMetricsService.h"
#include "nsIStreamListener.h"
#include "nsILocalFile.h"
#include "nsIObserver.h"
#include "nsITimer.h"
#include "nsTArray.h"
#include "nsCOMPtr.h"
#include "prio.h"
// This class manages the metrics datastore. It is responsible for persisting
// the data when the browser closes and for uploading it to the metrics server
// periodically.
class nsMetricsService : public nsIMetricsService
, public nsIStreamListener
, public nsIObserver
, public nsITimerCallback
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMETRICSSERVICE
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIOBSERVER
NS_DECL_NSITIMERCALLBACK
nsMetricsService()
: mSuspendCount(0)
, mUploading(PR_FALSE)
{}
nsresult Init();
private:
nsresult FlushData();
nsresult UploadData();
nsresult GetDataFile(nsCOMPtr<nsILocalFile> *result);
nsresult OpenDataFile(PRUint32 flags, PRFileDesc **result);
private:
// Memory buffer containing events to be flushed.
nsTArray<PRUint8> mEventLog;
PRInt32 mSuspendCount;
PRBool mUploading;
};
#endif // nsMetricsService_h__

View File

@ -0,0 +1,190 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** 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.org code.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* 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 <string.h>
#include <stdio.h>
//-----------------------------------------------------------------------------
#define HEXDUMP_MAX_ROWS 16
static void hex_dump(unsigned int *state, const unsigned char *buf, int n)
{
const unsigned char *p;
while (n) {
printf(" %08x: ", *state);
*state += HEXDUMP_MAX_ROWS;
p = buf;
int i, row_max = n;
if (row_max > HEXDUMP_MAX_ROWS)
row_max = HEXDUMP_MAX_ROWS;
// print hex codes:
for (i = 0; i < row_max; ++i) {
printf("%02x ", *p++);
}
for (i = row_max; i < HEXDUMP_MAX_ROWS; ++i) {
printf(" ");
}
// print ASCII glyphs if possible:
p = buf;
for (i = 0; i < row_max; ++i, ++p) {
if (*p < 0x7F && *p > 0x1F) {
printf("%c", *p);
} else {
printf("%c", '.');
}
}
printf("\n");
buf += row_max;
n -= row_max;
}
}
//-----------------------------------------------------------------------------
typedef int (* TypeHandler)(const unsigned char *buf, int bufLen);
struct TypeMap {
unsigned char type;
const char *name;
TypeHandler handler;
};
static int dump_profile_event(const unsigned char *buf, int bufLen);
static int dump_custom_event(const unsigned char *buf, int bufLen);
static int dump_load_event(const unsigned char *buf, int bufLen);
static int dump_ui_event(const unsigned char *buf, int bufLen);
static TypeMap g_typemap[] = {
{ '\x00', "PROFILE", dump_profile_event },
{ '\x01', "CUSTOM", dump_custom_event },
{ '\x02', "LOAD", dump_load_event },
{ '\x03', "UI", dump_ui_event }
};
int dump_profile_event(const unsigned char *buf, int bufLen)
{
return -1; // XXX Implement me!
}
int dump_load_event(const unsigned char *buf, int bufLen)
{
return -1; // XXX Implement me!
}
int dump_ui_event(const unsigned char *buf, int bufLen)
{
return -1; // XXX Implement me!
}
int dump_custom_event(const unsigned char *buf, int bufLen)
{
unsigned short num;
memcpy(&num, buf, sizeof(num));
unsigned int state = 0;
hex_dump(&state, buf + 2, num);
return 2 + num;
}
static void dump_data(const unsigned char *buf, int bufLen)
{
const unsigned char *end = buf + bufLen;
while (buf < end) {
int n = -1;
for (size_t i = 0; i < sizeof(g_typemap)/sizeof(g_typemap[0]); ++i) {
if (g_typemap[i].type == *buf) {
static unsigned long g_first_timestamp = 0;
// dump the header, which consists of a single byte identifier
// for the type, and a 32-bit timestamp (seconds since epoch)
unsigned long ts;
memcpy(&ts, buf + 1, 4);
if (g_first_timestamp == 0) {
g_first_timestamp = ts;
ts = 0;
} else {
ts -= g_first_timestamp;
}
printf("%s(%lu):\n", g_typemap[i].name, ts);
buf += 5;
n = g_typemap[i].handler(buf, bufLen);
if (n > 0)
buf += n;
break;
}
}
if (n == -1) {
fprintf(stderr, "error: unhandled event type!\n");
return;
}
}
}
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
if (argc < 2) {
fprintf(stderr, "usage: DumpMetrics metrics.dat\n");
return -1;
}
FILE *fp = fopen(argv[1], "rb");
if (!fp)
return -1;
fseek(fp, 0, SEEK_END);
long len = ftell(fp);
fseek(fp, 0, SEEK_SET);
unsigned char *buf = new unsigned char[len];
if (fread(buf, len, 1, fp) != 1)
len = 0;
if (len)
dump_data(buf, len);
delete[] buf;
fclose(fp);
return 0;
}

View File

@ -0,0 +1,50 @@
# vim:set ts=8 sw=8 sts=8 noet:
# ***** 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 the Metrics extension.
#
# The Initial Developer of the Original Code is Google Inc.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Darin Fisher <darin@meer.net>
#
# 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 *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = metrics
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
CPPSRCS = DumpMetrics.cpp
include $(topsrcdir)/config/rules.mk