mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2026-02-08 00:52:01 +01:00
Removed lib that are luxuary components.
This commit is contained in:
@@ -17,7 +17,6 @@ ChromePHP 4.1.0 Apache Software License 2.0 Yes
|
||||
CKEditor 4.3.3 LGPL-2.1+ Yes Editor WYSIWYG
|
||||
EvalMath 1.0 BSD Yes Safe math expressions evaluation
|
||||
Escpos-php MIT License Yes Thermal receipt printer library, for use with ESC/POS compatible printers
|
||||
FirePHPCore 0.4.0 MIT License Yes Send logs to Firefox Firebug console
|
||||
FPDI 1.5.2 Apache Software License 2.0 Yes PDF templates management
|
||||
GeoIP 1.4 LGPL-2.1+ Yes Sample code to make geoip convert (not into deb package)
|
||||
Mobiledetect 2.8.3 MIT License Yes Detect mobile devices browsers
|
||||
@@ -28,7 +27,6 @@ PHPExcel 1.8.1 LGPL-2.1+ Yes
|
||||
php-iban 1.4.7 LGPL-3+ Yes Parse and validate IBAN (and IIBAN) bank account information in PHP
|
||||
PHPoAuthLib 0.8.2 MIT License Yes Library to provide oauth1 and oauth2 to different service
|
||||
PHPPrintIPP 1.3 GPL-2+ Yes Library to send print IPP requests
|
||||
Raven-php 0.12.1 MIT License Yes Used for server-side error logging with Sentry logger
|
||||
Restler 3.0 LGPL-3+ Yes Library to develop REST Web services
|
||||
TCPDF 6.2.6 LGPL-3+ Yes PDF generation
|
||||
TCPDI 1.0.0 LGPL-3+ / Apache 2.0 Yes FPDI replacement
|
||||
@@ -55,7 +53,6 @@ jQuery Timepicker 1.1.0 GPL and MIT License Yes
|
||||
jQuery Tiptip 1.3 GPL and MIT License Yes JS library for tooltips
|
||||
jsGantt 1.2 BSD License Yes JS library (to build Gantt reports)
|
||||
JsTimezoneDetect 1.0.6 MIT License Yes JS library to detect user timezone
|
||||
Raven.js 1.1.19 MIT License Yes Used for client-side error logging with Sentry logger
|
||||
|
||||
For licenses compatibility informations:
|
||||
http://www.gnu.org/licenses/licenses.en.html
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
build/
|
||||
@@ -1,171 +0,0 @@
|
||||
|
||||
TODO:
|
||||
|
||||
* Fix code indenting in PHP 4 code
|
||||
* Port maxDepth option to PHP 4 code
|
||||
|
||||
2013-04-23 - Release Version: 0.4.0
|
||||
|
||||
* No changes
|
||||
|
||||
2011-06-22 - Release Version: 0.4.0rc3
|
||||
|
||||
* Build fixes
|
||||
|
||||
2011-06-20 - Release Version: 0.4.0rc1
|
||||
|
||||
* (Issue 163) PHP5 class_exists() throws Exception without second parameter
|
||||
* (Issue 166) Non-utf8 array values replaced with null
|
||||
* Cleaned up code formatting [sokolov.innokenty@gmail.com]
|
||||
* Ensure JSON keys are never NULL (due to NULL key in some arrays)
|
||||
* Better UTF-8 encoding detection
|
||||
* Code style cleanup (qbbr)
|
||||
* Changed license to MIT
|
||||
* Refactored project
|
||||
|
||||
2010-10-26 - Release Version: 0.3.2
|
||||
|
||||
2010-10-12 - Release Version: 0.3.2rc6
|
||||
|
||||
* (Issue 154) getRequestHeader uses "getallheaders" even though it doesn't always exist. [25m]
|
||||
|
||||
2010-10-09 - Release Version: 0.3.2rc5
|
||||
|
||||
* (Issue 153) FirePHP incorrectly double-encodes UTF8 when mbstring.func_overload is enabled
|
||||
|
||||
2010-10-08 - Release Version: 0.3.2rc4
|
||||
|
||||
* Trigger upgrade message if part of FirePHP 1.0
|
||||
* Removed FirePHP/Init.php inclusion logic and only load FirePHP.class.php if not already loaded
|
||||
|
||||
2010-07-19 - Release Version: 0.3.2rc3
|
||||
|
||||
* Fixed FirePHP/Init.php inclusion logic
|
||||
|
||||
2010-07-19 - Release Version: 0.3.2rc2
|
||||
|
||||
* (Issue 145) maxDepth option
|
||||
* Changed maxObjectDepth and maxArrayDepth option defaults to 5
|
||||
* Fixed code indentation
|
||||
|
||||
2010-03-05 - Release Version: 0.3.2rc1
|
||||
|
||||
* (Issue 114) Allow options to be passed on to basic logging wrappers
|
||||
* (Issue 122) Filter objectStack property of FirePHP class
|
||||
* (Issue 123) registerErrorHandler(false) by default
|
||||
* Added setOption() and getOption() methods
|
||||
* (Issue 117) dump() method argument validation
|
||||
* Started adding PHPUnit tests
|
||||
* Some refactoring to support unit testing
|
||||
* Deprecated setProcessorUrl() and setRendererUrl()
|
||||
* Check User-Agent and X-FirePHP-Version header to detect FirePHP on client
|
||||
* (Issue 135) FirePHP 0.4.3 with Firebug 1.5 changes user agent on the fly
|
||||
* (Issue 112) Error Predefined Constants Not available for PHP 5.x versions
|
||||
|
||||
2008-06-14 - Release Version: 0.3.1
|
||||
|
||||
* (Issue 108) ignore class name case in object filter
|
||||
|
||||
2009-05-11 - Release Version: 0.3
|
||||
2009-05-01 - Release Version: 0.3.rc.1
|
||||
|
||||
* (Issue 90) PHP4 compatible version of FirePHPCore
|
||||
* (Issue 98) Thrown exceptions don't send an HTTP 500 if the FirePHP exception handler is enabled
|
||||
* (Issue 85) Support associative arrays in encodeTable method in FirePHP.class.php
|
||||
* (Issue 66) Add a new getOptions() public method in API
|
||||
* (Issue 82) Define $this->options outside of __construct
|
||||
* (Issue 72) Message error if group name is null
|
||||
* (Issue 68) registerErrorHandler() and registerExceptionHandler() should returns previous handlers defined
|
||||
* (Issue 69) Add the missing register handler in the triumvirate (error, exception, assert)
|
||||
* (Issue 75) [Error & Exception Handling] Option to not exit script execution
|
||||
* (Issue 83) Exception handler can't throw exceptions
|
||||
* (Issue 80) Auto/Pre collapsing groups AND Custom group row colors
|
||||
|
||||
2008-11-09 - Release Version: 0.2.1
|
||||
|
||||
* (Issue 70) Problem when logging resources
|
||||
|
||||
2008-10-21 - Release Version: 0.2.0
|
||||
|
||||
* Updated version to 0.2.0
|
||||
* Switched to using __sleep instead of __wakeup
|
||||
* Added support to exclude object members when encoding
|
||||
* Add support to enable/disable logging
|
||||
|
||||
2008-10-17 - Release Version: 0.2.b.8
|
||||
|
||||
* New implementation for is_utf8()
|
||||
* (Issue 55) maxObjectDepth Option not working correctly when using TABLE and EXCEPTION Type
|
||||
* Bugfix for max[Object|Array]Depth when encoding nested array/object graphs
|
||||
* Bugfix for FB::setOptions()
|
||||
|
||||
2008-10-16 - Release Version: 0.2.b.7
|
||||
|
||||
* (Issue 45) Truncate dump when string have non utf8 cars
|
||||
* (Issue 52) logging will not work when firephp object gets stored in the session.
|
||||
|
||||
2008-10-16 - Release Version: 0.2.b.6
|
||||
|
||||
* (Issue 37) Display file and line information for each log message
|
||||
* (Issue 51) Limit output of object graphs
|
||||
* Bugfix for encoding object members set to NULL|false|''
|
||||
|
||||
2008-10-14 - Release Version: 0.2.b.5
|
||||
|
||||
* Updated JsonStream wildfire protocol to be more robust
|
||||
* (Issue 33) PHP error notices running demos
|
||||
* (Issue 48) Warning: ReflectionProperty::getValue() expects exactly 1 parameter, 0 given
|
||||
|
||||
2008-10-08 - Release Version: 0.2.b.4
|
||||
|
||||
* Bugfix for logging objects with recursion
|
||||
|
||||
2008-10-08 - Release Version: 0.2.b.3
|
||||
|
||||
* (Issue 43) Notice message in 0.2b2
|
||||
* Added support for PHP's native json_encode() if available
|
||||
* Revised object encoder to detect object recursion
|
||||
|
||||
2008-10-07 - Release Version: 0.2.b.2
|
||||
|
||||
* (Issue 28) Need solution for logging private and protected object variables
|
||||
* Added trace() and table() aliases in FirePHP class
|
||||
* (Issue 41) Use PHP doc in FirePHP
|
||||
* (Issue 39) Static logging method for object oriented API
|
||||
|
||||
2008-10-01 - Release Version: 0.2.b.1
|
||||
|
||||
* Added support for error and exception handling
|
||||
* Updated min PHP version for PEAR package to 5.2
|
||||
* Added version constant for library
|
||||
* Gave server library it's own wildfire plugin namespace
|
||||
* Migrated communication protocol to Wildfire JsonStream
|
||||
* Added support for console groups using "group" and "groupEnd"
|
||||
* Added support for log, info, warn and error logging aliases
|
||||
* (Issue 29) problem with TRACE when using with error_handler
|
||||
* (Issue 33) PHP error notices running demos
|
||||
* (Issue 12) undefined index php notice
|
||||
* Removed closing ?> php tags
|
||||
* (Issue 13) the code in the fb() function has a second return statement that will never be reached
|
||||
|
||||
2008-07-30 - Release Version: 0.1.1.3
|
||||
|
||||
* Include __className property in JSON string if variable was an object
|
||||
* Bugfix - Mis-spelt "Exception" in JSON encoding code
|
||||
|
||||
2008-06-13 - Release Version: 0.1.1.1
|
||||
|
||||
* Bugfix - Standardize windows paths in stack traces
|
||||
* Bugfix - Display correct stack trace info in windows environments
|
||||
* Bugfix - Check $_SERVER['HTTP_USER_AGENT'] before returning
|
||||
|
||||
2008-06-13 - Release Version: 0.1.1
|
||||
|
||||
* Added support for FirePHP::TRACE log style
|
||||
* Changed license to New BSD License
|
||||
|
||||
2008-06-06 - Release Version: 0.0.2
|
||||
|
||||
* Bugfix - Added usleep() to header writing loop to ensure unique index
|
||||
* Bugfix - Ensure chunk_split does not generate trailing "\n" with empty data header
|
||||
* Added support for FirePHP::TABLE log style
|
||||
@@ -1,75 +0,0 @@
|
||||
FirePHPCore
|
||||
===========
|
||||
|
||||
**Status: stable**
|
||||
|
||||
> **FirePHP is an advanced logging system that can display PHP variables in the browser as an application is navigated.**
|
||||
> All communication is out of band to the application meaning that the logging data will not interfere with the normal functioning of the application.
|
||||
|
||||
This project contains the *FirePHPCore* PHP server library and provides a development environment (see `./workspace/`) for working on *FirePHPCore*.
|
||||
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
See [Install/Traditional: FirePHPCore](http://docs.sourcemint.org/firephp.org/firephp/1/-docs/Configuration/Traditional) in the
|
||||
[FirePHP 1.0 Documentation](http://docs.sourcemint.org/firephp.org/firephp/1/-docs/).
|
||||
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
cd tests
|
||||
phpunit .
|
||||
|
||||
|
||||
Support & Feedback
|
||||
==================
|
||||
|
||||
See [Support](http://docs.sourcemint.org/firephp.org/firephp/1/-docs/OpenSource#support) in the [FirePHP 1.0 Documentation](http://docs.sourcemint.org/firephp.org/firephp/1/-docs/).
|
||||
|
||||
|
||||
Contribute
|
||||
==========
|
||||
|
||||
See [Contribute](http://docs.sourcemint.org/firephp.org/firephp/1/-docs/OpenSource#contribute) in the [FirePHP 1.0 Documentation](http://docs.sourcemint.org/firephp.org/firephp/1/-docs/).
|
||||
|
||||
|
||||
Author
|
||||
======
|
||||
|
||||
This project is authored and maintained by [Christoph Dorn](http://www.christophdorn.com/).
|
||||
|
||||
|
||||
Documentation License
|
||||
=====================
|
||||
|
||||
[Creative Commons Attribution-NonCommercial-ShareAlike 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/)
|
||||
|
||||
Copyright (c) 2007+ [Christoph Dorn](http://www.christophdorn.com/)
|
||||
|
||||
|
||||
Code License
|
||||
============
|
||||
|
||||
[MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
|
||||
Copyright (c) 2007+ [Christoph Dorn](http://www.christophdorn.com/)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"name": "firephp/firephp-core",
|
||||
"description": "Traditional FirePHPCore library for sending PHP variables to the browser.",
|
||||
"type": "library",
|
||||
"homepage": "https://github.com/firephp/firephp-core",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christoph Dorn",
|
||||
"email": "christoph@christophdorn.com",
|
||||
"homepage": "http://christophdorn.com"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"forum": "http://groups.google.com/group/firephp-dev",
|
||||
"issues": "https://github.com/firephp/firephp-core/issues",
|
||||
"source": "https://github.com/firephp/firephp-core"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"lib/FirePHPCore/FirePHP.class.php",
|
||||
"lib/FirePHPCore/fb.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
<?php
|
||||
// Authors:
|
||||
// - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2007, New BSD License
|
||||
// - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2011, MIT License
|
||||
|
||||
/* *** BEGIN LICENSE BLOCK *****
|
||||
*
|
||||
* [MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
*
|
||||
* Copyright (c) 2007+ [Christoph Dorn](http://www.christophdorn.com/)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
/* NOTE: You must have the FirePHPCore library in your include path */
|
||||
|
||||
set_include_path(dirname(dirname(__FILE__)).'/lib'.PATH_SEPARATOR.get_include_path());
|
||||
|
||||
|
||||
require('FirePHPCore/FirePHP.class.php');
|
||||
|
||||
/* NOTE: You must have Output Buffering enabled via
|
||||
ob_start() or output_buffering ini directive. */
|
||||
|
||||
|
||||
$firephp = FirePHP::getInstance(true);
|
||||
|
||||
|
||||
$firephp->fb('Hello World'); /* Defaults to FirePHP::LOG */
|
||||
|
||||
$firephp->fb('Log message' ,FirePHP::LOG);
|
||||
$firephp->fb('Info message' ,FirePHP::INFO);
|
||||
$firephp->fb('Warn message' ,FirePHP::WARN);
|
||||
$firephp->fb('Error message',FirePHP::ERROR);
|
||||
|
||||
$firephp->fb('Message with label','Label',FirePHP::LOG);
|
||||
|
||||
$firephp->fb(array('key1'=>'val1',
|
||||
'key2'=>array(array('v1','v2'),'v3')),
|
||||
'TestArray',FirePHP::LOG);
|
||||
|
||||
function test($Arg1) {
|
||||
throw new Exception('Test Exception');
|
||||
}
|
||||
try {
|
||||
test(array('Hello'=>'World'));
|
||||
} catch(Exception $e) {
|
||||
/* Log exception including stack trace & variables */
|
||||
$firephp->fb($e);
|
||||
}
|
||||
|
||||
$firephp->fb('Backtrace to here',FirePHP::TRACE);
|
||||
|
||||
$firephp->fb(array('2 SQL queries took 0.06 seconds',array(
|
||||
array('SQL Statement','Time','Result'),
|
||||
array('SELECT * FROM Foo','0.02',array('row1','row2')),
|
||||
array('SELECT * FROM Bar','0.04',array('row1','row2'))
|
||||
)),FirePHP::TABLE);
|
||||
|
||||
/* Will show only in "Server" tab for the request */
|
||||
$firephp->fb(apache_request_headers(),'RequestHeaders',FirePHP::DUMP);
|
||||
|
||||
|
||||
print 'Hello World';
|
||||
@@ -1,72 +0,0 @@
|
||||
<?php
|
||||
// Authors:
|
||||
// - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2007, New BSD License
|
||||
// - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2011, MIT License
|
||||
|
||||
/* *** BEGIN LICENSE BLOCK *****
|
||||
*
|
||||
* [MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
*
|
||||
* Copyright (c) 2007+ [Christoph Dorn](http://www.christophdorn.com/)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
/* NOTE: You must have the FirePHPCore library in your include path */
|
||||
|
||||
set_include_path(dirname(dirname(__FILE__)).'/lib'.PATH_SEPARATOR.get_include_path());
|
||||
|
||||
|
||||
require('FirePHPCore/FirePHP.class.php4');
|
||||
|
||||
/* NOTE: You must have Output Buffering enabled via
|
||||
ob_start() or output_buffering ini directive. */
|
||||
|
||||
|
||||
$firephp =& FirePHP::getInstance(true);
|
||||
|
||||
|
||||
$firephp->fb('Hello World'); /* Defaults to FirePHP::LOG */
|
||||
|
||||
$firephp->fb('Log message' ,FirePHP_LOG);
|
||||
$firephp->fb('Info message' ,FirePHP_INFO);
|
||||
$firephp->fb('Warn message' ,FirePHP_WARN);
|
||||
$firephp->fb('Error message',FirePHP_ERROR);
|
||||
|
||||
$firephp->fb('Message with label','Label',FirePHP_LOG);
|
||||
|
||||
$firephp->fb(array('key1'=>'val1',
|
||||
'key2'=>array(array('v1','v2'),'v3')),
|
||||
'TestArray',FirePHP_LOG);
|
||||
|
||||
$firephp->fb('Backtrace to here',FirePHP_TRACE);
|
||||
|
||||
$firephp->fb(array('2 SQL queries took 0.06 seconds',array(
|
||||
array('SQL Statement','Time','Result'),
|
||||
array('SELECT * FROM Foo','0.02',array('row1','row2')),
|
||||
array('SELECT * FROM Bar','0.04',array('row1','row2'))
|
||||
)),FirePHP_TABLE);
|
||||
|
||||
/* Will show only in "Server" tab for the request */
|
||||
$firephp->fb(apache_request_headers(),'RequestHeaders',FirePHP_DUMP);
|
||||
|
||||
|
||||
print 'Hello World';
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
// Authors:
|
||||
// - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2007, New BSD License
|
||||
// - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2011, MIT License
|
||||
|
||||
/* *** BEGIN LICENSE BLOCK *****
|
||||
*
|
||||
* [MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
*
|
||||
* Copyright (c) 2007+ [Christoph Dorn](http://www.christophdorn.com/)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
/* NOTE: You must have the FirePHPCore library in your include path */
|
||||
|
||||
set_include_path(dirname(dirname(__FILE__)).'/lib'.PATH_SEPARATOR.get_include_path());
|
||||
|
||||
|
||||
require('FirePHPCore/fb.php');
|
||||
|
||||
/* NOTE: You must have Output Buffering enabled via
|
||||
ob_start() or output_buffering ini directive. */
|
||||
|
||||
fb('Hello World'); /* Defaults to FirePHP::LOG */
|
||||
|
||||
fb('Log message' ,FirePHP::LOG);
|
||||
fb('Info message' ,FirePHP::INFO);
|
||||
fb('Warn message' ,FirePHP::WARN);
|
||||
fb('Error message',FirePHP::ERROR);
|
||||
|
||||
fb('Message with label','Label',FirePHP::LOG);
|
||||
|
||||
fb(array('key1'=>'val1',
|
||||
'key2'=>array(array('v1','v2'),'v3')),
|
||||
'TestArray',FirePHP::LOG);
|
||||
|
||||
function test($Arg1) {
|
||||
throw new Exception('Test Exception');
|
||||
}
|
||||
try {
|
||||
test(array('Hello'=>'World'));
|
||||
} catch(Exception $e) {
|
||||
/* Log exception including stack trace & variables */
|
||||
fb($e);
|
||||
}
|
||||
|
||||
fb('Backtrace to here',FirePHP::TRACE);
|
||||
|
||||
fb(array('2 SQL queries took 0.06 seconds',array(
|
||||
array('SQL Statement','Time','Result'),
|
||||
array('SELECT * FROM Foo','0.02',array('row1','row2')),
|
||||
array('SELECT * FROM Bar','0.04',array('row1','row2'))
|
||||
)),FirePHP::TABLE);
|
||||
|
||||
/* Will show only in "Server" tab for the request */
|
||||
fb(apache_request_headers(),'RequestHeaders',FirePHP::DUMP);
|
||||
|
||||
|
||||
print 'Hello World';
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
// Authors:
|
||||
// - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2007, New BSD License
|
||||
// - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2011, MIT License
|
||||
|
||||
/* *** BEGIN LICENSE BLOCK *****
|
||||
*
|
||||
* [MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
*
|
||||
* Copyright (c) 2007+ [Christoph Dorn](http://www.christophdorn.com/)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
/* NOTE: You must have the FirePHPCore library in your include path */
|
||||
|
||||
set_include_path(dirname(dirname(__FILE__)).'/lib'.PATH_SEPARATOR.get_include_path());
|
||||
|
||||
|
||||
require('FirePHPCore/fb.php');
|
||||
|
||||
/* NOTE: You must have Output Buffering enabled via
|
||||
ob_start() or output_buffering ini directive. */
|
||||
|
||||
fb('Hello World'); /* Defaults to FirePHP::LOG */
|
||||
|
||||
fb('Log message' ,FirePHP_LOG);
|
||||
fb('Info message' ,FirePHP_INFO);
|
||||
fb('Warn message' ,FirePHP_WARN);
|
||||
fb('Error message',FirePHP_ERROR);
|
||||
|
||||
fb('Message with label','Label',FirePHP_LOG);
|
||||
|
||||
fb(array('key1'=>'val1',
|
||||
'key2'=>array(array('v1','v2'),'v3')),
|
||||
'TestArray',FirePHP_LOG);
|
||||
|
||||
fb('Backtrace to here',FirePHP_TRACE);
|
||||
|
||||
fb(array('2 SQL queries took 0.06 seconds',array(
|
||||
array('SQL Statement','Time','Result'),
|
||||
array('SELECT * FROM Foo','0.02',array('row1','row2')),
|
||||
array('SELECT * FROM Bar','0.04',array('row1','row2'))
|
||||
)),FirePHP_TABLE);
|
||||
|
||||
/* Will show only in "Server" tab for the request */
|
||||
fb(apache_request_headers(),'RequestHeaders',FirePHP_DUMP);
|
||||
|
||||
|
||||
print 'Hello World';
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,275 +0,0 @@
|
||||
<?php
|
||||
// Authors:
|
||||
// - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2007, New BSD License
|
||||
// - qbbr, Sokolov Innokenty <sokolov.innokenty@gmail.com>, Copyright 2011, New BSD License
|
||||
// - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2011, MIT License
|
||||
|
||||
/**
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
*
|
||||
* [MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
*
|
||||
* Copyright (c) 2007+ [Christoph Dorn](http://www.christophdorn.com/)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK *****
|
||||
*
|
||||
* @copyright Copyright (C) 2007+ Christoph Dorn
|
||||
* @author Christoph Dorn <christoph@christophdorn.com>
|
||||
* @license [MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
* @package FirePHPCore
|
||||
*/
|
||||
|
||||
if (!class_exists('FirePHP', false)) {
|
||||
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'FirePHP.class.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the given data to the FirePHP Firefox Extension.
|
||||
* The data can be displayed in the Firebug Console or in the
|
||||
* "Server" request tab.
|
||||
*
|
||||
* @see http://www.firephp.org/Wiki/Reference/Fb
|
||||
* @param mixed $Object
|
||||
* @return true
|
||||
* @throws Exception
|
||||
*/
|
||||
function fb()
|
||||
{
|
||||
$instance = FirePHP::getInstance(true);
|
||||
|
||||
$args = func_get_args();
|
||||
return call_user_func_array(array($instance, 'fb'), $args);
|
||||
}
|
||||
|
||||
|
||||
class FB
|
||||
{
|
||||
/**
|
||||
* Set an Insight console to direct all logging calls to
|
||||
*
|
||||
* @param object $console The console object to log to
|
||||
* @return void
|
||||
*/
|
||||
public static function setLogToInsightConsole($console)
|
||||
{
|
||||
FirePHP::getInstance(true)->setLogToInsightConsole($console);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable and disable logging to Firebug
|
||||
*
|
||||
* @see FirePHP->setEnabled()
|
||||
* @param boolean $enabled TRUE to enable, FALSE to disable
|
||||
* @return void
|
||||
*/
|
||||
public static function setEnabled($enabled)
|
||||
{
|
||||
FirePHP::getInstance(true)->setEnabled($enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if logging is enabled
|
||||
*
|
||||
* @see FirePHP->getEnabled()
|
||||
* @return boolean TRUE if enabled
|
||||
*/
|
||||
public static function getEnabled()
|
||||
{
|
||||
return FirePHP::getInstance(true)->getEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a filter to be used when encoding an object
|
||||
*
|
||||
* Filters are used to exclude object members.
|
||||
*
|
||||
* @see FirePHP->setObjectFilter()
|
||||
* @param string $class The class name of the object
|
||||
* @param array $filter An array or members to exclude
|
||||
* @return void
|
||||
*/
|
||||
public static function setObjectFilter($class, $filter)
|
||||
{
|
||||
FirePHP::getInstance(true)->setObjectFilter($class, $filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some options for the library
|
||||
*
|
||||
* @see FirePHP->setOptions()
|
||||
* @param array $options The options to be set
|
||||
* @return void
|
||||
*/
|
||||
public static function setOptions($options)
|
||||
{
|
||||
FirePHP::getInstance(true)->setOptions($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get options for the library
|
||||
*
|
||||
* @see FirePHP->getOptions()
|
||||
* @return array The options
|
||||
*/
|
||||
public static function getOptions()
|
||||
{
|
||||
return FirePHP::getInstance(true)->getOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Log object to firebug
|
||||
*
|
||||
* @see http://www.firephp.org/Wiki/Reference/Fb
|
||||
* @param mixed $object
|
||||
* @return true
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function send()
|
||||
{
|
||||
$args = func_get_args();
|
||||
return call_user_func_array(array(FirePHP::getInstance(true), 'fb'), $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a group for following messages
|
||||
*
|
||||
* Options:
|
||||
* Collapsed: [true|false]
|
||||
* Color: [#RRGGBB|ColorName]
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $options OPTIONAL Instructions on how to log the group
|
||||
* @return true
|
||||
*/
|
||||
public static function group($name, $options=null)
|
||||
{
|
||||
return FirePHP::getInstance(true)->group($name, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a group you have started before
|
||||
*
|
||||
* @return true
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function groupEnd()
|
||||
{
|
||||
return self::send(null, null, FirePHP::GROUP_END);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log object with label to firebug console
|
||||
*
|
||||
* @see FirePHP::LOG
|
||||
* @param mixes $object
|
||||
* @param string $label
|
||||
* @return true
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function log($object, $label=null)
|
||||
{
|
||||
return self::send($object, $label, FirePHP::LOG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log object with label to firebug console
|
||||
*
|
||||
* @see FirePHP::INFO
|
||||
* @param mixes $object
|
||||
* @param string $label
|
||||
* @return true
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function info($object, $label=null)
|
||||
{
|
||||
return self::send($object, $label, FirePHP::INFO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log object with label to firebug console
|
||||
*
|
||||
* @see FirePHP::WARN
|
||||
* @param mixes $object
|
||||
* @param string $label
|
||||
* @return true
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function warn($object, $label=null)
|
||||
{
|
||||
return self::send($object, $label, FirePHP::WARN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log object with label to firebug console
|
||||
*
|
||||
* @see FirePHP::ERROR
|
||||
* @param mixes $object
|
||||
* @param string $label
|
||||
* @return true
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function error($object, $label=null)
|
||||
{
|
||||
return self::send($object, $label, FirePHP::ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps key and variable to firebug server panel
|
||||
*
|
||||
* @see FirePHP::DUMP
|
||||
* @param string $key
|
||||
* @param mixed $variable
|
||||
* @return true
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function dump($key, $variable)
|
||||
{
|
||||
return self::send($variable, $key, FirePHP::DUMP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a trace in the firebug console
|
||||
*
|
||||
* @see FirePHP::TRACE
|
||||
* @param string $label
|
||||
* @return true
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function trace($label)
|
||||
{
|
||||
return self::send($label, FirePHP::TRACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a table in the firebug console
|
||||
*
|
||||
* @see FirePHP::TABLE
|
||||
* @param string $label
|
||||
* @param string $table
|
||||
* @return true
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function table($label, $table)
|
||||
{
|
||||
return self::send($table, $label, FirePHP::TABLE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,245 +0,0 @@
|
||||
<?php
|
||||
// Authors:
|
||||
// - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2007, New BSD License
|
||||
// - qbbr, Michael Day <manveru.alma@gmail.com>, Copyright 2008, New BSD License
|
||||
// - cadorn, Christoph Dorn <christoph@christophdorn.com>, Copyright 2011, MIT License
|
||||
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
*
|
||||
* [MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
*
|
||||
* Copyright (c) 2007+ [Christoph Dorn](http://www.christophdorn.com/)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* ***** END LICENSE BLOCK *****
|
||||
*
|
||||
* @copyright Copyright (C) 2007+ Christoph Dorn
|
||||
* @author Christoph Dorn <christoph@christophdorn.com>
|
||||
* @author Michael Day <manveru.alma@gmail.com>
|
||||
* @license [MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
* @package FirePHPCore
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__).'/FirePHP.class.php4';
|
||||
|
||||
/**
|
||||
* Sends the given data to the FirePHP Firefox Extension.
|
||||
* The data can be displayed in the Firebug Console or in the
|
||||
* "Server" request tab.
|
||||
*
|
||||
* @see http://www.firephp.org/Wiki/Reference/Fb
|
||||
* @param mixed $Object
|
||||
* @return true
|
||||
* @throws Exception
|
||||
*/
|
||||
function fb()
|
||||
{
|
||||
$instance =& FirePHP::getInstance(true);
|
||||
|
||||
$args = func_get_args();
|
||||
return call_user_func_array(array(&$instance,'fb'),$args);
|
||||
}
|
||||
|
||||
|
||||
class FB
|
||||
{
|
||||
/**
|
||||
* Enable and disable logging to Firebug
|
||||
*
|
||||
* @see FirePHP->setEnabled()
|
||||
* @param boolean $Enabled TRUE to enable, FALSE to disable
|
||||
* @return void
|
||||
*/
|
||||
function setEnabled($Enabled) {
|
||||
$instance =& FirePHP::getInstance(true);
|
||||
$instance->setEnabled($Enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if logging is enabled
|
||||
*
|
||||
* @see FirePHP->getEnabled()
|
||||
* @return boolean TRUE if enabled
|
||||
*/
|
||||
function getEnabled() {
|
||||
$instance =& FirePHP::getInstance(true);
|
||||
return $instance->getEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a filter to be used when encoding an object
|
||||
*
|
||||
* Filters are used to exclude object members.
|
||||
*
|
||||
* @see FirePHP->setObjectFilter()
|
||||
* @param string $Class The class name of the object
|
||||
* @param array $Filter An array or members to exclude
|
||||
* @return void
|
||||
*/
|
||||
function setObjectFilter($Class, $Filter) {
|
||||
$instance =& FirePHP::getInstance(true);
|
||||
$instance->setObjectFilter($Class, $Filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set some options for the library
|
||||
*
|
||||
* @see FirePHP->setOptions()
|
||||
* @param array $Options The options to be set
|
||||
* @return void
|
||||
*/
|
||||
function setOptions($Options) {
|
||||
$instance =& FirePHP::getInstance(true);
|
||||
$instance->setOptions($Options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get options for the library
|
||||
*
|
||||
* @see FirePHP->getOptions()
|
||||
* @return array The options
|
||||
*/
|
||||
function getOptions() {
|
||||
$instance =& FirePHP::getInstance(true);
|
||||
return $instance->getOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Log object to firebug
|
||||
*
|
||||
* @see http://www.firephp.org/Wiki/Reference/Fb
|
||||
* @param mixed $Object
|
||||
* @return true
|
||||
*/
|
||||
function send()
|
||||
{
|
||||
$instance =& FirePHP::getInstance(true);
|
||||
$args = func_get_args();
|
||||
return call_user_func_array(array(&$instance,'fb'),$args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a group for following messages
|
||||
*
|
||||
* Options:
|
||||
* Collapsed: [true|false]
|
||||
* Color: [#RRGGBB|ColorName]
|
||||
*
|
||||
* @param string $Name
|
||||
* @param array $Options OPTIONAL Instructions on how to log the group
|
||||
* @return true
|
||||
*/
|
||||
function group($Name, $Options=null) {
|
||||
$instance =& FirePHP::getInstance(true);
|
||||
return $instance->group($Name, $Options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a group you have started before
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
function groupEnd() {
|
||||
return FB::send(null, null, FirePHP_GROUP_END);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log object with label to firebug console
|
||||
*
|
||||
* @see FirePHP::LOG
|
||||
* @param mixes $Object
|
||||
* @param string $Label
|
||||
* @return true
|
||||
*/
|
||||
function log($Object, $Label=null) {
|
||||
return FB::send($Object, $Label, FirePHP_LOG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log object with label to firebug console
|
||||
*
|
||||
* @see FirePHP::INFO
|
||||
* @param mixes $Object
|
||||
* @param string $Label
|
||||
* @return true
|
||||
*/
|
||||
function info($Object, $Label=null) {
|
||||
return FB::send($Object, $Label, FirePHP_INFO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log object with label to firebug console
|
||||
*
|
||||
* @see FirePHP::WARN
|
||||
* @param mixes $Object
|
||||
* @param string $Label
|
||||
* @return true
|
||||
*/
|
||||
function warn($Object, $Label=null) {
|
||||
return FB::send($Object, $Label, FirePHP_WARN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log object with label to firebug console
|
||||
*
|
||||
* @see FirePHP::ERROR
|
||||
* @param mixes $Object
|
||||
* @param string $Label
|
||||
* @return true
|
||||
*/
|
||||
function error($Object, $Label=null) {
|
||||
return FB::send($Object, $Label, FirePHP_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dumps key and variable to firebug server panel
|
||||
*
|
||||
* @see FirePHP::DUMP
|
||||
* @param string $Key
|
||||
* @param mixed $Variable
|
||||
* @return true
|
||||
*/
|
||||
function dump($Key, $Variable) {
|
||||
return FB::send($Variable, $Key, FirePHP_DUMP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a trace in the firebug console
|
||||
*
|
||||
* @see FirePHP::TRACE
|
||||
* @param string $Label
|
||||
* @return true
|
||||
*/
|
||||
function trace($Label) {
|
||||
return FB::send($Label, FirePHP_TRACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a table in the firebug console
|
||||
*
|
||||
* @see FirePHP::TABLE
|
||||
* @param string $Label
|
||||
* @param string $Table
|
||||
* @return true
|
||||
*/
|
||||
function table($Label, $Table) {
|
||||
return FB::send($Table, $Label, FirePHP_TABLE);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
{
|
||||
"uid": "https://github.com/firephp/firephp-core/",
|
||||
"name": "firephp-core",
|
||||
"version": "0.4.0",
|
||||
"label": "FirePHP Server Library",
|
||||
"repositories": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "git://github.com/firephp/firephp-core.git"
|
||||
}
|
||||
],
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Christoph Dorn",
|
||||
"email": "christoph@christophdorn.com",
|
||||
"web": "http://www.christophdorn.com/",
|
||||
"alias": {
|
||||
"github": "cadorn"
|
||||
}
|
||||
}
|
||||
],
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Christoph Dorn",
|
||||
"email": "christoph@christophdorn.com",
|
||||
"web": "http://www.christophdorn.com/",
|
||||
"alias": {
|
||||
"github": "cadorn"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Michael Day",
|
||||
"email": "manveru.alma@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Sokolov Innokenty",
|
||||
"email": "sokolov.innokenty@gmail.com",
|
||||
"alias": {
|
||||
"github": "qbbr"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"extends": {
|
||||
"location": "./workspace/program.json"
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
set_include_path(dirname(dirname(dirname(__FILE__))).'/lib'.PATH_SEPARATOR.get_include_path());
|
||||
require('FirePHPCore/fb.php');
|
||||
|
||||
|
||||
fb('Hello\nWorld');
|
||||
fb(array('Hello\nWorld'));
|
||||
fb(array('Table cell with newline',array(
|
||||
array('Header'),
|
||||
array('Hello\nWorld'),
|
||||
)),FirePHP::TABLE);
|
||||
@@ -1,181 +0,0 @@
|
||||
<?php
|
||||
|
||||
class FirePHPCore_FirePHPTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @issue http://code.google.com/p/firephp/issues/detail?id=117
|
||||
*/
|
||||
public function testDumpArguments()
|
||||
{
|
||||
$firephp = new FirePHP_Test_Class();
|
||||
|
||||
$firephp->dump("key", "value");
|
||||
$headers = $firephp->_getHeaders();
|
||||
$this->assertEquals('15|{"key":"value"}|', $headers['X-Wf-1-2-1-1']);
|
||||
$firephp->_clearHeaders();
|
||||
|
||||
$caught = false;
|
||||
try {
|
||||
$firephp->dump(array(), "value");
|
||||
} catch(Exception $e) {
|
||||
// Key passed to dump() is not a string
|
||||
$caught = true;
|
||||
}
|
||||
if(!$caught) $this->fail('No exception thrown');
|
||||
|
||||
$caught = false;
|
||||
try {
|
||||
$firephp->dump("key \n\r value", "value");
|
||||
} catch(Exception $e) {
|
||||
// Key passed to dump() contains invalid characters [a-zA-Z0-9-_\.:]
|
||||
$caught = true;
|
||||
}
|
||||
if(!$caught) $this->fail('No exception thrown');
|
||||
|
||||
$caught = false;
|
||||
try {
|
||||
$firephp->dump("keykeykeykkeykeykeykkeykeykeykkeykeykeykkeykeykeykkeykeykeykkeykeykeykkeykeykeykkeykeykeykkeykeykeyk1", "value");
|
||||
} catch(Exception $e) {
|
||||
// Key passed to dump() is longer than 100 characters
|
||||
$caught = true;
|
||||
}
|
||||
if(!$caught) $this->fail('No exception thrown');
|
||||
}
|
||||
|
||||
/**
|
||||
* @issue http://code.google.com/p/firephp/issues/detail?id=123
|
||||
*/
|
||||
public function testRegisterErrorHandler()
|
||||
{
|
||||
$firephp = new FirePHP_Test_Class();
|
||||
$firephp->setOption("maxObjectDepth", 1);
|
||||
$firephp->setOption("maxArrayDepth", 1);
|
||||
|
||||
$firephp->registerErrorHandler();
|
||||
trigger_error("Hello World");
|
||||
$headers = $firephp->_getHeaders();
|
||||
if(!isset($headers["X-Wf-1-1-1-1"])) {
|
||||
$this->fail("Error not in headers");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @issue http://code.google.com/p/firephp/issues/detail?id=122
|
||||
*/
|
||||
public function testFirePHPClassInstanceLogging()
|
||||
{
|
||||
$firephp = new FirePHP_Test_Class();
|
||||
|
||||
$firephp->log($firephp);
|
||||
$headers = $firephp->_getHeaders();
|
||||
if(!preg_match_all('/"protected:objectStack":"\\*\\* Excluded by Filter \\*\\*"/', $headers['X-Wf-1-1-1-1'], $m)) {
|
||||
$this->fail("objectStack member contains value");
|
||||
}
|
||||
if(!preg_match_all('/"protected:static:instance":"\\*\\* Excluded by Filter \\*\\*"/', $headers['X-Wf-1-1-1-1'], $m)) {
|
||||
$this->fail("instance member should not be logged");
|
||||
}
|
||||
if(!preg_match_all('/"undeclared:json_objectStack":"\\*\\* Excluded by Filter \\*\\*"/', $headers['X-Wf-1-1-1-1'], $m)) {
|
||||
$this->fail("json_objectStack member should not be logged");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @issue http://code.google.com/p/firephp/issues/detail?id=114
|
||||
*/
|
||||
public function testCustomFileLineOptions()
|
||||
{
|
||||
$firephp = new FirePHP_Test_Class();
|
||||
|
||||
$firephp->log("message", "label", array("File"=>"/file/path", "Line"=>"1"));
|
||||
$firephp->info("message", "label", array("File"=>"/file/path", "Line"=>"1"));
|
||||
$firephp->warn("message", "label", array("File"=>"/file/path", "Line"=>"1"));
|
||||
$firephp->error("message", "label", array("File"=>"/file/path", "Line"=>"1"));
|
||||
$firephp->dump("key", "value", array("File"=>"/file/path", "Line"=>"1"));
|
||||
$firephp->table("label", array(array("header"),array("cell")), array("File"=>"/file/path", "Line"=>"1"));
|
||||
|
||||
$headers = $firephp->_getHeaders();
|
||||
|
||||
$this->assertEquals('75|[{"File":"\/file\/path","Line":"1","Type":"LOG","Label":"label"},"message"]|', $headers['X-Wf-1-1-1-1']);
|
||||
$this->assertEquals('76|[{"File":"\/file\/path","Line":"1","Type":"INFO","Label":"label"},"message"]|', $headers['X-Wf-1-1-1-2']);
|
||||
$this->assertEquals('76|[{"File":"\/file\/path","Line":"1","Type":"WARN","Label":"label"},"message"]|', $headers['X-Wf-1-1-1-3']);
|
||||
$this->assertEquals('77|[{"File":"\/file\/path","Line":"1","Type":"ERROR","Label":"label"},"message"]|', $headers['X-Wf-1-1-1-4']);
|
||||
$this->assertEquals('15|{"key":"value"}|', $headers['X-Wf-1-2-1-5']);
|
||||
$this->assertEquals('89|[{"File":"\/file\/path","Line":"1","Type":"TABLE","Label":"label"},[["header"],["cell"]]]|', $headers['X-Wf-1-1-1-6']);
|
||||
}
|
||||
|
||||
public function testRecursiveEncode()
|
||||
{
|
||||
$firephp = new FirePHP_Test_Class();
|
||||
|
||||
$obj = new FirePHPCore_FirePHPTest__TestObject();
|
||||
$obj->child = $obj;
|
||||
|
||||
$firephp->log($obj, "label", array("File"=>"/file/path", "Line"=>"1"));
|
||||
$headers = $firephp->_getHeaders();
|
||||
$this->assertEquals('215|[{"File":"\/file\/path","Line":"1","Type":"LOG","Label":"label"},{"__className":"FirePHPCore_FirePHPTest__TestObject","public:var":"value","undeclared:child":"** Recursion (FirePHPCore_FirePHPTest__TestObject) **"}]|', $headers['X-Wf-1-1-1-1']);
|
||||
}
|
||||
|
||||
public function testOptions()
|
||||
{
|
||||
$firephp = new FirePHP_Test_Class();
|
||||
|
||||
// defaults
|
||||
$this->assertEquals(5, $firephp->getOption("maxObjectDepth"));
|
||||
$this->assertEquals(5, $firephp->getOption("maxArrayDepth"));
|
||||
$this->assertEquals(true, $firephp->getOption("useNativeJsonEncode"));
|
||||
$this->assertEquals(true, $firephp->getOption("includeLineNumbers"));
|
||||
|
||||
// modify
|
||||
$firephp->setOption("maxObjectDepth", 1);
|
||||
$this->assertEquals(1, $firephp->getOption("maxObjectDepth"));
|
||||
|
||||
// invalid
|
||||
$caught = false;
|
||||
try {
|
||||
$firephp->setOption("invalidName", 1);
|
||||
} catch(Exception $e) {
|
||||
$caught = true;
|
||||
}
|
||||
if(!$caught) $this->fail('No exception thrown');
|
||||
|
||||
$caught = false;
|
||||
try {
|
||||
$firephp->getOption("invalidName");
|
||||
} catch(Exception $e) {
|
||||
$caught = true;
|
||||
}
|
||||
if(!$caught) $this->fail('No exception thrown');
|
||||
}
|
||||
|
||||
public function testDeprecatedMethods()
|
||||
{
|
||||
$firephp = new FirePHP_Test_Class();
|
||||
|
||||
$caught = false;
|
||||
try {
|
||||
$firephp->setProcessorUrl('URL');
|
||||
} catch(Exception $e) {
|
||||
$caught = true;
|
||||
$this->assertEquals(E_USER_DEPRECATED, $e->getCode());
|
||||
$this->assertEquals('The FirePHP::setProcessorUrl() method is no longer supported', $e->getMessage());
|
||||
}
|
||||
if(!$caught) $this->fail('No deprecation error thrown');
|
||||
|
||||
$caught = false;
|
||||
try {
|
||||
$firephp->setRendererUrl('URL');
|
||||
} catch(Exception $e) {
|
||||
$caught = true;
|
||||
$this->assertEquals(E_USER_DEPRECATED, $e->getCode());
|
||||
$this->assertEquals('The FirePHP::setRendererUrl() method is no longer supported', $e->getMessage());
|
||||
}
|
||||
if(!$caught) $this->fail('No deprecation error thrown');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class FirePHPCore_FirePHPTest__TestObject
|
||||
{
|
||||
public $var = "value";
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
function __autoload__($class)
|
||||
{
|
||||
if (strpos($class, 'FirePHPCore') !== 0 && $class != 'FirePHP') {
|
||||
return;
|
||||
}
|
||||
|
||||
$basePath = dirname(dirname(__FILE__)) . '/lib';
|
||||
if (!file_exists($basePath)) {
|
||||
$basePath = dirname(dirname(dirname(dirname(__FILE__)))) . '/lib';
|
||||
}
|
||||
|
||||
if ($class == 'FirePHP') {
|
||||
$class = 'FirePHPCore/FirePHP.class';
|
||||
}
|
||||
|
||||
// find relative
|
||||
if (file_exists($file = $basePath . '/' . str_replace('_', '/', $class) . '.php')) {
|
||||
require_once($file);
|
||||
}
|
||||
}
|
||||
|
||||
spl_autoload_register('__autoload__');
|
||||
|
||||
class FirePHP_Test_Class extends FirePHP {
|
||||
|
||||
private $_headers = array();
|
||||
|
||||
|
||||
public function _getHeaders() {
|
||||
return $this->_headers;
|
||||
}
|
||||
public function _clearHeaders() {
|
||||
$this->_headers = array();
|
||||
}
|
||||
|
||||
|
||||
// ######################
|
||||
// # Subclassed Methods #
|
||||
// ######################
|
||||
|
||||
protected function setHeader($Name, $Value) {
|
||||
$this->_headers[$Name] = $Value;
|
||||
}
|
||||
|
||||
protected function headersSent(&$Filename, &$Linenum) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function detectClientExtension() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
<phpunit bootstrap="TestHelper.php">
|
||||
</phpunit>
|
||||
@@ -1,19 +0,0 @@
|
||||
|
||||
The [PINF JavaScript Loader](https://github.com/pinf/loader-js) is used to provide a development environment and package releases for this project.
|
||||
|
||||
**NOTE:** It is assumed you have the _PINF JavaScript Loader_ mapped to the `commonjs` command and are using the `node` platform by default as explained [here](https://github.com/pinf/loader-js/blob/master/docs/Setup.md).
|
||||
|
||||
|
||||
Publishing
|
||||
==========
|
||||
|
||||
git tag v...
|
||||
|
||||
commonjs -v --script build .
|
||||
|
||||
commonjs -v --script publish .
|
||||
|
||||
|
||||
TODO: Auto-upload to PEAR channel server at http://pear.firephp.org/
|
||||
|
||||
NOTE: For PEAR RC releases: Change release stability to "beta" and capitalize "RC" in release version in package.xml
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
exports.main = function(options)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"name": "firephp-core",
|
||||
"engine": [
|
||||
"node"
|
||||
],
|
||||
"main": "lib/project.js",
|
||||
"scripts": {
|
||||
"build": {
|
||||
"location": "./",
|
||||
"module": "/scripts/build.js"
|
||||
},
|
||||
"publish": {
|
||||
"location": "./",
|
||||
"module": "/scripts/publish.js"
|
||||
}
|
||||
},
|
||||
"mappings": {
|
||||
"nodejs": {
|
||||
"id": "nodejs.org/"
|
||||
},
|
||||
"pinf": {
|
||||
"id": "pinf.org/loader/"
|
||||
},
|
||||
"modules": {
|
||||
"id": "github.com/pinf/modules-js/"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
{
|
||||
"boot": "workspace",
|
||||
"engine": [
|
||||
"node"
|
||||
],
|
||||
"packages": {
|
||||
"workspace": {
|
||||
"locator": {
|
||||
"location": "./"
|
||||
}
|
||||
},
|
||||
"nodejs.org/": {
|
||||
"provider": "nodejs.org/"
|
||||
},
|
||||
"pinf.org/loader/": {
|
||||
"provider": "pinf.org/loader/"
|
||||
},
|
||||
"github.com/pinf/modules-js/": {
|
||||
"locator": {
|
||||
"archive": "https://github.com/pinf/modules-js/zipball/master"
|
||||
}
|
||||
},
|
||||
"github.com/kriskowal/q/": {
|
||||
"locator": {
|
||||
"archive": "https://github.com/kriskowal/q/zipball/v0.3.0"
|
||||
},
|
||||
"descriptor": {
|
||||
"uid": "https://github.com/kriskowal/q/",
|
||||
"dependencies": [
|
||||
{
|
||||
"id": "github.com/pinf/modules-js/"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"private-registry.appspot.com/cadorn.com/github/com.cadorn.baby/projects/sourcemint/packages/client-js/": {
|
||||
"locator": {
|
||||
"archive": "https://github.com/cadorn/com.cadorn.baby/zipball/master",
|
||||
"path": "projects/sourcemint/packages/client-js"
|
||||
}
|
||||
},
|
||||
"github.com/cadorn/aws-lib/": {
|
||||
"locator": {
|
||||
"archive": "https://github.com/cadorn/aws-lib/zipball/master"
|
||||
},
|
||||
"descriptor": {
|
||||
"uid": "https://github.com/cadorn/aws-lib/",
|
||||
"native": true,
|
||||
"dependencies": [
|
||||
{
|
||||
"id": "registry.npmjs.org/sax/"
|
||||
},
|
||||
{
|
||||
"id": "registry.npmjs.org/xml2js/"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"registry.npmjs.org/sax/": {
|
||||
"locator": {
|
||||
"archive": "http://registry.npmjs.org/sax/-/sax-0.1.2.tgz"
|
||||
},
|
||||
"descriptor": {
|
||||
"uid": "http://registry.npmjs.org/sax/",
|
||||
"native": true
|
||||
}
|
||||
},
|
||||
"registry.npmjs.org/xml2js/": {
|
||||
"locator": {
|
||||
"archive": "http://registry.npmjs.org/xml2js/-/xml2js-0.1.6.tgz"
|
||||
},
|
||||
"descriptor": {
|
||||
"uid": "http://registry.npmjs.org/xml2js/",
|
||||
"native": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
|
||||
var FILE = require("modules/file"),
|
||||
Q = require("modules/q"),
|
||||
SYSTEM = require("modules/system"),
|
||||
UTIL = require("modules/util"),
|
||||
JSON = require("modules/json");
|
||||
|
||||
|
||||
var pkgPath = FILE.dirname(FILE.dirname(FILE.dirname(module.id))),
|
||||
buildPath = pkgPath + "/build",
|
||||
tplPath = pkgPath + "/workspace/tpl",
|
||||
version = false;
|
||||
|
||||
exports.getBuildPath = function()
|
||||
{
|
||||
return buildPath;
|
||||
}
|
||||
|
||||
exports.main = function()
|
||||
{
|
||||
|
||||
SYSTEM.exec("rm -Rf " + buildPath, function()
|
||||
{
|
||||
FILE.mkdirs(buildPath, 0775);
|
||||
|
||||
SYSTEM.exec("git tag", function(stdout)
|
||||
{
|
||||
version = UTIL.trim(stdout).split("\n").pop().match(/^v(.*)$/)[1];
|
||||
|
||||
// TODO: Compare against version in `../../program.json ~ version` (ensure =)
|
||||
|
||||
module.print("\0cyan(Building version: " + version + "\0)\n");
|
||||
|
||||
buildZipArchive(function()
|
||||
{
|
||||
buildPEARArchive(function()
|
||||
{
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function done()
|
||||
{
|
||||
module.print("\0green(Done\0)\n");
|
||||
}
|
||||
}
|
||||
|
||||
function buildZipArchive(callback)
|
||||
{
|
||||
var targetBasePath = buildPath + "/FirePHPCore-" + version;
|
||||
|
||||
FILE.mkdirs(targetBasePath, 0775);
|
||||
|
||||
SYSTEM.exec("rsync -r --copy-links --exclude \"- .DS_Store\" --exclude \"- .git/\" --exclude \"- .tmp_*\" " + pkgPath + "/lib " + targetBasePath, function()
|
||||
{
|
||||
replaceVariablesInFile(targetBasePath + "/lib/FirePHPCore/FirePHP.class.php");
|
||||
replaceVariablesInFile(targetBasePath + "/lib/FirePHPCore/FirePHP.class.php4");
|
||||
|
||||
SYSTEM.exec("cp -Rf " + pkgPath + "/examples " + targetBasePath, function()
|
||||
{
|
||||
next1();
|
||||
});
|
||||
});
|
||||
|
||||
function next1()
|
||||
{
|
||||
var content = FILE.read(tplPath + "/readme.tpl.md");
|
||||
content = content.replace(/%%VERSION%%/g, version);
|
||||
FILE.write(targetBasePath + "/README.md", content);
|
||||
|
||||
var content = FILE.read(tplPath + "/license.tpl.md");
|
||||
FILE.write(targetBasePath + "/LICENSE.md", content);
|
||||
|
||||
FILE.write(buildPath + "/info.json", JSON.encode({
|
||||
version: version
|
||||
}));
|
||||
|
||||
next2();
|
||||
}
|
||||
|
||||
function next2()
|
||||
{
|
||||
SYSTEM.exec("cd " + buildPath + " ; zip -vr FirePHPCore-" + version + ".zip FirePHPCore-" + version, function(stdout)
|
||||
{
|
||||
console.log(stdout);
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function buildPEARArchive(callback)
|
||||
{
|
||||
var targetBasePath = buildPath + "/pear";
|
||||
|
||||
FILE.mkdirs(targetBasePath, 0775);
|
||||
|
||||
SYSTEM.exec("rsync -r --copy-links --exclude \"- .DS_Store\" --exclude \"- .git/\" --exclude \"- .tmp_*\" " + pkgPath + "/lib/FirePHPCore/* " + targetBasePath, function()
|
||||
{
|
||||
replaceVariablesInFile(targetBasePath + "/FirePHP.class.php");
|
||||
replaceVariablesInFile(targetBasePath + "/FirePHP.class.php4");
|
||||
|
||||
next1();
|
||||
});
|
||||
|
||||
function next1()
|
||||
{
|
||||
var content = FILE.read(tplPath + "/pear.package.tpl.xml");
|
||||
|
||||
var date = new Date();
|
||||
content = content.replace(/%%DATE%%/g, date.getFullYear() + "-" + UTIL.padBegin(date.getMonth()+1, 2, "0") + "-" + date.getDate());
|
||||
content = content.replace(/%%VERSION%%/g, version);
|
||||
content = content.replace(/%%STABILITY%%/g, "stable");
|
||||
|
||||
FILE.write(targetBasePath + "/package.xml", content);
|
||||
|
||||
next2();
|
||||
}
|
||||
|
||||
function next2()
|
||||
{
|
||||
SYSTEM.exec("pear channel-discover pear.firephp.org", function(stdout)
|
||||
{
|
||||
console.log(stdout);
|
||||
|
||||
SYSTEM.exec("cd " + targetBasePath + "; pear package package.xml", function(stdout)
|
||||
{
|
||||
console.log(stdout);
|
||||
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function replaceVariablesInFile(path)
|
||||
{
|
||||
var content = FILE.read(path);
|
||||
|
||||
// @pinf replace '0.3' with '%%VERSION%%'
|
||||
var re1 = /\n(.*)\/\/\s*@pinf\s(.*)\n/g;
|
||||
var match1;
|
||||
while (match1 = re1.exec(content)) {
|
||||
var rule = match1[2].match(/^replace (.*?) with (.*)$/);
|
||||
if(rule) {
|
||||
// replace variables in rule
|
||||
var re2 = /%%([^%]*)%%/g;
|
||||
var match2;
|
||||
while (match2 = re2.exec(rule[2])) {
|
||||
var value;
|
||||
if(match2[1]=="VERSION") {
|
||||
value = version;
|
||||
}
|
||||
rule[2] = rule[2].replace(match2[0], value);
|
||||
}
|
||||
match1[1] = match1[1].replace(rule[1], rule[2]);
|
||||
content = content.replace(match1[0], "\n"+match1[1]+"\n");
|
||||
}
|
||||
}
|
||||
|
||||
FILE.write(path, content);
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
|
||||
var PINF_LOADER = require("pinf/loader"),
|
||||
SANDBOX = PINF_LOADER.getSandbox(),
|
||||
FILE = require("modules/file"),
|
||||
Q = require("modules/q"),
|
||||
SYSTEM = require("modules/system"),
|
||||
BUILD = require("./build"),
|
||||
JSON = require("modules/json"),
|
||||
SOURCEMINT_CLIENT = false;
|
||||
|
||||
exports.main = function()
|
||||
{
|
||||
module.load({
|
||||
id: "private-registry.appspot.com/cadorn.com/github/com.cadorn.baby/projects/sourcemint/packages/client-js/",
|
||||
descriptor: {
|
||||
main: "lib/client.js"
|
||||
}
|
||||
}, function(id)
|
||||
{
|
||||
SOURCEMINT_CLIENT = require(id);
|
||||
|
||||
publish();
|
||||
});
|
||||
}
|
||||
|
||||
function publish()
|
||||
{
|
||||
var buildPath = BUILD.getBuildPath(),
|
||||
info = JSON.decode(FILE.read(buildPath + "/info.json")),
|
||||
descriptor = JSON.decode(FILE.read(FILE.dirname(FILE.dirname(FILE.dirname(module.id))) + "/package.json"));
|
||||
|
||||
var bundles = {};
|
||||
bundles["firephp-core.zip"] = {
|
||||
"type": "zip",
|
||||
"options": {
|
||||
"archivePath": buildPath + "/FirePHPCore-" + info.version + ".zip",
|
||||
}
|
||||
};
|
||||
|
||||
var packages = [
|
||||
{
|
||||
"uid": descriptor.uid,
|
||||
"stream": "stable",
|
||||
"version": info.version,
|
||||
"bundles": bundles
|
||||
}
|
||||
];
|
||||
|
||||
try
|
||||
{
|
||||
Q.when(SOURCEMINT_CLIENT.publish(packages), function(info)
|
||||
{
|
||||
module.print("\0green(Published:\n");
|
||||
console.log(info);
|
||||
module.print("\0)");
|
||||
}, function(e)
|
||||
{
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
console.error("Error: " + e);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
[MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
|
||||
Copyright (c) 2007+ [Christoph Dorn](http://www.christophdorn.com/)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -1,61 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<package packagerversion="1.7.1"
|
||||
version="2.0"
|
||||
xmlns="http://pear.php.net/dtd/package-2.0"
|
||||
xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
|
||||
|
||||
<name>FirePHPCore</name>
|
||||
<channel>pear.firephp.org</channel>
|
||||
<summary>Log variables from PHP to the browser (Firebug Console)</summary>
|
||||
<description>Handles all communication between the PHP code on the server and the client. Also implements all core FirePHP features.</description>
|
||||
|
||||
<lead>
|
||||
<name>Christoph Dorn</name>
|
||||
<user>cadorn</user>
|
||||
<email>christoph@christophdorn.com</email>
|
||||
<active>yes</active>
|
||||
</lead>
|
||||
|
||||
<date>%%DATE%%</date>
|
||||
<version>
|
||||
<release>%%VERSION%%</release>
|
||||
<api>0.3</api>
|
||||
</version>
|
||||
|
||||
<stability>
|
||||
<release>%%STABILITY%%</release>
|
||||
<api>stable</api>
|
||||
</stability>
|
||||
|
||||
<license>MIT</license>
|
||||
|
||||
<notes>No Notes</notes>
|
||||
|
||||
<contents>
|
||||
<dir name="/" baseinstalldir="FirePHPCore">
|
||||
|
||||
<file name="fb.php" role="php"/>
|
||||
<file name="fb.php4" role="php"/>
|
||||
|
||||
<file name="FirePHP.class.php" role="php"/>
|
||||
<file name="FirePHP.class.php4" role="php"/>
|
||||
|
||||
</dir>
|
||||
</contents>
|
||||
|
||||
<dependencies>
|
||||
<required>
|
||||
<php>
|
||||
<min>4.0</min>
|
||||
</php>
|
||||
<pearinstaller>
|
||||
<min>1.4.5</min>
|
||||
</pearinstaller>
|
||||
</required>
|
||||
</dependencies>
|
||||
|
||||
<phprelease />
|
||||
|
||||
</package>
|
||||
@@ -1,17 +0,0 @@
|
||||
FirePHPCore Server Library
|
||||
==========================
|
||||
|
||||
Status: stable
|
||||
|
||||
Version: [%%VERSION%%](https://github.com/firephp/firephp-core/tree/v%%VERSION%%)
|
||||
|
||||
This archive contains the *FirePHPCore* PHP server library.
|
||||
|
||||
Links
|
||||
-----
|
||||
|
||||
* Documentation: http://docs.sourcemint.org/firephp.org/firephp/1/-docs/
|
||||
* Install: http://docs.sourcemint.org/firephp.org/firephp/1/-docs/Configuration/Traditional
|
||||
* Support: http://docs.sourcemint.org/firephp.org/firephp/1/-docs/OpenSource#support
|
||||
* Author: [Christoph Dorn](http://www.christophdorn.com/)
|
||||
* License: [MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "raven-js",
|
||||
"version": "1.1.19",
|
||||
"dependencies": {},
|
||||
"main": "dist/raven.js",
|
||||
"ignore": {},
|
||||
"homepage": "https://github.com/getsentry/raven-js",
|
||||
"_release": "1.1.19",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "1.1.19",
|
||||
"commit": "82b9c07b7545c6c10e297709a741eaa9b75f64e8"
|
||||
},
|
||||
"_source": "git://github.com/getsentry/raven-js.git",
|
||||
"_target": "~1.1.19",
|
||||
"_originalSource": "raven-js",
|
||||
"_direct": true
|
||||
}
|
||||
22
htdocs/includes/raven-js/.gitignore
vendored
22
htdocs/includes/raven-js/.gitignore
vendored
@@ -1,22 +0,0 @@
|
||||
.DS_Store
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear on external disk
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
|
||||
docs/html
|
||||
docs/doctrees
|
||||
|
||||
build
|
||||
node_modules
|
||||
npm-debug.log
|
||||
|
||||
scratch/
|
||||
|
||||
*.pyc
|
||||
|
||||
.idea
|
||||
aws.json
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"es3": true,
|
||||
"globalstrict": true,
|
||||
"browser": true,
|
||||
"predef": [
|
||||
"TraceKit",
|
||||
"console"
|
||||
]
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
# language doesn't matter, we're only using phantom.js
|
||||
language: node_js
|
||||
node_js:
|
||||
- "0.10"
|
||||
script:
|
||||
- ./node_modules/.bin/grunt test build
|
||||
notifications:
|
||||
irc: "irc.freenode.org#sentry"
|
||||
@@ -1 +0,0 @@
|
||||
https://github.com/getsentry/raven-js/graphs/contributors
|
||||
@@ -1,254 +0,0 @@
|
||||
module.exports = function(grunt) {
|
||||
"use strict";
|
||||
|
||||
var _ = require('lodash');
|
||||
var path = require('path');
|
||||
|
||||
var coreFiles = [
|
||||
'template/_header.js',
|
||||
'vendor/**/*.js',
|
||||
'src/**/*.js',
|
||||
'template/_footer.js'
|
||||
];
|
||||
|
||||
var plugins = grunt.option('plugins');
|
||||
// Create plugin paths and verify hey exist
|
||||
plugins = _.map(plugins ? plugins.split(',') : [], function (plugin) {
|
||||
var path = 'plugins/' + plugin + '.js';
|
||||
|
||||
if(!grunt.file.exists(path))
|
||||
throw new Error("Plugin '" + plugin + "' not found in plugins directory.");
|
||||
|
||||
return path;
|
||||
});
|
||||
|
||||
// Taken from http://dzone.com/snippets/calculate-all-combinations
|
||||
var combine = function (a) {
|
||||
var fn = function (n, src, got, all) {
|
||||
if (n === 0) {
|
||||
all.push(got);
|
||||
return;
|
||||
}
|
||||
|
||||
for (var j = 0; j < src.length; j++) {
|
||||
fn(n - 1, src.slice(j + 1), got.concat([src[j]]), all);
|
||||
}
|
||||
};
|
||||
|
||||
var all = [a];
|
||||
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
fn(i, a, [], all);
|
||||
}
|
||||
|
||||
return all;
|
||||
};
|
||||
|
||||
var pluginCombinations = combine(grunt.file.expand('plugins/*.js'));
|
||||
var pluginConcatFiles = _.reduce(pluginCombinations, function (dict, comb) {
|
||||
var key = _.map(comb, function (plugin) {
|
||||
return path.basename(plugin, '.js');
|
||||
});
|
||||
key.sort();
|
||||
|
||||
var dest = path.join('build/', key.join(','), '/raven.js');
|
||||
dict[dest] = coreFiles.concat(comb);
|
||||
|
||||
return dict;
|
||||
}, {});
|
||||
|
||||
var gruntConfig = {
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
aws: grunt.file.exists('aws.json') ? grunt.file.readJSON('aws.json'): {},
|
||||
|
||||
clean: ['build'],
|
||||
concat: {
|
||||
options: {
|
||||
separator: '\n',
|
||||
banner: grunt.file.read('template/_copyright.js'),
|
||||
process: true
|
||||
},
|
||||
core: {
|
||||
src: coreFiles.concat(plugins),
|
||||
dest: 'build/raven.js'
|
||||
},
|
||||
all: {
|
||||
files: pluginConcatFiles
|
||||
}
|
||||
},
|
||||
|
||||
uglify: {
|
||||
options: {
|
||||
sourceMap: function (dest) {
|
||||
return path.join(path.dirname(dest),
|
||||
path.basename(dest, '.js')) +
|
||||
'.map';
|
||||
},
|
||||
sourceMappingURL: function (dest) {
|
||||
return path.basename(dest, '.js') + '.map';
|
||||
},
|
||||
preserveComments: 'some'
|
||||
},
|
||||
dist: {
|
||||
src: ['build/**/*.js'],
|
||||
ext: '.min.js',
|
||||
expand: true
|
||||
}
|
||||
},
|
||||
|
||||
fixSourceMaps: {
|
||||
all: ['build/**/*.map']
|
||||
},
|
||||
|
||||
jshint: {
|
||||
options: {
|
||||
jshintrc: '.jshintrc'
|
||||
},
|
||||
all: ['Gruntfile.js', 'src/**/*.js', 'plugins/**/*.js']
|
||||
},
|
||||
|
||||
mocha: {
|
||||
all: {
|
||||
options: {
|
||||
mocha: {
|
||||
ignoreLeaks: true,
|
||||
grep: grunt.option('grep')
|
||||
},
|
||||
log: true,
|
||||
reporter: 'Dot',
|
||||
run: true
|
||||
},
|
||||
src: ['test/index.html'],
|
||||
nonull: true
|
||||
}
|
||||
},
|
||||
|
||||
release: {
|
||||
options: {
|
||||
npm: false,
|
||||
commitMessage: 'Release <%= version %>'
|
||||
}
|
||||
},
|
||||
|
||||
s3: {
|
||||
options: {
|
||||
key: '<%= aws.key %>',
|
||||
secret: '<%= aws.secret %>',
|
||||
bucket: '<%= aws.bucket %>',
|
||||
access: 'public-read',
|
||||
// Limit concurrency
|
||||
maxOperations: 20,
|
||||
headers: {
|
||||
// Surrogate-Key header for Fastly to purge by release
|
||||
'x-amz-meta-surrogate-key': '<%= pkg.release %>'
|
||||
}
|
||||
},
|
||||
all: {
|
||||
upload: [{
|
||||
src: 'build/**/*',
|
||||
dest: '<%= pkg.release %>/',
|
||||
rel: 'build/'
|
||||
}]
|
||||
}
|
||||
},
|
||||
|
||||
connect: {
|
||||
test: {
|
||||
options: {
|
||||
port: 8000,
|
||||
debug: true,
|
||||
keepalive: true
|
||||
}
|
||||
},
|
||||
|
||||
docs: {
|
||||
options: {
|
||||
port: 8000,
|
||||
debug: true,
|
||||
base: 'docs/html',
|
||||
keepalive: true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
copy: {
|
||||
dist: {
|
||||
expand: true,
|
||||
flatten: true,
|
||||
cwd: 'build/',
|
||||
src: '**',
|
||||
dest: 'dist/'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
grunt.initConfig(gruntConfig);
|
||||
|
||||
// Custom Grunt tasks
|
||||
grunt.registerTask('version', function() {
|
||||
var pkg = grunt.config.get('pkg');
|
||||
if (grunt.option('dev')) {
|
||||
pkg.release = 'dev';
|
||||
pkg.version = grunt.config.get('gitinfo').local.branch.current.shortSHA;
|
||||
} else {
|
||||
pkg.release = pkg.version;
|
||||
}
|
||||
grunt.config.set('pkg', pkg);
|
||||
});
|
||||
|
||||
grunt.registerMultiTask('fixSourceMaps', function () {
|
||||
this.files.forEach(function (f) {
|
||||
var result;
|
||||
var sources = f.src.filter(function (filepath) {
|
||||
if (!grunt.file.exists(filepath)) {
|
||||
grunt.log.warn('Source file "' + filepath + '" not found.');
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}).forEach(function (filepath) {
|
||||
var base = path.dirname(filepath);
|
||||
var sMap = grunt.file.readJSON(filepath);
|
||||
sMap.file = path.relative(base, sMap.file);
|
||||
sMap.sources = _.map(sMap.sources, path.relative.bind(path, base));
|
||||
|
||||
grunt.file.write(filepath, JSON.stringify(sMap));
|
||||
// Print a success message.
|
||||
grunt.log.writeln('File "' + filepath + '" fixed.');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Grunt contrib tasks
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-connect');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
|
||||
// 3rd party Grunt tasks
|
||||
grunt.loadNpmTasks('grunt-mocha');
|
||||
grunt.loadNpmTasks('grunt-release');
|
||||
grunt.loadNpmTasks('grunt-s3');
|
||||
grunt.loadNpmTasks('grunt-gitinfo');
|
||||
|
||||
// Build tasks
|
||||
grunt.registerTask('_prep', ['clean', 'gitinfo', 'version']);
|
||||
grunt.registerTask('concat.core', ['_prep', 'concat:core']);
|
||||
grunt.registerTask('concat.all', ['_prep', 'concat:all']);
|
||||
grunt.registerTask('build.core', ['concat.core', 'uglify', 'fixSourceMaps']);
|
||||
grunt.registerTask('build.all', ['concat.all', 'uglify', 'fixSourceMaps']);
|
||||
grunt.registerTask('build', ['build.all']);
|
||||
grunt.registerTask('dist', ['build.core', 'copy:dist']);
|
||||
|
||||
// Test task
|
||||
grunt.registerTask('test', ['jshint', 'mocha']);
|
||||
|
||||
// Webserver tasks
|
||||
grunt.registerTask('run:test', ['connect:test']);
|
||||
grunt.registerTask('run:docs', ['connect:docs']);
|
||||
|
||||
grunt.registerTask('publish', ['test', 'build.all', 's3']);
|
||||
grunt.registerTask('default', ['test']);
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
Copyright (c) 2014 Matt Robenolt and other contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,20 +0,0 @@
|
||||
develop: update-submodules
|
||||
npm install .
|
||||
|
||||
update-submodules:
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
docs:
|
||||
cd docs; $(MAKE) html
|
||||
|
||||
docs-live:
|
||||
while true; do \
|
||||
sleep 2; \
|
||||
$(MAKE) docs; \
|
||||
done
|
||||
|
||||
clean:
|
||||
rm -rf docs/html
|
||||
|
||||
.PHONY: develop update-submodules docs docs-live clean
|
||||
@@ -1,13 +0,0 @@
|
||||
# Raven.js [](https://travis-ci.org/getsentry/raven-js)
|
||||
|
||||
Raven.js is a tiny standalone JavaScript client for [Sentry](https://www.getsentry.com/).
|
||||
|
||||
**Raven.js v1.1 requires Sentry v6.0 or later.**
|
||||
|
||||
## Resources
|
||||
|
||||
* [Download](http://ravenjs.com)
|
||||
* [Documentation](https://raven-js.readthedocs.org)
|
||||
* [Bug Tracker](https://github.com/getsentry/raven-js/issues)
|
||||
* [IRC](irc://chat.freenode.net/sentry) (chat.freenode.net, #sentry)
|
||||
* Follow [@mattrobenolt](https://twitter.com/mattrobenolt) on Twitter for updates
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "raven-js",
|
||||
"version": "1.1.19",
|
||||
"dependencies": {},
|
||||
"main": "dist/raven.js",
|
||||
"ignore": {}
|
||||
}
|
||||
1909
htdocs/includes/raven-js/dist/raven.js
vendored
1909
htdocs/includes/raven-js/dist/raven.js
vendored
File diff suppressed because it is too large
Load Diff
3
htdocs/includes/raven-js/dist/raven.min.js
vendored
3
htdocs/includes/raven-js/dist/raven.min.js
vendored
File diff suppressed because one or more lines are too long
1
htdocs/includes/raven-js/dist/raven.min.map
vendored
1
htdocs/includes/raven-js/dist/raven.min.map
vendored
File diff suppressed because one or more lines are too long
@@ -1,153 +0,0 @@
|
||||
# Makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = .
|
||||
|
||||
# Internal variables.
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
# the i18n builder cannot share the environment and doctrees with the others
|
||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " dirhtml to make HTML files named index.html in directories"
|
||||
@echo " singlehtml to make a single large HTML file"
|
||||
@echo " pickle to make pickle files"
|
||||
@echo " json to make JSON files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " qthelp to make HTML files and a qthelp project"
|
||||
@echo " devhelp to make HTML files and a Devhelp project"
|
||||
@echo " epub to make an epub"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
@echo " text to make text files"
|
||||
@echo " man to make manual pages"
|
||||
@echo " texinfo to make Texinfo files"
|
||||
@echo " info to make Texinfo files and run them through makeinfo"
|
||||
@echo " gettext to make PO message catalogs"
|
||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
dirhtml:
|
||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||
|
||||
singlehtml:
|
||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||
@echo
|
||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||
|
||||
pickle:
|
||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||
@echo
|
||||
@echo "Build finished; now you can process the pickle files."
|
||||
|
||||
json:
|
||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||
@echo
|
||||
@echo "Build finished; now you can process the JSON files."
|
||||
|
||||
htmlhelp:
|
||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||
|
||||
qthelp:
|
||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||
@echo
|
||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/raven-js.qhcp"
|
||||
@echo "To view the help file:"
|
||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/raven-js.qhc"
|
||||
|
||||
devhelp:
|
||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||
@echo
|
||||
@echo "Build finished."
|
||||
@echo "To view the help file:"
|
||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/raven-js"
|
||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/raven-js"
|
||||
@echo "# devhelp"
|
||||
|
||||
epub:
|
||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||
@echo
|
||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
latex:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo
|
||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||
"(use \`make latexpdf' here to do that automatically)."
|
||||
|
||||
latexpdf:
|
||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@echo "Running LaTeX files through pdflatex..."
|
||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||
|
||||
text:
|
||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||
@echo
|
||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
||||
texinfo:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo
|
||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
||||
"(use \`make info' here to do that automatically)."
|
||||
|
||||
info:
|
||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||
@echo "Running Texinfo files through makeinfo..."
|
||||
make -C $(BUILDDIR)/texinfo info
|
||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
||||
|
||||
gettext:
|
||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||
@echo
|
||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
||||
|
||||
changes:
|
||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||
@echo
|
||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||
|
||||
linkcheck:
|
||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||
@echo
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||
|
||||
doctest:
|
||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in $(BUILDDIR)/doctest/output.txt."
|
||||
@@ -1,138 +0,0 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
1.1.19
|
||||
~~~~~~
|
||||
* Use more compliant way of creating an Image in the dom. See: https://github.com/getsentry/raven-js/pull/334
|
||||
* `String` objects weren't getting identified as a string. See: https://github.com/getsentry/raven-js/pull/336
|
||||
* Expose getter/setter for dataCallback and shouldSendCallback
|
||||
* Better handle if/when the dataCallback returns garbage
|
||||
* Fix support for nodeunit. See: https://github.com/getsentry/raven-js/pull/338
|
||||
* Fix `console.warn` sending as a `warning` level to server. See: https://github.com/getsentry/raven-js/issues/342
|
||||
* Improve the capture of unhandled errors from promises in Ember plugin. See: https://github.com/getsentry/raven-js/pull/330
|
||||
|
||||
1.1.18
|
||||
~~~~~~
|
||||
* Fixed a trailing comma which would make IE8 cry. This affects the uncompressed builds only. Compressed builds were unaffected. See: https://github.com/getsentry/raven-js/pull/333
|
||||
|
||||
1.1.17
|
||||
~~~~~~
|
||||
* Better support for Angular errors. See: https://github.com/getsentry/raven-js/pull/238
|
||||
* Allow setting truncate length through ``globalOptions.maxMessageLength``. See: https://github.com/getsentry/raven-js/pull/246
|
||||
* Fixed the pattern for parsing gecko stacktraces. See: https://github.com/getsentry/raven-js/pull/252
|
||||
* Browserify support. See: https://github.com/getsentry/raven-js/pull/253, https://github.com/getsentry/raven-js/pull/260, https://github.com/getsentry/raven-js/pull/261
|
||||
* Start tracking ``session:duration`` automatically as metadata.
|
||||
* Fix globalOptions overwrite. See: https://github.com/getsentry/raven-js/pull/264
|
||||
* Better cross origin support. See: https://github.com/getsentry/raven-js/pull/276
|
||||
* Better anonymous function support in Chrome stack trace parsing. See: https://github.com/getsentry/raven-js/pull/290, https://github.com/getsentry/raven-js/pull/294
|
||||
* Remove deprecated ``site`` param.
|
||||
* New ``Raven.isSetup()``. See: https://github.com/getsentry/raven-js/pull/309
|
||||
* Better backbone.js support. See: https://github.com/getsentry/raven-js/pull/307
|
||||
* ``ignoreErrors`` now also is applied to ``captureMessage()``. See: https://github.com/getsentry/raven-js/pull/312
|
||||
* Capture unhandled errors from promises in Ember. See: https://github.com/getsentry/raven-js/pull/319
|
||||
* Add new support for ``releases``. See: https://github.com/getsentry/raven-js/issues/325
|
||||
|
||||
1.1.16
|
||||
~~~~~~
|
||||
* Fixed a bug that was preventing stack frames from ``raven.js`` from being hidden correctly. See: https://github.com/getsentry/raven-js/pull/216
|
||||
* Fixed an IE bug with the ``console`` plugin. See: https://github.com/getsentry/raven-js/issues/217
|
||||
* Added support for ``chrome-extension://`` protocol in Chrome in stack traces.
|
||||
* Added ``setExtraContext`` and ``setTagsContext``. See: https://github.com/getsentry/raven-js/pull/219
|
||||
* Renamed ``setUser`` to ``setUserContext`` to match. ``setUser`` still exists, but will be deprecated in a future release.
|
||||
* New ``backbone.js`` plugin. See: https://github.com/getsentry/raven-js/pull/220
|
||||
* Added support for ``chrome://`` protocol in Firefox in stack traces. See: https://github.com/getsentry/raven-js/pull/225
|
||||
* Ignore more garbage from IE cross origin errors. See: https://github.com/getsentry/raven-js/pull/224
|
||||
* Added ``Raven.debug`` to prevent logging to ``console`` when ``false``. Defaults to ``true`` for backwards compatability. See: https://github.com/getsentry/raven-js/pull/229
|
||||
* Prevent calling ``Raven.config()`` or ``Raven.install()`` twice. See: https://github.com/getsentry/raven-js/pull/233
|
||||
|
||||
1.1.15
|
||||
~~~~~~
|
||||
* Fix issues if a non-string were passed to ``Raven.captureMessage`` and non-Error objects were passed to ``Raven.captureException``.
|
||||
|
||||
1.1.14
|
||||
~~~~~~
|
||||
* Only filter normal Error objects without a message, not all of them. Turns out, people throw errors like this. Ahem, Underscore.js. See: https://github.com/jashkenas/underscore/pull/1589/files
|
||||
|
||||
1.1.13
|
||||
~~~~~~
|
||||
* Fixed a unicode issue in the previous release.
|
||||
|
||||
1.1.12
|
||||
~~~~~~
|
||||
* Fix a bug using the ``console`` plugin with older IE. See: https://github.com/getsentry/raven-js/pull/192
|
||||
* Added initial ``ember.js`` plugin for early testing and feedback.
|
||||
* Added initial ``angular.js`` plugin for early testing and feedback.
|
||||
* Fixed an issue with the ``require.js`` plugin basically not working at all. See: https://github.com/getsentry/raven-js/commit/c2a2e2672a2a61a5a07e88f24a9c885f6dba57ae
|
||||
* Got rid of ``Raven.afterLoad`` and made it internal only.
|
||||
* ``Raven.TraceKit`` is now internal only.
|
||||
* Truncate message length to a max of 100 characters becasue angular.js sucks and generates stupidly large error messages.
|
||||
|
||||
1.1.11
|
||||
~~~~~~
|
||||
* Capture column number from FireFox
|
||||
* Fix propagation of extra options through ``captureException``, see: https://github.com/getsentry/raven-js/pull/189
|
||||
* Fix a minor bug that causes TraceKit to blow up of someone passes something dumb through ``window.onerror``
|
||||
|
||||
1.1.10
|
||||
~~~~~~
|
||||
* A falsey DSN value disables Raven without yelling about an invalid DSN.
|
||||
|
||||
1.1.9
|
||||
~~~~~
|
||||
* Added ``Raven.lastEventId()`` to get back the Sentry event id. See: http://raven-js.readthedocs.org/en/latest/usage/index.html#getting-back-an-event-id
|
||||
* Fixed a bug in the ``console`` plugin. See: https://github.com/getsentry/raven-js/pull/181
|
||||
* Provide a way out of deep wrapping arguments. See: https://github.com/getsentry/raven-js/pull/182
|
||||
* ``Raven.uninstall()`` actually removes the patched ``window.onerror``.
|
||||
* No more globally exposed ``TraceKit``!
|
||||
|
||||
1.1.8
|
||||
~~~~~
|
||||
* Fixed a bug in IE8. See: https://github.com/getsentry/raven-js/pull/179
|
||||
|
||||
1.1.4-1.1.7
|
||||
~~~~~~~~~~~
|
||||
These were a bunch of super small incremental updates trying to get better integration and better support inside Sentry itself.
|
||||
|
||||
* Culprit determined from the src url of the offending script, not the url of the page.
|
||||
* Send Sentry the frames in the right order. They were being sent in reverse. Somehow nobody noticed this.
|
||||
* Support for Chrome's new window.onerror api. See: https://github.com/getsentry/raven-js/issues/172
|
||||
|
||||
1.1.3
|
||||
~~~~~
|
||||
* When loading with an AMD loader present, do not automatically call ``Raven.noConflict()``. This was causing issues with using plugins. See: https://github.com/getsentry/raven-js/pull/165
|
||||
* https://github.com/getsentry/raven-js/pull/168
|
||||
|
||||
1.1.2
|
||||
~~~~~
|
||||
* An invalid DSN will now raise a RavenConfigError instead of some cryptic error
|
||||
* Will raise a RavenConfigError when supplying the private key part of the DSN since this isn't applicable for raven.js and is harmful to include
|
||||
* https://github.com/getsentry/raven-js/issues/128
|
||||
|
||||
1.1.1
|
||||
~~~~~
|
||||
* Fixed a bug in parsing some DSNs. See: https://github.com/getsentry/raven-js/issues/160
|
||||
|
||||
1.1.0
|
||||
~~~~~
|
||||
|
||||
Plugins
|
||||
-------
|
||||
If you're upgrading from 1.0.x, 2 "plugins" were included with the package. These 2 plugins are now stripped out of core and included as the ``jquery`` and ``native`` plugins. If you'd like to start using 1.1.0 and maintain existing functionality, you'll want to use: http://cdn.ravenjs.com/1.1.0/jquery,native/raven.min.js For a list of other plugins, checkout http://ravenjs.com
|
||||
|
||||
ravenjs.com
|
||||
-----------
|
||||
A new website dedicated to helping you compile a custom build of raven.js
|
||||
|
||||
whitelistUrls
|
||||
-------------
|
||||
``whitelistUrls`` are recommended over ``ignoreUrls``. ``whitelistUrls`` drastically helps cut out noisy error messages from other scripts running on your site.
|
||||
|
||||
Misc
|
||||
----
|
||||
* ``ignoreUrls``, ``ignoreErrors``, ``includePaths`` have all been unified to accept both a regular expression and strings to avoid confusion and backwards compatability
|
||||
* ``Raven.wrap`` recursively wraps arguments
|
||||
* Events are dispatched when an exception is received, recorded or failed sending to Sentry
|
||||
* Support newer Sentry protocol which allows smaller packets
|
||||
* Allow loading raven async with RavenConfig
|
||||
* Entirely new build system with Grunt
|
||||
* ``options.collectWindowErrors`` to tell Raven to ignore window.onerror
|
||||
@@ -1,244 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# raven-js documentation build configuration file, created by
|
||||
# sphinx-quickstart on Mon Jan 21 21:04:27 2013.
|
||||
#
|
||||
# This file is execfile()d with the current directory set to its containing dir.
|
||||
#
|
||||
# Note that not all possible configuration values are present in this
|
||||
# autogenerated file.
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys, os, datetime
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
|
||||
# If your documentation needs a minimal Sphinx version, state it here.
|
||||
#needs_sphinx = '1.0'
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = []
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The encoding of source files.
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'raven-js'
|
||||
copyright = u'%s, Matt Robenolt' % datetime.date.today().year
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
|
||||
import json
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = json.load(open('../package.json'))['version']
|
||||
# The short X.Y version.
|
||||
version = release.rsplit('.', 1)[0]
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
#language = None
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
#today = ''
|
||||
# Else, today_fmt is used as the format for a strftime call.
|
||||
#today_fmt = '%B %d, %Y'
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||
#default_role = None
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
#add_module_names = True
|
||||
|
||||
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||
# output. They are ignored by default.
|
||||
#show_authors = False
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# A list of ignored prefixes for module index sorting.
|
||||
#modindex_common_prefix = []
|
||||
|
||||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
html_theme = 'default'
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
#html_title = None
|
||||
|
||||
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||
#html_short_title = None
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#html_favicon = None
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
#html_use_smartypants = True
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
#html_sidebars = {}
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
# If false, no index is generated.
|
||||
#html_use_index = True
|
||||
|
||||
# If true, the index is split into individual pages for each letter.
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
|
||||
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||
#html_show_copyright = True
|
||||
|
||||
# If true, an OpenSearch description file will be output, and all pages will
|
||||
# contain a <link> tag referring to it. The value of this option must be the
|
||||
# base URL from which the finished HTML is served.
|
||||
#html_use_opensearch = ''
|
||||
|
||||
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||
#html_file_suffix = None
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'raven-jsdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output --------------------------------------------------
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#'preamble': '',
|
||||
}
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||
latex_documents = [
|
||||
('index', 'raven-js.tex', u'raven-js Documentation',
|
||||
u'Matt Robenolt', 'manual'),
|
||||
]
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top of
|
||||
# the title page.
|
||||
#latex_logo = None
|
||||
|
||||
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||
# not chapters.
|
||||
#latex_use_parts = False
|
||||
|
||||
# If true, show page references after internal links.
|
||||
#latex_show_pagerefs = False
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#latex_show_urls = False
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#latex_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#latex_domain_indices = True
|
||||
|
||||
|
||||
# -- Options for manual page output --------------------------------------------
|
||||
|
||||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
('index', 'raven-js', u'raven-js Documentation',
|
||||
[u'Matt Robenolt'], 1)
|
||||
]
|
||||
|
||||
# If true, show URL addresses after external links.
|
||||
#man_show_urls = False
|
||||
|
||||
|
||||
# -- Options for Texinfo output ------------------------------------------------
|
||||
|
||||
# Grouping the document tree into Texinfo files. List of tuples
|
||||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
('index', 'raven-js', u'raven-js Documentation',
|
||||
u'Matt Robenolt', 'raven-js', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
# Documents to append as an appendix to all manuals.
|
||||
#texinfo_appendices = []
|
||||
|
||||
# If false, no module index is generated.
|
||||
#texinfo_domain_indices = True
|
||||
|
||||
# How to display URL addresses: 'footnote', 'no', or 'inline'.
|
||||
#texinfo_show_urls = 'footnote'
|
||||
@@ -1,220 +0,0 @@
|
||||
Configuration
|
||||
=============
|
||||
|
||||
We must first configure Sentry to allow certain hosts to report errors. This prevents abuse so somebody else couldn't start sending errors to your account from their site.
|
||||
|
||||
**Note**: Without setting this, all messages will be rejected!
|
||||
|
||||
This can be found under the *Project Details* page in Sentry.
|
||||
|
||||
.. image:: https://i.imgur.com/S09MeSM.png
|
||||
|
||||
Now need to set up Raven.js to use your Sentry DSN.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
Raven.config('https://public@getsentry.com/1').install()
|
||||
|
||||
At this point, Raven is ready to capture any uncaught exception.
|
||||
|
||||
Although, this technically works, this is not going to yield the greatest results. It's highly recommended to next check out :doc:`/usage/index`.
|
||||
|
||||
Optional settings
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
``Raven.config()`` can be passed an optional object for extra configuration.
|
||||
|
||||
logger
|
||||
------
|
||||
|
||||
The name of the logger used by Sentry. Default: ``javascript``
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
logger: 'javascript'
|
||||
}
|
||||
|
||||
release
|
||||
-------
|
||||
|
||||
Track the version of your application in Sentry.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
release: '721e41770371db95eee98ca2707686226b993eda'
|
||||
}
|
||||
|
||||
Can also be defined with ``Raven.setReleaseContext('721e41770371db95eee98ca2707686226b993eda')``.
|
||||
|
||||
.. _config-whitelist-urls:
|
||||
|
||||
tags
|
||||
----
|
||||
|
||||
Additional `tags <https://www.getsentry.com/docs/tags/>`__ to assign to each event.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
tags: {git_commit: 'c0deb10c4'}
|
||||
}
|
||||
|
||||
whitelistUrls
|
||||
-------------
|
||||
|
||||
The inverse of ``ignoreUrls``. Only report errors from whole urls matching a regex pattern or an exact string. ``whitelistUrls`` should match the url of your actual JavaScript files. It should match the url of your site if and only if you are inlining code inside ``<script>`` tags.
|
||||
|
||||
Does not affect captureMessage or when non-error object is passed in as argument to captureException.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
whitelistUrls: [/getsentry\.com/, /cdn\.getsentry\.com/]
|
||||
}
|
||||
|
||||
ignoreErrors
|
||||
------------
|
||||
|
||||
Very often, you will come across specific errors that are a result of something other than your application, or errors that you're completely not interested in. `ignoreErrors` is a list of these messages to be filtered out before being sent to Sentry as either regular expressions or strings.
|
||||
|
||||
Does not affect captureMessage or when non-error object is passed in as argument to captureException.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
ignoreErrors: ['fb_xd_fragment']
|
||||
}
|
||||
|
||||
ignoreUrls
|
||||
----------
|
||||
|
||||
The inverse of ``whitelistUrls`` and similar to ``ignoreErrors``, but will ignore errors from whole urls matching a regex pattern or an exact string.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
ignoreUrls: [/graph\.facebook\.com/, 'http://example.com/script2.js']
|
||||
}
|
||||
|
||||
Does not affect captureMessage or when non-error object is passed in as argument to captureException.
|
||||
|
||||
includePaths
|
||||
------------
|
||||
|
||||
An array of regex patterns to indicate which urls are a part of your app in the stack trace. All other frames will appear collapsed inside Sentry to make it easier to discern between frames that happened in your code vs other code. It'd be suggested to add the current page url, and the host for your CDN.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
includePaths: [/https?:\/\/getsentry\.com/, /https?:\/\/cdn\.getsentry\.com/]
|
||||
}
|
||||
|
||||
dataCallback
|
||||
------------
|
||||
|
||||
A function that allows mutation of the data payload right before being sent to Sentry.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
dataCallback: function(data) {
|
||||
// do something to data
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
Can also be set at runtime with `Raven.setDataCallback(function(data) { ... })`.
|
||||
|
||||
shouldSendCallback
|
||||
------------------
|
||||
|
||||
A callback function that allows you to apply your own filters to determine if the message should be sent to Sentry.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
shouldSendCallback: function(data) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Can also be set at runtime with `Raven.setShouldSendCallback(function(data) { ... })`.
|
||||
|
||||
maxMessageLength
|
||||
------------------
|
||||
|
||||
By default, raven truncates messages to a max length of 100 characters. You can customize the max length with this parameter.
|
||||
|
||||
|
||||
Putting it all together
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Awesome stuff happening here</title>
|
||||
</head>
|
||||
<body>
|
||||
...
|
||||
<script src="jquery.min.js"></script>
|
||||
<script src="//cdn.ravenjs.com/|release|/jquery,native/raven.min.js"></script>
|
||||
<script>
|
||||
var options = {
|
||||
logger: 'my-logger',
|
||||
whitelistUrls: [
|
||||
/disqus\\.com/, /getsentry\\.com/
|
||||
],
|
||||
ignoreErrors: [
|
||||
'fb_xd_fragment', /ReferenceError:.*/
|
||||
],
|
||||
includePaths: [
|
||||
/https?:\\/\\/(www\\.)?getsentry\\.com/
|
||||
]
|
||||
};
|
||||
Raven.config('https://public@app.getsentry.com/1', options).install();
|
||||
</script>
|
||||
<script src="myapp.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
TraceKit specific optional settings
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Usually there is no need to touch these settings, but they exist in case you need to tweak something.
|
||||
|
||||
fetchContext
|
||||
------------
|
||||
|
||||
Enable TraceKit to attempt to fetch source files to look up anonymous function names, this can be useful to enable if you don't get the context for some entries in the stack trace. Default value is ``false``.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
fetchContext: true
|
||||
}
|
||||
|
||||
linesOfContext
|
||||
--------------
|
||||
|
||||
The count of lines surrounding the error line that should be used as context in the stack trace, default value is ``11``. Only applicable when ``fetchContext` is enabled.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
linesOfContext: 11
|
||||
}
|
||||
|
||||
collectWindowErrors
|
||||
-------------------
|
||||
|
||||
Enable or disable the TraceKit ``window.onerror`` handler, default value is ``true``.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
collectWindowErrors: true
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
Contributing
|
||||
============
|
||||
|
||||
Setting up an Environment
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To run the test suite and run our code linter, node.js and npm are required. If you don't have node installed, `get it here <http://nodejs.org/download/>`_ first.
|
||||
|
||||
Installing all other dependencies is as simple as:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ npm install
|
||||
|
||||
And if you don't have `Grunt <http://gruntjs.com/>`_ already, feel free to install that globally:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ npm install -g grunt-cli
|
||||
|
||||
Running the Test Suite
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The test suite is powered by `Mocha <http://visionmedia.github.com/mocha/>`_ and can both run from the command line, or in the browser.
|
||||
|
||||
From the command line:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ grunt test
|
||||
|
||||
From your browser:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ grunt run:test
|
||||
|
||||
Then visit: http://localhost:8000/test/
|
||||
|
||||
Compiling Raven.js
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The simplest way to compile your own version of Raven.js is with the supplied grunt command:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ grunt build
|
||||
|
||||
By default, this will compile raven.js and all of the included plugins.
|
||||
|
||||
If you only want to compile the core raven.js:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ grunt build.core
|
||||
|
||||
Files are compiled into ``build/``.
|
||||
|
||||
Contributing Back Code
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Please, send over suggestions and bug fixes in the form of pull requests on `GitHub <https://github.com/getsentry/raven-js>`_. Any nontrivial fixes/features should include tests.
|
||||
Do not include any changes to the ``dist/`` folder or bump version numbers yourself.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
The documentation is written using `reStructuredText <http://en.wikipedia.org/wiki/ReStructuredText>`_, and compiled using `Sphinx <http://sphinx-doc.org/>`_. If you don't have Sphinx installed, you can do it using following command (assuming you have Python already installed in your system):
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ pip install sphinx
|
||||
|
||||
Documentation can be then compiled by running:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ make docs
|
||||
|
||||
Afterwards you can view it in your browser by running following command and than pointing your browser to http://127.0.0.1:8000/:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ grunt run:docs
|
||||
|
||||
|
||||
|
||||
Releasing New Version
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Bump version numbers in both ``package.json`` and ``bower.json``.
|
||||
* ``$ grunt dist`` This will compile a new version and update it in the ``dist/`` folder.
|
||||
* Confirm that build was fine, etc.
|
||||
* Commit new version, create a tag. Push to GitHub.
|
||||
* ``$ grunt publish`` to recompile all plugins and all permutations and upload to S3.
|
||||
* ``$ npm publish`` to push to npm.
|
||||
* Confirm that the new version exists behind ``cdn.ravenjs.com``
|
||||
* Update version in the ``gh-pages`` branch specifically for http://ravenjs.com/.
|
||||
* glhf
|
||||
@@ -1,42 +0,0 @@
|
||||
Raven.js
|
||||
========
|
||||
|
||||
Raven.js is a tiny standalone JavaScript client for `Sentry <http://www.getsentry.com/>`_.
|
||||
|
||||
**This version of Raven.js requires Sentry 6.0 or newer.**
|
||||
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
install/index
|
||||
plugins/index
|
||||
config/index
|
||||
usage/index
|
||||
tips/index
|
||||
|
||||
Developers
|
||||
----------
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
contributing/index
|
||||
|
||||
What's New?
|
||||
-----------
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
changelog/index
|
||||
|
||||
Resources
|
||||
---------
|
||||
* `Download <http://ravenjs.com>`_
|
||||
* `Bug Tracker <https://github.com/getsentry/raven-js/issues>`_
|
||||
* `Code <https://github.com/getsentry/raven-js>`_
|
||||
* `IRC <irc://irc.freenode.net/sentry>`_ (irc.freenode.net, #sentry)
|
||||
* :doc:`Changelog </changelog/index>`
|
||||
* Follow `@mattrobenolt <https://twitter.com/mattrobenolt>`_ on Twitter for updates!
|
||||
@@ -1,61 +0,0 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
Raven is distributed in a few different methods, and should get included after any other libraries are included, but before your own scripts.
|
||||
|
||||
So for example:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
<script src="jquery.js"></script>
|
||||
<script src="//cdn.ravenjs.com/|release|/jquery,native/raven.min.js"></script>
|
||||
<script>Raven.config('...').install();</script>
|
||||
<script src="app.js"></script>
|
||||
|
||||
This allows the ability for Raven's plugins to instrument themselves. If included before something like jQuery, it'd be impossible to use for example, the jquery plugin.
|
||||
|
||||
Using our CDN
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
We serve our own builds off of `Fastly <http://www.fastly.com/>`_. They are accessible over both http and https, so we recommend leaving the protocol off.
|
||||
|
||||
Our CDN distributes builds with and without :doc:`plugins </plugins/index>`.
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
<script src="//cdn.ravenjs.com/|release|/raven.min.js"></script>
|
||||
|
||||
**We highly recommend trying out a plugin or two since it'll greatly improve the chances that we can collect good information.**
|
||||
|
||||
This version does not include any plugins. See `ravenjs.com <http://ravenjs.com/>`_ for more information about plugins and getting other builds.
|
||||
|
||||
Bower
|
||||
~~~~~
|
||||
|
||||
We also provide a way to deploy Raven via `bower
|
||||
<http://bower.io/>`_. Useful if you want serve your own scripts instead of depending on our CDN and mantain a ``bower.json`` with a list of dependencies and versions (adding the ``--save`` flag would automatically add it to ``bower.json``).
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ bower install raven-js --save
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<script src="/bower_components/raven-js/dist/raven.js"></script>
|
||||
|
||||
Also note that the file is uncompresed but is ready to pass to any decent JavaScript compressor like `uglify <https://github.com/mishoo/UglifyJS2>`_.
|
||||
|
||||
npm
|
||||
~~~
|
||||
|
||||
Raven is published to npm as well. https://www.npmjs.com/package/raven-js
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ npm install raven-js --save
|
||||
|
||||
Requirements
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Raven expects the browser to provide `window.JSON` and `window.JSON.stringify`. In Internet Explorer 8+ these are available in `standards mode <http://msdn.microsoft.com/en-us/library/cc288325(VS.85).aspx>`_.
|
||||
You can also use `json2.js <https://github.com/douglascrockford/JSON-js>`_ to provide the JSON implementation in browsers/modes which doesn't support native JSON
|
||||
@@ -1,190 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set BUILDDIR=_build
|
||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
|
||||
set I18NSPHINXOPTS=%SPHINXOPTS% .
|
||||
if NOT "%PAPER%" == "" (
|
||||
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
|
||||
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
if "%1" == "help" (
|
||||
:help
|
||||
echo.Please use `make ^<target^>` where ^<target^> is one of
|
||||
echo. html to make standalone HTML files
|
||||
echo. dirhtml to make HTML files named index.html in directories
|
||||
echo. singlehtml to make a single large HTML file
|
||||
echo. pickle to make pickle files
|
||||
echo. json to make JSON files
|
||||
echo. htmlhelp to make HTML files and a HTML help project
|
||||
echo. qthelp to make HTML files and a qthelp project
|
||||
echo. devhelp to make HTML files and a Devhelp project
|
||||
echo. epub to make an epub
|
||||
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
echo. text to make text files
|
||||
echo. man to make manual pages
|
||||
echo. texinfo to make Texinfo files
|
||||
echo. gettext to make PO message catalogs
|
||||
echo. changes to make an overview over all changed/added/deprecated items
|
||||
echo. linkcheck to check all external links for integrity
|
||||
echo. doctest to run all doctests embedded in the documentation if enabled
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "clean" (
|
||||
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
|
||||
del /q /s %BUILDDIR%\*
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "html" (
|
||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "dirhtml" (
|
||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "singlehtml" (
|
||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "pickle" (
|
||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the pickle files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "json" (
|
||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can process the JSON files.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "htmlhelp" (
|
||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "qthelp" (
|
||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\raven-js.qhcp
|
||||
echo.To view the help file:
|
||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\raven-js.ghc
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "devhelp" (
|
||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "epub" (
|
||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "latex" (
|
||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "text" (
|
||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "man" (
|
||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "texinfo" (
|
||||
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "gettext" (
|
||||
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "changes" (
|
||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.The overview file is in %BUILDDIR%/changes.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "linkcheck" (
|
||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Link check complete; look for any errors in the above output ^
|
||||
or in %BUILDDIR%/linkcheck/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
if "%1" == "doctest" (
|
||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
||||
if errorlevel 1 exit /b 1
|
||||
echo.
|
||||
echo.Testing of doctests in the sources finished, look at the ^
|
||||
results in %BUILDDIR%/doctest/output.txt.
|
||||
goto end
|
||||
)
|
||||
|
||||
:end
|
||||
@@ -1,20 +0,0 @@
|
||||
Plugins
|
||||
=======
|
||||
|
||||
What are plugins?
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
In Raven.js, plugins are little snippets of code to augment functionality for a specific application/framework. It is highly recommended to checkout the list of plugins and use what apply to your project.
|
||||
|
||||
In order to keep the core small, we have opted to only include the most basic functionality by default, and you can pick and choose which plugins are applicable for you.
|
||||
|
||||
Why are plugins needed at all?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
JavaScript is pretty restrictive when it comes to exception handling, and there are a lot of things that make it difficult to get relevent information, so it's important that we inject code and wrap things magically so we can extract what we need. See :doc:`/usage/index` for tips regarding that.
|
||||
|
||||
|
||||
All Plugins
|
||||
~~~~~~~~~~~
|
||||
* https://github.com/getsentry/raven-js/tree/master/plugins
|
||||
* `Download <http://ravenjs.com>`_
|
||||
@@ -1,79 +0,0 @@
|
||||
Pro Tips™
|
||||
=========
|
||||
|
||||
|
||||
Decluttering Sentry
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The first thing to do is to consider constructing a whitelist of domains in which might raise acceptable exceptions.
|
||||
|
||||
If your scripts are loaded from ``cdn.example.com`` and your site is ``example.com`` it'd be reasonable to set ``whitelistUrls`` to:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
whitelistUrls: [
|
||||
/https?:\/\/((cdn|www)\.)?example\.com/
|
||||
]
|
||||
|
||||
Since this accepts a regular expression, that would catch anything \*.example.com or example.com exactly. See also: :ref:`Config: whitelistUrls<config-whitelist-urls>`.
|
||||
|
||||
Next, checkout the list of :doc:`plugins </plugins/index>` we provide and see which are applicable to you.
|
||||
|
||||
The community has compiled a list of common ignore rules for common things, like Facebook, Chrome extensions, etc. So it's recommended to at least check these out and see if they apply to you. `Check out the original gist <https://gist.github.com/impressiver/5092952>`_.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
var ravenOptions = {
|
||||
ignoreErrors: [
|
||||
// Random plugins/extensions
|
||||
'top.GLOBALS',
|
||||
// See: http://blog.errorception.com/2012/03/tale-of-unfindable-js-error. html
|
||||
'originalCreateNotification',
|
||||
'canvas.contentDocument',
|
||||
'MyApp_RemoveAllHighlights',
|
||||
'http://tt.epicplay.com',
|
||||
'Can\'t find variable: ZiteReader',
|
||||
'jigsaw is not defined',
|
||||
'ComboSearch is not defined',
|
||||
'http://loading.retry.widdit.com/',
|
||||
'atomicFindClose',
|
||||
// Facebook borked
|
||||
'fb_xd_fragment',
|
||||
// ISP "optimizing" proxy - `Cache-Control: no-transform` seems to reduce this. (thanks @acdha)
|
||||
// See http://stackoverflow.com/questions/4113268/how-to-stop-javascript-injection-from-vodafone-proxy
|
||||
'bmi_SafeAddOnload',
|
||||
'EBCallBackMessageReceived',
|
||||
// See http://toolbar.conduit.com/Developer/HtmlAndGadget/Methods/JSInjection.aspx
|
||||
'conduitPage'
|
||||
],
|
||||
ignoreUrls: [
|
||||
// Facebook flakiness
|
||||
/graph\.facebook\.com/i,
|
||||
// Facebook blocked
|
||||
/connect\.facebook\.net\/en_US\/all\.js/i,
|
||||
// Woopra flakiness
|
||||
/eatdifferent\.com\.woopra-ns\.com/i,
|
||||
/static\.woopra\.com\/js\/woopra\.js/i,
|
||||
// Chrome extensions
|
||||
/extensions\//i,
|
||||
/^chrome:\/\//i,
|
||||
// Other plugins
|
||||
/127\.0\.0\.1:4001\/isrunning/i, // Cacaoweb
|
||||
/webappstoolbarba\.texthelp\.com\//i,
|
||||
/metrics\.itunes\.apple\.com\.edgesuite\.net\//i
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
Sampling Data
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
It happens frequently that errors sent from your frontend can be overwhelming. One solution here is to only send a sample of the events that happen. You can do this via the ``shouldSendCallback`` setting:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
shouldSendCallback: function(data) {
|
||||
// only send 10% of errors
|
||||
var sampleRate = 10;
|
||||
return (Math.random() * 100 <= sampleRate);
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
Usage
|
||||
=====
|
||||
|
||||
By default, Raven makes a few efforts to try its best to capture meaningful stack traces, but browsers make it pretty difficult.
|
||||
|
||||
The easiest solution is to prevent an error from bubbling all of the way up the stack to ``window``.
|
||||
|
||||
How to actually capture an error correctly
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
try...catch
|
||||
-----------
|
||||
|
||||
The simplest way, is to try and explicitly capture and report potentially problematic code with a ``try...catch`` block and ``Raven.captureException``.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
try {
|
||||
doSomething(a[0])
|
||||
} catch(e) {
|
||||
Raven.captureException(e)
|
||||
}
|
||||
|
||||
**Do not** throw strings! Always throw an actual ``Error`` object. For example:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
throw new Error('broken') // good
|
||||
throw 'broken' // bad
|
||||
|
||||
It's impossible to retrieve a stack trace from a string. If this happens, Raven transmits the error as a plain message.
|
||||
|
||||
context/wrap
|
||||
------------
|
||||
|
||||
``Raven.context`` allows you to wrap any function to be immediately executed. Behind the scenes, Raven is just wrapping your code in a ``try...catch`` block to record the exception before re-throwing it.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
Raven.context(function() {
|
||||
doSomething(a[0])
|
||||
})
|
||||
|
||||
``Raven.wrap`` wraps a function in a similar way to ``Raven.context``, but instead of executing the function, it returns another function. This is totally awesome for use when passing around a callback.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
var doIt = function() {
|
||||
// doing cool stuff
|
||||
}
|
||||
|
||||
setTimeout(Raven.wrap(doIt), 1000)
|
||||
|
||||
Tracking authenticated users
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
While a user is logged in, you can tell Sentry to associate errors with user data.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
Raven.setUserContext({
|
||||
email: 'matt@example.com',
|
||||
id: '123'
|
||||
})
|
||||
|
||||
If at any point, the user becomes unauthenticated, you can call ``Raven.setUserContext()`` with no arguments to remove their data. *This would only really be useful in a large web app where the user logs in/out without a page reload.*
|
||||
|
||||
Capturing a specific message
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
Raven.captureMessage('Broken!')
|
||||
|
||||
Passing additional data
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``captureException``, ``context``, ``wrap``, and ``captureMessage`` functions all allow passing additional data to be tagged onto the error, such as ``tags`` or ``extra`` for additional context.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
Raven.captureException(e, {tags: { key: "value" }})
|
||||
|
||||
Raven.captureMessage('Broken!', {tags: { key: "value" }})
|
||||
|
||||
Raven.context({tags: { key: "value" }}, function(){ ... })
|
||||
|
||||
Raven.wrap({logger: "my.module"}, function(){ ... })
|
||||
|
||||
Raven.captureException(e, {extra: { foo: "bar" }})
|
||||
|
||||
You can also set context variables globally to be merged in with future exceptions with ``setExtraContext`` and ``setTagsContext``.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
Raven.setExtraContext({ foo: "bar" })
|
||||
Raven.setTagsContext({ key: "value" })
|
||||
|
||||
|
||||
Getting back an event id
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
An event id is a globally unique id for the event that was just sent. This event id can be used to find the exact event from within Sentry.
|
||||
|
||||
This is often used to display for the user and report an error to customer service.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
Raven.lastEventId()
|
||||
|
||||
``Raven.lastEventId()`` will be undefined until an event is sent. After an event is sent, it will contain the string id.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
Raven.captureMessage('Broken!')
|
||||
alert(Raven.lastEventId())
|
||||
|
||||
|
||||
Check if Raven is setup and ready to go
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
Raven.isSetup()
|
||||
|
||||
|
||||
Dealing with minified source code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Raven and Sentry now support `Source Maps <http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/>`_.
|
||||
|
||||
We have provided some instructions to creating Source Maps over at https://www.getsentry.com/docs/sourcemaps/. Also, checkout our `Gruntfile <https://github.com/getsentry/raven-js/blob/master/Gruntfile.js>`_ for a good example of what we're doing.
|
||||
|
||||
You can use `Source Map Validator <http://sourcemap-validator.herokuapp.com/>`_ to help verify that things are correct.
|
||||
|
||||
CORS
|
||||
~~~~
|
||||
|
||||
If you're hosting your scripts on another domain and things don't get caught by Raven, it's likely that the error will bubble up to ``window.onerror``. If this happens, the error will report some ugly ``Script error`` and Raven will drop it on the floor
|
||||
since this is a useless error for everybody.
|
||||
|
||||
To help mitigate this, we can tell the browser that these scripts are safe and we're allowing them to expose their errors to us.
|
||||
|
||||
In your ``<script>`` tag, specify the ``crossorigin`` attribute:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<script src="//cdn.example.com/script.js" crossorigin="anonymous"></script>
|
||||
|
||||
And set an ``Access-Control-Allow-Origin`` HTTP header on that file.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
Access-Control-Allow-Origin: *
|
||||
|
||||
**Note: both of these steps need to be done or your scripts might not even get executed**
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
build:
|
||||
../node_modules/.bin/uglifyjs --source-map=file.sourcemap.js -c -o file.min.js file1.js file2.js
|
||||
2
htdocs/includes/raven-js/example/file.min.js
vendored
2
htdocs/includes/raven-js/example/file.min.js
vendored
@@ -1,2 +0,0 @@
|
||||
function add(a,b){"use strict";return a+b}function multiply(a,b){"use strict";return a*b}function divide(a,b){"use strict";try{return multiply(add(a,b),a,b)/c}catch(e){Raven.captureException(e)}}
|
||||
//@ sourceMappingURL=file.sourcemap.js
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"file.min.js","sources":["file1.js","file2.js"],"names":["add","a","b","multiply","divide","c","e","Raven","captureException"],"mappings":"AAAA,QAASA,KAAIC,EAAGC,GACf,YACA,OAAOD,GAAIC,ECFZ,QAASC,UAASF,EAAGC,GACpB,YACA,OAAOD,GAAIC,EAEZ,QAASE,QAAOH,EAAGC,GAClB,YACA,KACC,MAAOC,UAASH,IAAIC,EAAGC,GAAID,EAAGC,GAAKG,EAClC,MAAOC,GACRC,MAAMC,iBAAiBF"}
|
||||
@@ -1,4 +0,0 @@
|
||||
function add(a, b) {
|
||||
"use strict";
|
||||
return a + b;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
function multiply(a, b) {
|
||||
"use strict";
|
||||
return a * b;
|
||||
}
|
||||
function divide(a, b) {
|
||||
"use strict";
|
||||
try {
|
||||
return multiply(add(a, b), a, b) / c;
|
||||
} catch (e) {
|
||||
Raven.captureException(e);
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Scratch Disk</title>
|
||||
</head>
|
||||
<script src="../vendor/TraceKit/tracekit.js"></script>
|
||||
<script src="../src/raven.js"></script>
|
||||
<!-- <script src="scratch.min.js"></script> -->
|
||||
<script src="scratch.js" crossorigin></script>
|
||||
<script src="file.min.js" crossorigin></script>
|
||||
<script>
|
||||
//cool
|
||||
//really cool
|
||||
//awesome
|
||||
Raven.config('http://50dbe04cd1224d439e9c49bf1d0464df@localhost:8000/1', {
|
||||
whitelistUrls: [
|
||||
/localhost/
|
||||
],
|
||||
dataCallback: function(data) {
|
||||
console.log(data);
|
||||
return data;
|
||||
}
|
||||
}).install();
|
||||
|
||||
Raven.setUserContext({
|
||||
email: 'matt@ydekproductions.com',
|
||||
id: 5
|
||||
})
|
||||
|
||||
</script>
|
||||
<body>
|
||||
<button id="test">Break me</button>
|
||||
<script>ready()</script>
|
||||
|
||||
<button onclick="divide(1, 0)">Sourcemap breakage</button>
|
||||
<button onclick="derp()">window.onerror</button>
|
||||
<button onclick="testOptions()">test options</button>
|
||||
<button onclick="throwString()">throw string</button>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,42 +0,0 @@
|
||||
function foo() {
|
||||
console.log("lol, i don't do anything")
|
||||
}
|
||||
|
||||
function foo2() {
|
||||
foo()
|
||||
console.log('i called foo')
|
||||
}
|
||||
|
||||
function broken() {
|
||||
try {
|
||||
/*fkjdsahfdhskfhdsahfudshafuoidashfudsa*/ fdasfds[0]; // i throw an error h sadhf hadsfdsakf kl;dsjaklf jdklsajfk ljds;klafldsl fkhdas;hf hdsaf hdsalfhjldksahfljkdsahfjkl dhsajkfl hdklsahflkjdsahkfj hdsjakhf dkashfl diusafh kdsjahfkldsahf jkdashfj khdasjkfhdjksahflkjdhsakfhjdksahfjkdhsakf hdajskhf kjdash kjfads fjkadsh jkfdsa jkfdas jkfdjkas hfjkdsajlk fdsajk fjkdsa fjdsa fdkjlsa fjkdaslk hfjlkdsah fhdsahfui
|
||||
}catch(e) {
|
||||
Raven.captureException(e);
|
||||
}
|
||||
}
|
||||
|
||||
function ready() {
|
||||
document.getElementById('test').onclick = broken;
|
||||
}
|
||||
|
||||
function foo3() {
|
||||
document.getElementById('crap').value = 'barfdasjkfhoadshflkaosfjadiosfhdaskjfasfadsfads';
|
||||
}
|
||||
|
||||
function somethingelse() {
|
||||
document.getElementById('somethingelse').value = 'this is some realy really long message just so our minification is largeeeeeeeeee!';
|
||||
}
|
||||
|
||||
function derp() {
|
||||
fdas[0];
|
||||
}
|
||||
|
||||
function testOptions() {
|
||||
Raven.context({tags: {foo: 'bar'}}, function() {
|
||||
throw new Error('foo');
|
||||
});
|
||||
}
|
||||
|
||||
function throwString() {
|
||||
throw 'oops';
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
{
|
||||
"name": "raven-js",
|
||||
"version": "1.1.19",
|
||||
"license": "BSD-2-Clause",
|
||||
"homepage": "https://getsentry.com",
|
||||
"scripts": {
|
||||
"pretest": "npm install",
|
||||
"test": "grunt test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/getsentry/raven-js.git"
|
||||
},
|
||||
"main": "dist/raven.js",
|
||||
"devDependencies": {
|
||||
"chai": "~1.8.1",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt-contrib-jshint": "~0.6.3",
|
||||
"grunt-contrib-uglify": "~0.2.2",
|
||||
"grunt-contrib-concat": "~0.3.0",
|
||||
"grunt-contrib-clean": "~0.4.0",
|
||||
"grunt-mocha": "~0.4.1",
|
||||
"grunt-release": "~0.6.0",
|
||||
"grunt-s3": "~0.2.0-alpha.3",
|
||||
"grunt-gitinfo": "~0.1.1",
|
||||
"grunt-contrib-connect": "~0.5.0",
|
||||
"grunt-contrib-copy": "~0.4.1",
|
||||
"sinon": "~1.7.3",
|
||||
"lodash": "~2.4.0"
|
||||
}
|
||||
}
|
||||
36
htdocs/includes/raven-js/plugins/angular.js
vendored
36
htdocs/includes/raven-js/plugins/angular.js
vendored
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* Angular.js plugin
|
||||
*
|
||||
* Provides an $exceptionHandler for Angular.js
|
||||
*/
|
||||
;(function(Raven, angular) {
|
||||
'use strict';
|
||||
|
||||
// quit if angular isn't on the page
|
||||
if (!angular) {
|
||||
return;
|
||||
}
|
||||
|
||||
function ngRavenProvider($provide) {
|
||||
$provide.decorator('$exceptionHandler', [
|
||||
'RavenConfig', '$delegate',
|
||||
ngRavenExceptionHandler
|
||||
]);
|
||||
}
|
||||
|
||||
function ngRavenExceptionHandler(RavenConfig, $delegate) {
|
||||
if (!RavenConfig)
|
||||
throw new Error('RavenConfig must be set before using this');
|
||||
|
||||
Raven.config(RavenConfig.dsn, RavenConfig.config).install();
|
||||
return function angularExceptionHandler(ex, cause) {
|
||||
$delegate(ex, cause);
|
||||
Raven.captureException(ex, {extra: {cause: cause}});
|
||||
};
|
||||
}
|
||||
|
||||
angular.module('ngRaven', [])
|
||||
.config(['$provide', ngRavenProvider])
|
||||
.value('Raven', Raven);
|
||||
|
||||
})(window.Raven, window.angular);
|
||||
@@ -1,55 +0,0 @@
|
||||
/**
|
||||
* Backbone.js plugin
|
||||
*
|
||||
* Patches Backbone.Events callbacks.
|
||||
*/
|
||||
;(function(window, Raven, Backbone) {
|
||||
'use strict';
|
||||
|
||||
// quit if Backbone isn't on the page
|
||||
if (!Backbone) {
|
||||
return;
|
||||
}
|
||||
|
||||
function makeBackboneEventsOn(oldOn) {
|
||||
return function BackboneEventsOn(name, callback, context) {
|
||||
var wrapCallback = function (cb) {
|
||||
if (Object.prototype.toString.call(cb) === '[object Function]') {
|
||||
var _callback = cb._callback || cb;
|
||||
cb = Raven.wrap(cb);
|
||||
cb._callback = _callback;
|
||||
}
|
||||
return cb;
|
||||
};
|
||||
if (Object.prototype.toString.call(name) === '[object Object]') {
|
||||
// Handle event maps.
|
||||
for (var key in name) {
|
||||
if (name.hasOwnProperty(key)) {
|
||||
name[key] = wrapCallback(name[key]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
callback = wrapCallback(callback);
|
||||
}
|
||||
return oldOn.call(this, name, callback, context);
|
||||
};
|
||||
}
|
||||
|
||||
// We're too late to catch all of these by simply patching Backbone.Events.on
|
||||
var affectedObjects = [
|
||||
Backbone.Events,
|
||||
Backbone,
|
||||
Backbone.Model.prototype,
|
||||
Backbone.Collection.prototype,
|
||||
Backbone.View.prototype,
|
||||
Backbone.Router.prototype,
|
||||
Backbone.History.prototype
|
||||
], i = 0, l = affectedObjects.length;
|
||||
|
||||
for (; i < l; i++) {
|
||||
var affected = affectedObjects[i];
|
||||
affected.on = makeBackboneEventsOn(affected.on);
|
||||
affected.bind = affected.on;
|
||||
}
|
||||
|
||||
}(window, window.Raven, window.Backbone));
|
||||
@@ -1,43 +0,0 @@
|
||||
/**
|
||||
* console plugin
|
||||
*
|
||||
* Monkey patches console.* calls into Sentry messages with
|
||||
* their appropriate log levels. (Experimental)
|
||||
*/
|
||||
;(function(window, Raven, console) {
|
||||
'use strict';
|
||||
|
||||
var originalConsole = console,
|
||||
logLevels = ['debug', 'info', 'warn', 'error'],
|
||||
level = logLevels.pop();
|
||||
|
||||
var logForGivenLevel = function(level) {
|
||||
var originalConsoleLevel = console[level];
|
||||
|
||||
// warning level is the only level that doesn't map up
|
||||
// correctly with what Sentry expects.
|
||||
if (level === 'warn') level = 'warning';
|
||||
return function () {
|
||||
var args = [].slice.call(arguments);
|
||||
Raven.captureMessage('' + args, {level: level, logger: 'console'});
|
||||
|
||||
// this fails for some browsers. :(
|
||||
if (originalConsoleLevel) {
|
||||
// IE9 doesn't allow calling apply on console functions directly
|
||||
// See: https://stackoverflow.com/questions/5472938/does-ie9-support-console-log-and-is-it-a-real-function#answer-5473193
|
||||
Function.prototype.bind
|
||||
.call(originalConsoleLevel, originalConsole)
|
||||
.apply(originalConsole, args);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
while(level) {
|
||||
console[level] = logForGivenLevel(level);
|
||||
level = logLevels.pop();
|
||||
}
|
||||
// export
|
||||
window.console = console;
|
||||
|
||||
}(window, window.Raven, window.console || {}));
|
||||
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* Ember.js plugin
|
||||
*
|
||||
* Patches event handler callbacks and ajax callbacks.
|
||||
*/
|
||||
;(function(window, Raven, Ember) {
|
||||
'use strict';
|
||||
|
||||
// quit if Ember isn't on the page
|
||||
if (!Ember) {
|
||||
return;
|
||||
}
|
||||
|
||||
var _oldOnError = Ember.onerror;
|
||||
Ember.onerror = function EmberOnError(error) {
|
||||
Raven.captureException(error);
|
||||
if (typeof _oldOnError === 'function') {
|
||||
_oldOnError.call(this, error);
|
||||
}
|
||||
};
|
||||
Ember.RSVP.on('error', function (reason) {
|
||||
if (reason instanceof Error) {
|
||||
Raven.captureException(reason, {extra: {context: 'Unhandled Promise error detected'}});
|
||||
} else {
|
||||
Raven.captureMessage('Unhandled Promise error detected', {extra: {reason: reason}});
|
||||
}
|
||||
});
|
||||
|
||||
}(window, window.Raven, window.Ember));
|
||||
75
htdocs/includes/raven-js/plugins/jquery.js
vendored
75
htdocs/includes/raven-js/plugins/jquery.js
vendored
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
* jQuery plugin
|
||||
*
|
||||
* Patches event handler callbacks and ajax callbacks.
|
||||
*/
|
||||
;(function(window, Raven, $) {
|
||||
'use strict';
|
||||
|
||||
// quit if jQuery isn't on the page
|
||||
if (!$) {
|
||||
return;
|
||||
}
|
||||
|
||||
var _oldEventAdd = $.event.add;
|
||||
$.event.add = function ravenEventAdd(elem, types, handler, data, selector) {
|
||||
var _handler;
|
||||
|
||||
if (handler && handler.handler) {
|
||||
_handler = handler.handler;
|
||||
handler.handler = Raven.wrap(handler.handler);
|
||||
} else {
|
||||
_handler = handler;
|
||||
handler = Raven.wrap(handler);
|
||||
}
|
||||
|
||||
// If the handler we are attaching doesn’t have the same guid as
|
||||
// the original, it will never be removed when someone tries to
|
||||
// unbind the original function later. Technically as a result of
|
||||
// this our guids are no longer globally unique, but whatever, that
|
||||
// never hurt anybody RIGHT?!
|
||||
if (_handler.guid) {
|
||||
handler.guid = _handler.guid;
|
||||
} else {
|
||||
handler.guid = _handler.guid = $.guid++;
|
||||
}
|
||||
|
||||
return _oldEventAdd.call(this, elem, types, handler, data, selector);
|
||||
};
|
||||
|
||||
var _oldReady = $.fn.ready;
|
||||
$.fn.ready = function ravenjQueryReadyWrapper(fn) {
|
||||
return _oldReady.call(this, Raven.wrap(fn));
|
||||
};
|
||||
|
||||
var _oldAjax = $.ajax;
|
||||
$.ajax = function ravenAjaxWrapper(url, options) {
|
||||
var keys = ['complete', 'error', 'success'], key;
|
||||
|
||||
// Taken from https://github.com/jquery/jquery/blob/eee2eaf1d7a189d99106423a4206c224ebd5b848/src/ajax.js#L311-L318
|
||||
// If url is an object, simulate pre-1.5 signature
|
||||
if (typeof url === 'object') {
|
||||
options = url;
|
||||
url = undefined;
|
||||
}
|
||||
|
||||
// Force options to be an object
|
||||
options = options || {};
|
||||
|
||||
/*jshint -W084*/
|
||||
while(key = keys.pop()) {
|
||||
if ($.isFunction(options[key])) {
|
||||
options[key] = Raven.wrap(options[key]);
|
||||
}
|
||||
}
|
||||
/*jshint +W084*/
|
||||
|
||||
try {
|
||||
return _oldAjax.call(this, url, options);
|
||||
} catch (e) {
|
||||
Raven.captureException(e);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
}(window, window.Raven, window.jQuery));
|
||||
@@ -1,33 +0,0 @@
|
||||
/**
|
||||
* native plugin
|
||||
*
|
||||
* Extends support for global error handling for asynchronous browser
|
||||
* functions. Adopted from Closure Library's errorhandler.js.
|
||||
*/
|
||||
;(function extendToAsynchronousCallbacks(window, Raven) {
|
||||
"use strict";
|
||||
|
||||
var _helper = function _helper(fnName) {
|
||||
var originalFn = window[fnName];
|
||||
window[fnName] = function ravenAsyncExtension() {
|
||||
// Make a copy of the arguments
|
||||
var args = [].slice.call(arguments);
|
||||
var originalCallback = args[0];
|
||||
if (typeof (originalCallback) === 'function') {
|
||||
args[0] = Raven.wrap(originalCallback);
|
||||
}
|
||||
// IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it
|
||||
// also supports only two arguments and doesn't care what this is, so we
|
||||
// can just call the original function directly.
|
||||
if (originalFn.apply) {
|
||||
return originalFn.apply(this, args);
|
||||
} else {
|
||||
return originalFn(args[0], args[1]);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
_helper('setTimeout');
|
||||
_helper('setInterval');
|
||||
|
||||
}(window, window.Raven));
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* require.js plugin
|
||||
*
|
||||
* Automatically wrap define/require callbacks. (Experimental)
|
||||
*/
|
||||
;(function(window, Raven) {
|
||||
'use strict';
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
window.define = Raven.wrap({deep: false}, define);
|
||||
window.require = Raven.wrap({deep: false}, require);
|
||||
}
|
||||
|
||||
}(window, window.Raven));
|
||||
@@ -1,830 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
// First, check for JSON support
|
||||
// If there is no JSON, we no-op the core features of Raven
|
||||
// since JSON is required to encode the payload
|
||||
var _Raven = window.Raven,
|
||||
hasJSON = !!(typeof JSON === 'object' && JSON.stringify),
|
||||
lastCapturedException,
|
||||
lastEventId,
|
||||
globalServer,
|
||||
globalUser,
|
||||
globalKey,
|
||||
globalProject,
|
||||
globalOptions = {
|
||||
logger: 'javascript',
|
||||
ignoreErrors: [],
|
||||
ignoreUrls: [],
|
||||
whitelistUrls: [],
|
||||
includePaths: [],
|
||||
collectWindowErrors: true,
|
||||
tags: {},
|
||||
maxMessageLength: 100,
|
||||
extra: {}
|
||||
},
|
||||
authQueryString,
|
||||
isRavenInstalled = false,
|
||||
|
||||
objectPrototype = Object.prototype,
|
||||
startTime = now();
|
||||
|
||||
/*
|
||||
* The core Raven singleton
|
||||
*
|
||||
* @this {Raven}
|
||||
*/
|
||||
var Raven = {
|
||||
VERSION: '<%= pkg.version %>',
|
||||
|
||||
debug: true,
|
||||
|
||||
/*
|
||||
* Allow multiple versions of Raven to be installed.
|
||||
* Strip Raven from the global context and returns the instance.
|
||||
*
|
||||
* @return {Raven}
|
||||
*/
|
||||
noConflict: function() {
|
||||
window.Raven = _Raven;
|
||||
return Raven;
|
||||
},
|
||||
|
||||
/*
|
||||
* Configure Raven with a DSN and extra options
|
||||
*
|
||||
* @param {string} dsn The public Sentry DSN
|
||||
* @param {object} options Optional set of of global options [optional]
|
||||
* @return {Raven}
|
||||
*/
|
||||
config: function(dsn, options) {
|
||||
if (globalServer) {
|
||||
logDebug('error', 'Error: Raven has already been configured');
|
||||
return Raven;
|
||||
}
|
||||
if (!dsn) return Raven;
|
||||
|
||||
var uri = parseDSN(dsn),
|
||||
lastSlash = uri.path.lastIndexOf('/'),
|
||||
path = uri.path.substr(1, lastSlash);
|
||||
|
||||
// merge in options
|
||||
if (options) {
|
||||
each(options, function(key, value){
|
||||
globalOptions[key] = value;
|
||||
});
|
||||
}
|
||||
|
||||
// "Script error." is hard coded into browsers for errors that it can't read.
|
||||
// this is the result of a script being pulled in from an external domain and CORS.
|
||||
globalOptions.ignoreErrors.push(/^Script error\.?$/);
|
||||
globalOptions.ignoreErrors.push(/^Javascript error: Script error\.? on line 0$/);
|
||||
|
||||
// join regexp rules into one big rule
|
||||
globalOptions.ignoreErrors = joinRegExp(globalOptions.ignoreErrors);
|
||||
globalOptions.ignoreUrls = globalOptions.ignoreUrls.length ? joinRegExp(globalOptions.ignoreUrls) : false;
|
||||
globalOptions.whitelistUrls = globalOptions.whitelistUrls.length ? joinRegExp(globalOptions.whitelistUrls) : false;
|
||||
globalOptions.includePaths = joinRegExp(globalOptions.includePaths);
|
||||
|
||||
globalKey = uri.user;
|
||||
globalProject = uri.path.substr(lastSlash + 1);
|
||||
|
||||
// assemble the endpoint from the uri pieces
|
||||
globalServer = '//' + uri.host +
|
||||
(uri.port ? ':' + uri.port : '') +
|
||||
'/' + path + 'api/' + globalProject + '/store/';
|
||||
|
||||
if (uri.protocol) {
|
||||
globalServer = uri.protocol + ':' + globalServer;
|
||||
}
|
||||
|
||||
if (globalOptions.fetchContext) {
|
||||
TraceKit.remoteFetching = true;
|
||||
}
|
||||
|
||||
if (globalOptions.linesOfContext) {
|
||||
TraceKit.linesOfContext = globalOptions.linesOfContext;
|
||||
}
|
||||
|
||||
TraceKit.collectWindowErrors = !!globalOptions.collectWindowErrors;
|
||||
|
||||
setAuthQueryString();
|
||||
|
||||
// return for chaining
|
||||
return Raven;
|
||||
},
|
||||
|
||||
/*
|
||||
* Installs a global window.onerror error handler
|
||||
* to capture and report uncaught exceptions.
|
||||
* At this point, install() is required to be called due
|
||||
* to the way TraceKit is set up.
|
||||
*
|
||||
* @return {Raven}
|
||||
*/
|
||||
install: function() {
|
||||
if (isSetup() && !isRavenInstalled) {
|
||||
TraceKit.report.subscribe(handleStackInfo);
|
||||
isRavenInstalled = true;
|
||||
}
|
||||
|
||||
return Raven;
|
||||
},
|
||||
|
||||
/*
|
||||
* Wrap code within a context so Raven can capture errors
|
||||
* reliably across domains that is executed immediately.
|
||||
*
|
||||
* @param {object} options A specific set of options for this context [optional]
|
||||
* @param {function} func The callback to be immediately executed within the context
|
||||
* @param {array} args An array of arguments to be called with the callback [optional]
|
||||
*/
|
||||
context: function(options, func, args) {
|
||||
if (isFunction(options)) {
|
||||
args = func || [];
|
||||
func = options;
|
||||
options = undefined;
|
||||
}
|
||||
|
||||
return Raven.wrap(options, func).apply(this, args);
|
||||
},
|
||||
|
||||
/*
|
||||
* Wrap code within a context and returns back a new function to be executed
|
||||
*
|
||||
* @param {object} options A specific set of options for this context [optional]
|
||||
* @param {function} func The function to be wrapped in a new context
|
||||
* @return {function} The newly wrapped functions with a context
|
||||
*/
|
||||
wrap: function(options, func) {
|
||||
// 1 argument has been passed, and it's not a function
|
||||
// so just return it
|
||||
if (isUndefined(func) && !isFunction(options)) {
|
||||
return options;
|
||||
}
|
||||
|
||||
// options is optional
|
||||
if (isFunction(options)) {
|
||||
func = options;
|
||||
options = undefined;
|
||||
}
|
||||
|
||||
// At this point, we've passed along 2 arguments, and the second one
|
||||
// is not a function either, so we'll just return the second argument.
|
||||
if (!isFunction(func)) {
|
||||
return func;
|
||||
}
|
||||
|
||||
// We don't wanna wrap it twice!
|
||||
if (func.__raven__) {
|
||||
return func;
|
||||
}
|
||||
|
||||
function wrapped() {
|
||||
var args = [], i = arguments.length,
|
||||
deep = !options || options && options.deep !== false;
|
||||
// Recursively wrap all of a function's arguments that are
|
||||
// functions themselves.
|
||||
|
||||
while(i--) args[i] = deep ? Raven.wrap(options, arguments[i]) : arguments[i];
|
||||
|
||||
try {
|
||||
/*jshint -W040*/
|
||||
return func.apply(this, args);
|
||||
} catch(e) {
|
||||
Raven.captureException(e, options);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// copy over properties of the old function
|
||||
for (var property in func) {
|
||||
if (hasKey(func, property)) {
|
||||
wrapped[property] = func[property];
|
||||
}
|
||||
}
|
||||
|
||||
// Signal that this function has been wrapped already
|
||||
// for both debugging and to prevent it to being wrapped twice
|
||||
wrapped.__raven__ = true;
|
||||
wrapped.__inner__ = func;
|
||||
|
||||
return wrapped;
|
||||
},
|
||||
|
||||
/*
|
||||
* Uninstalls the global error handler.
|
||||
*
|
||||
* @return {Raven}
|
||||
*/
|
||||
uninstall: function() {
|
||||
TraceKit.report.uninstall();
|
||||
isRavenInstalled = false;
|
||||
|
||||
return Raven;
|
||||
},
|
||||
|
||||
/*
|
||||
* Manually capture an exception and send it over to Sentry
|
||||
*
|
||||
* @param {error} ex An exception to be logged
|
||||
* @param {object} options A specific set of options for this error [optional]
|
||||
* @return {Raven}
|
||||
*/
|
||||
captureException: function(ex, options) {
|
||||
// If not an Error is passed through, recall as a message instead
|
||||
if (!isError(ex)) return Raven.captureMessage(ex, options);
|
||||
|
||||
// Store the raw exception object for potential debugging and introspection
|
||||
lastCapturedException = ex;
|
||||
|
||||
// TraceKit.report will re-raise any exception passed to it,
|
||||
// which means you have to wrap it in try/catch. Instead, we
|
||||
// can wrap it here and only re-raise if TraceKit.report
|
||||
// raises an exception different from the one we asked to
|
||||
// report on.
|
||||
try {
|
||||
TraceKit.report(ex, options);
|
||||
} catch(ex1) {
|
||||
if(ex !== ex1) {
|
||||
throw ex1;
|
||||
}
|
||||
}
|
||||
|
||||
return Raven;
|
||||
},
|
||||
|
||||
/*
|
||||
* Manually send a message to Sentry
|
||||
*
|
||||
* @param {string} msg A plain message to be captured in Sentry
|
||||
* @param {object} options A specific set of options for this message [optional]
|
||||
* @return {Raven}
|
||||
*/
|
||||
captureMessage: function(msg, options) {
|
||||
// config() automagically converts ignoreErrors from a list to a RegExp so we need to test for an
|
||||
// early call; we'll error on the side of logging anything called before configuration since it's
|
||||
// probably something you should see:
|
||||
if (!!globalOptions.ignoreErrors.test && globalOptions.ignoreErrors.test(msg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire away!
|
||||
send(
|
||||
objectMerge({
|
||||
message: msg + '' // Make sure it's actually a string
|
||||
}, options)
|
||||
);
|
||||
|
||||
return Raven;
|
||||
},
|
||||
|
||||
/*
|
||||
* Set/clear a user to be sent along with the payload.
|
||||
*
|
||||
* @param {object} user An object representing user data [optional]
|
||||
* @return {Raven}
|
||||
*/
|
||||
setUserContext: function(user) {
|
||||
globalUser = user;
|
||||
|
||||
return Raven;
|
||||
},
|
||||
|
||||
/*
|
||||
* Set extra attributes to be sent along with the payload.
|
||||
*
|
||||
* @param {object} extra An object representing extra data [optional]
|
||||
* @return {Raven}
|
||||
*/
|
||||
setExtraContext: function(extra) {
|
||||
globalOptions.extra = extra || {};
|
||||
|
||||
return Raven;
|
||||
},
|
||||
|
||||
/*
|
||||
* Set tags to be sent along with the payload.
|
||||
*
|
||||
* @param {object} tags An object representing tags [optional]
|
||||
* @return {Raven}
|
||||
*/
|
||||
setTagsContext: function(tags) {
|
||||
globalOptions.tags = tags || {};
|
||||
|
||||
return Raven;
|
||||
},
|
||||
|
||||
/*
|
||||
* Set release version of application
|
||||
*
|
||||
* @param {string} release Typically something like a git SHA to identify version
|
||||
* @return {Raven}
|
||||
*/
|
||||
setReleaseContext: function(release) {
|
||||
globalOptions.release = release;
|
||||
|
||||
return Raven;
|
||||
},
|
||||
|
||||
/*
|
||||
* Set the dataCallback option
|
||||
*
|
||||
* @param {function} callback The callback to run which allows the
|
||||
* data blob to be mutated before sending
|
||||
* @return {Raven}
|
||||
*/
|
||||
setDataCallback: function(callback) {
|
||||
globalOptions.dataCallback = callback;
|
||||
|
||||
return Raven;
|
||||
},
|
||||
|
||||
/*
|
||||
* Set the shouldSendCallback option
|
||||
*
|
||||
* @param {function} callback The callback to run which allows
|
||||
* introspecting the blob before sending
|
||||
* @return {Raven}
|
||||
*/
|
||||
setShouldSendCallback: function(callback) {
|
||||
globalOptions.shouldSendCallback = callback;
|
||||
|
||||
return Raven;
|
||||
},
|
||||
|
||||
/*
|
||||
* Get the latest raw exception that was captured by Raven.
|
||||
*
|
||||
* @return {error}
|
||||
*/
|
||||
lastException: function() {
|
||||
return lastCapturedException;
|
||||
},
|
||||
|
||||
/*
|
||||
* Get the last event id
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
lastEventId: function() {
|
||||
return lastEventId;
|
||||
},
|
||||
|
||||
/*
|
||||
* Determine if Raven is setup and ready to go.
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
isSetup: function() {
|
||||
return isSetup();
|
||||
}
|
||||
};
|
||||
|
||||
Raven.setUser = Raven.setUserContext; // To be deprecated
|
||||
|
||||
function triggerEvent(eventType, options) {
|
||||
var event, key;
|
||||
|
||||
options = options || {};
|
||||
|
||||
eventType = 'raven' + eventType.substr(0,1).toUpperCase() + eventType.substr(1);
|
||||
|
||||
if (document.createEvent) {
|
||||
event = document.createEvent('HTMLEvents');
|
||||
event.initEvent(eventType, true, true);
|
||||
} else {
|
||||
event = document.createEventObject();
|
||||
event.eventType = eventType;
|
||||
}
|
||||
|
||||
for (key in options) if (hasKey(options, key)) {
|
||||
event[key] = options[key];
|
||||
}
|
||||
|
||||
if (document.createEvent) {
|
||||
// IE9 if standards
|
||||
document.dispatchEvent(event);
|
||||
} else {
|
||||
// IE8 regardless of Quirks or Standards
|
||||
// IE9 if quirks
|
||||
try {
|
||||
document.fireEvent('on' + event.eventType.toLowerCase(), event);
|
||||
} catch(e) {}
|
||||
}
|
||||
}
|
||||
|
||||
var dsnKeys = 'source protocol user pass host port path'.split(' '),
|
||||
dsnPattern = /^(?:(\w+):)?\/\/(\w+)(:\w+)?@([\w\.-]+)(?::(\d+))?(\/.*)/;
|
||||
|
||||
function RavenConfigError(message) {
|
||||
this.name = 'RavenConfigError';
|
||||
this.message = message;
|
||||
}
|
||||
RavenConfigError.prototype = new Error();
|
||||
RavenConfigError.prototype.constructor = RavenConfigError;
|
||||
|
||||
/**** Private functions ****/
|
||||
function parseDSN(str) {
|
||||
var m = dsnPattern.exec(str),
|
||||
dsn = {},
|
||||
i = 7;
|
||||
|
||||
try {
|
||||
while (i--) dsn[dsnKeys[i]] = m[i] || '';
|
||||
} catch(e) {
|
||||
throw new RavenConfigError('Invalid DSN: ' + str);
|
||||
}
|
||||
|
||||
if (dsn.pass)
|
||||
throw new RavenConfigError('Do not specify your private key in the DSN!');
|
||||
|
||||
return dsn;
|
||||
}
|
||||
|
||||
function isUndefined(what) {
|
||||
return what === void 0;
|
||||
}
|
||||
|
||||
function isFunction(what) {
|
||||
return typeof what === 'function';
|
||||
}
|
||||
|
||||
function isString(what) {
|
||||
return objectPrototype.toString.call(what) === '[object String]';
|
||||
}
|
||||
|
||||
function isObject(what) {
|
||||
return typeof what === 'object' && what !== null;
|
||||
}
|
||||
|
||||
function isEmptyObject(what) {
|
||||
for (var k in what) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Sorta yanked from https://github.com/joyent/node/blob/aa3b4b4/lib/util.js#L560
|
||||
// with some tiny modifications
|
||||
function isError(what) {
|
||||
return isObject(what) &&
|
||||
objectPrototype.toString.call(what) === '[object Error]' ||
|
||||
what instanceof Error;
|
||||
}
|
||||
|
||||
/**
|
||||
* hasKey, a better form of hasOwnProperty
|
||||
* Example: hasKey(MainHostObject, property) === true/false
|
||||
*
|
||||
* @param {Object} host object to check property
|
||||
* @param {string} key to check
|
||||
*/
|
||||
function hasKey(object, key) {
|
||||
return objectPrototype.hasOwnProperty.call(object, key);
|
||||
}
|
||||
|
||||
function each(obj, callback) {
|
||||
var i, j;
|
||||
|
||||
if (isUndefined(obj.length)) {
|
||||
for (i in obj) {
|
||||
if (hasKey(obj, i)) {
|
||||
callback.call(null, i, obj[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
j = obj.length;
|
||||
if (j) {
|
||||
for (i = 0; i < j; i++) {
|
||||
callback.call(null, i, obj[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function setAuthQueryString() {
|
||||
authQueryString =
|
||||
'?sentry_version=4' +
|
||||
'&sentry_client=raven-js/' + Raven.VERSION +
|
||||
'&sentry_key=' + globalKey;
|
||||
}
|
||||
|
||||
|
||||
function handleStackInfo(stackInfo, options) {
|
||||
var frames = [];
|
||||
|
||||
if (stackInfo.stack && stackInfo.stack.length) {
|
||||
each(stackInfo.stack, function(i, stack) {
|
||||
var frame = normalizeFrame(stack);
|
||||
if (frame) {
|
||||
frames.push(frame);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
triggerEvent('handle', {
|
||||
stackInfo: stackInfo,
|
||||
options: options
|
||||
});
|
||||
|
||||
processException(
|
||||
stackInfo.name,
|
||||
stackInfo.message,
|
||||
stackInfo.url,
|
||||
stackInfo.lineno,
|
||||
frames,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeFrame(frame) {
|
||||
if (!frame.url) return;
|
||||
|
||||
// normalize the frames data
|
||||
var normalized = {
|
||||
filename: frame.url,
|
||||
lineno: frame.line,
|
||||
colno: frame.column,
|
||||
'function': frame.func || '?'
|
||||
}, context = extractContextFromFrame(frame), i;
|
||||
|
||||
if (context) {
|
||||
var keys = ['pre_context', 'context_line', 'post_context'];
|
||||
i = 3;
|
||||
while (i--) normalized[keys[i]] = context[i];
|
||||
}
|
||||
|
||||
normalized.in_app = !( // determine if an exception came from outside of our app
|
||||
// first we check the global includePaths list.
|
||||
!globalOptions.includePaths.test(normalized.filename) ||
|
||||
// Now we check for fun, if the function name is Raven or TraceKit
|
||||
/(Raven|TraceKit)\./.test(normalized['function']) ||
|
||||
// finally, we do a last ditch effort and check for raven.min.js
|
||||
/raven\.(min\.)?js$/.test(normalized.filename)
|
||||
);
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
function extractContextFromFrame(frame) {
|
||||
// immediately check if we should even attempt to parse a context
|
||||
if (!frame.context || !globalOptions.fetchContext) return;
|
||||
|
||||
var context = frame.context,
|
||||
pivot = ~~(context.length / 2),
|
||||
i = context.length, isMinified = false;
|
||||
|
||||
while (i--) {
|
||||
// We're making a guess to see if the source is minified or not.
|
||||
// To do that, we make the assumption if *any* of the lines passed
|
||||
// in are greater than 300 characters long, we bail.
|
||||
// Sentry will see that there isn't a context
|
||||
if (context[i].length > 300) {
|
||||
isMinified = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isMinified) {
|
||||
// The source is minified and we don't know which column. Fuck it.
|
||||
if (isUndefined(frame.column)) return;
|
||||
|
||||
// If the source is minified and has a frame column
|
||||
// we take a chunk of the offending line to hopefully shed some light
|
||||
return [
|
||||
[], // no pre_context
|
||||
context[pivot].substr(frame.column, 50), // grab 50 characters, starting at the offending column
|
||||
[] // no post_context
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
context.slice(0, pivot), // pre_context
|
||||
context[pivot], // context_line
|
||||
context.slice(pivot + 1) // post_context
|
||||
];
|
||||
}
|
||||
|
||||
function processException(type, message, fileurl, lineno, frames, options) {
|
||||
var stacktrace, label, i;
|
||||
|
||||
// In some instances message is not actually a string, no idea why,
|
||||
// so we want to always coerce it to one.
|
||||
message += '';
|
||||
|
||||
// Sometimes an exception is getting logged in Sentry as
|
||||
// <no message value>
|
||||
// This can only mean that the message was falsey since this value
|
||||
// is hardcoded into Sentry itself.
|
||||
// At this point, if the message is falsey, we bail since it's useless
|
||||
if (type === 'Error' && !message) return;
|
||||
|
||||
if (globalOptions.ignoreErrors.test(message)) return;
|
||||
|
||||
if (frames && frames.length) {
|
||||
fileurl = frames[0].filename || fileurl;
|
||||
// Sentry expects frames oldest to newest
|
||||
// and JS sends them as newest to oldest
|
||||
frames.reverse();
|
||||
stacktrace = {frames: frames};
|
||||
} else if (fileurl) {
|
||||
stacktrace = {
|
||||
frames: [{
|
||||
filename: fileurl,
|
||||
lineno: lineno,
|
||||
in_app: true
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
// Truncate the message to a max of characters
|
||||
message = truncate(message, globalOptions.maxMessageLength);
|
||||
|
||||
if (globalOptions.ignoreUrls && globalOptions.ignoreUrls.test(fileurl)) return;
|
||||
if (globalOptions.whitelistUrls && !globalOptions.whitelistUrls.test(fileurl)) return;
|
||||
|
||||
label = lineno ? message + ' at ' + lineno : message;
|
||||
|
||||
// Fire away!
|
||||
send(
|
||||
objectMerge({
|
||||
// sentry.interfaces.Exception
|
||||
exception: {
|
||||
type: type,
|
||||
value: message
|
||||
},
|
||||
// sentry.interfaces.Stacktrace
|
||||
stacktrace: stacktrace,
|
||||
culprit: fileurl,
|
||||
message: label
|
||||
}, options)
|
||||
);
|
||||
}
|
||||
|
||||
function objectMerge(obj1, obj2) {
|
||||
if (!obj2) {
|
||||
return obj1;
|
||||
}
|
||||
each(obj2, function(key, value){
|
||||
obj1[key] = value;
|
||||
});
|
||||
return obj1;
|
||||
}
|
||||
|
||||
function truncate(str, max) {
|
||||
return str.length <= max ? str : str.substr(0, max) + '\u2026';
|
||||
}
|
||||
|
||||
function now() {
|
||||
return +new Date();
|
||||
}
|
||||
|
||||
function getHttpData() {
|
||||
var http = {
|
||||
url: document.location.href,
|
||||
headers: {
|
||||
'User-Agent': navigator.userAgent
|
||||
}
|
||||
};
|
||||
|
||||
if (document.referrer) {
|
||||
http.headers.Referer = document.referrer;
|
||||
}
|
||||
|
||||
return http;
|
||||
}
|
||||
|
||||
function send(data) {
|
||||
if (!isSetup()) return;
|
||||
|
||||
data = objectMerge({
|
||||
project: globalProject,
|
||||
logger: globalOptions.logger,
|
||||
platform: 'javascript',
|
||||
// sentry.interfaces.Http
|
||||
request: getHttpData()
|
||||
}, data);
|
||||
|
||||
// Merge in the tags and extra separately since objectMerge doesn't handle a deep merge
|
||||
data.tags = objectMerge(objectMerge({}, globalOptions.tags), data.tags);
|
||||
data.extra = objectMerge(objectMerge({}, globalOptions.extra), data.extra);
|
||||
|
||||
// Send along our own collected metadata with extra
|
||||
data.extra = objectMerge({
|
||||
'session:duration': now() - startTime
|
||||
}, data.extra);
|
||||
|
||||
// If there are no tags/extra, strip the key from the payload alltogther.
|
||||
if (isEmptyObject(data.tags)) delete data.tags;
|
||||
|
||||
if (globalUser) {
|
||||
// sentry.interfaces.User
|
||||
data.user = globalUser;
|
||||
}
|
||||
|
||||
// Include the release iff it's defined in globalOptions
|
||||
if (globalOptions.release) data.release = globalOptions.release;
|
||||
|
||||
if (isFunction(globalOptions.dataCallback)) {
|
||||
data = globalOptions.dataCallback(data) || data;
|
||||
}
|
||||
|
||||
// Why??????????
|
||||
if (!data || isEmptyObject(data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the request should be filtered or not
|
||||
if (isFunction(globalOptions.shouldSendCallback) && !globalOptions.shouldSendCallback(data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Send along an event_id if not explicitly passed.
|
||||
// This event_id can be used to reference the error within Sentry itself.
|
||||
// Set lastEventId after we know the error should actually be sent
|
||||
lastEventId = data.event_id || (data.event_id = uuid4());
|
||||
|
||||
makeRequest(data);
|
||||
}
|
||||
|
||||
|
||||
function makeRequest(data) {
|
||||
var img = newImage(),
|
||||
src = globalServer + authQueryString + '&sentry_data=' + encodeURIComponent(JSON.stringify(data));
|
||||
|
||||
img.crossOrigin = 'anonymous';
|
||||
img.onload = function success() {
|
||||
triggerEvent('success', {
|
||||
data: data,
|
||||
src: src
|
||||
});
|
||||
};
|
||||
img.onerror = img.onabort = function failure() {
|
||||
triggerEvent('failure', {
|
||||
data: data,
|
||||
src: src
|
||||
});
|
||||
};
|
||||
img.src = src;
|
||||
}
|
||||
|
||||
// Note: this is shitty, but I can't figure out how to get
|
||||
// sinon to stub document.createElement without breaking everything
|
||||
// so this wrapper is just so I can stub it for tests.
|
||||
function newImage() {
|
||||
return document.createElement('img');
|
||||
}
|
||||
|
||||
function isSetup() {
|
||||
if (!hasJSON) return false; // needs JSON support
|
||||
if (!globalServer) {
|
||||
logDebug('error', 'Error: Raven has not been configured.');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function joinRegExp(patterns) {
|
||||
// Combine an array of regular expressions and strings into one large regexp
|
||||
// Be mad.
|
||||
var sources = [],
|
||||
i = 0, len = patterns.length,
|
||||
pattern;
|
||||
|
||||
for (; i < len; i++) {
|
||||
pattern = patterns[i];
|
||||
if (isString(pattern)) {
|
||||
// If it's a string, we need to escape it
|
||||
// Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
|
||||
sources.push(pattern.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"));
|
||||
} else if (pattern && pattern.source) {
|
||||
// If it's a regexp already, we want to extract the source
|
||||
sources.push(pattern.source);
|
||||
}
|
||||
// Intentionally skip other cases
|
||||
}
|
||||
return new RegExp(sources.join('|'), 'i');
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
|
||||
function uuid4() {
|
||||
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
|
||||
var r = Math.random()*16|0,
|
||||
v = c == 'x' ? r : (r&0x3|0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
function logDebug(level, message) {
|
||||
if (window.console && console[level] && Raven.debug) {
|
||||
console[level](message);
|
||||
}
|
||||
}
|
||||
|
||||
function afterLoad() {
|
||||
// Attempt to initialize Raven on load
|
||||
var RavenConfig = window.RavenConfig;
|
||||
if (RavenConfig) {
|
||||
Raven.config(RavenConfig.dsn, RavenConfig.config).install();
|
||||
}
|
||||
}
|
||||
afterLoad();
|
||||
@@ -1,11 +0,0 @@
|
||||
/*! Raven.js <%= pkg.release %> (<%= gitinfo.local.branch.current.shortSHA %>) | github.com/getsentry/raven-js */
|
||||
|
||||
/*
|
||||
* Includes TraceKit
|
||||
* https://github.com/getsentry/TraceKit
|
||||
*
|
||||
* Copyright <%= grunt.template.today('yyyy') %> Matt Robenolt and other contributors
|
||||
* Released under the BSD license
|
||||
* https://github.com/getsentry/raven-js/blob/master/LICENSE
|
||||
*
|
||||
*/
|
||||
@@ -1,19 +0,0 @@
|
||||
// Expose Raven to the world
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD
|
||||
window.Raven = Raven;
|
||||
define('raven', [], function() {
|
||||
return Raven;
|
||||
});
|
||||
} else if (typeof module === 'object') {
|
||||
// browserify
|
||||
module.exports = Raven;
|
||||
} else if (typeof exports === 'object') {
|
||||
// CommonJS
|
||||
exports = Raven;
|
||||
} else {
|
||||
// Everything else
|
||||
window.Raven = Raven;
|
||||
}
|
||||
|
||||
})(typeof window !== 'undefined' ? window : this);
|
||||
@@ -1,2 +0,0 @@
|
||||
;(function(window, undefined){
|
||||
'use strict';
|
||||
@@ -1,62 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Raven.js Test Suite</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link rel="stylesheet" href="../node_modules/grunt-mocha/node_modules/mocha/mocha.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
<!-- Mocha -->
|
||||
<script src="../node_modules/grunt-mocha/node_modules/mocha/mocha.js"></script>
|
||||
<script src="../node_modules/chai/chai.js"></script>
|
||||
<script>
|
||||
mocha.ui('bdd');
|
||||
mocha.reporter('html');
|
||||
var assert = chai.assert
|
||||
</script>
|
||||
|
||||
<!-- Mocking -->
|
||||
<script src="../node_modules/sinon/pkg/sinon.js"></script>
|
||||
<script>
|
||||
beforeEach(function() {
|
||||
this.sinon = sinon.sandbox.create();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
this.sinon.restore();
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- Raven -->
|
||||
<script src="../vendor/TraceKit/tracekit.js"></script>
|
||||
<script src="../src/raven.js"></script>
|
||||
|
||||
<!-- Tests -->
|
||||
<script src="raven.test.js"></script>
|
||||
|
||||
<script>
|
||||
if (!window.PHANTOMJS) {
|
||||
(function(runner){
|
||||
var failed = [];
|
||||
|
||||
runner.on('fail', function(test, err){
|
||||
failed.push({
|
||||
title: test.title,
|
||||
fullTitle: test.fullTitle(),
|
||||
error: {
|
||||
message: err.message,
|
||||
stack: err.stack
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
runner.on('end', function(){
|
||||
runner.stats.failed = failed;
|
||||
global.mochaResults = runner.stats;
|
||||
});
|
||||
})(mocha.run());
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
1044
htdocs/includes/raven-js/vendor/TraceKit/tracekit.js
vendored
1044
htdocs/includes/raven-js/vendor/TraceKit/tracekit.js
vendored
File diff suppressed because it is too large
Load Diff
5
htdocs/includes/raven/raven/.gitignore
vendored
5
htdocs/includes/raven/raven/.gitignore
vendored
@@ -1,5 +0,0 @@
|
||||
*.lock
|
||||
package.xml
|
||||
/vendor
|
||||
.idea
|
||||
.php_cs.cache
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
$finder = Symfony\CS\Finder\DefaultFinder::create()
|
||||
->in(__DIR__)
|
||||
;
|
||||
|
||||
return Symfony\CS\Config\Config::create()
|
||||
->setUsingCache(true)
|
||||
->setUsingLinter(true)
|
||||
->level(Symfony\CS\FixerInterface::PSR2_LEVEL)
|
||||
->finder($finder)
|
||||
;
|
||||
@@ -1,30 +0,0 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- hhvm
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
- php: 7.0
|
||||
fast_finish: true
|
||||
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
|
||||
before_install:
|
||||
- composer self-update
|
||||
|
||||
install: travis_retry composer install --no-interaction --prefer-source
|
||||
|
||||
script:
|
||||
- vendor/bin/php-cs-fixer fix --config-file=.php_cs --verbose --diff --dry-run
|
||||
- vendor/bin/phpunit
|
||||
@@ -1,4 +0,0 @@
|
||||
The Raven PHP client was originally written by Michael van Tellingen
|
||||
and is maintained by the Sentry Team.
|
||||
|
||||
http://github.com/getsentry/raven-php/contributors
|
||||
@@ -1,45 +0,0 @@
|
||||
0.12.1
|
||||
------
|
||||
|
||||
- Dont send empty values for various context.
|
||||
|
||||
|
||||
0.12.0
|
||||
------
|
||||
|
||||
- Bumped protocol version to 6.
|
||||
- Fixed an issue with the async curl handler (GH-216).
|
||||
- Removed UDP transport.
|
||||
|
||||
0.11.0
|
||||
------
|
||||
|
||||
- New configuration parameter: 'release'
|
||||
- New configuration parameter: 'message_limit'
|
||||
- New configuration parameter: 'curl_ssl_version'
|
||||
- New configuration parameter: 'curl_ipv4'
|
||||
- New configuration parameter: 'verify_ssl'
|
||||
- Updated remote endpoint to use modern project-based path.
|
||||
- Expanded default sanitizer support to include 'auth_pw' attribute.
|
||||
|
||||
0.10.0
|
||||
------
|
||||
|
||||
- Added a default certificate bundle which includes common root CA's
|
||||
as well as getsentry.com's CA.
|
||||
|
||||
0.9.1
|
||||
-----
|
||||
|
||||
- Change default curl connection to 'sync'
|
||||
- Improve CLI reporting
|
||||
|
||||
|
||||
0.9.0
|
||||
-----
|
||||
|
||||
- Protocol version 5
|
||||
- Default to asynchronous HTTP handler using curl_multi.
|
||||
|
||||
|
||||
(For previous versions see the commit history)
|
||||
@@ -1,12 +0,0 @@
|
||||
Copyright (c) 2012 Sentry Team and individual contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the Raven nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,17 +0,0 @@
|
||||
.PHONY: test
|
||||
|
||||
develop:
|
||||
composer install --dev
|
||||
make setup-git
|
||||
|
||||
cs:
|
||||
vendor/bin/php-cs-fixer fix --config-file=.php_cs --verbose --diff
|
||||
|
||||
cs-dry-run:
|
||||
vendor/bin/php-cs-fixer fix --config-file=.php_cs --verbose --diff --dry-run
|
||||
|
||||
test:
|
||||
vendor/bin/phpunit
|
||||
|
||||
setup-git:
|
||||
git config branch.autosetuprebase always
|
||||
@@ -1,273 +0,0 @@
|
||||
raven-php
|
||||
=========
|
||||
|
||||
.. image:: https://secure.travis-ci.org/getsentry/raven-php.png?branch=master
|
||||
:target: http://travis-ci.org/getsentry/raven-php
|
||||
|
||||
|
||||
raven-php is a PHP client for `Sentry <http://aboutsentry.com/>`_.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Instantiate a new client with a compatible DSN
|
||||
$client = new Raven_Client('http://public:secret@example.com/1');
|
||||
|
||||
// Capture a message
|
||||
$event_id = $client->getIdent($client->captureMessage('my log message'));
|
||||
if ($client->getLastError() !== null) {
|
||||
printf('There was an error sending the event to Sentry: %s', $client->getLastError());
|
||||
}
|
||||
|
||||
// Capture an exception
|
||||
$event_id = $client->getIdent($client->captureException($ex));
|
||||
|
||||
// Provide some additional data with an exception
|
||||
$event_id = $client->getIdent($client->captureException($ex, array(
|
||||
'extra' => array(
|
||||
'php_version' => phpversion()
|
||||
),
|
||||
)));
|
||||
|
||||
// Give the user feedback
|
||||
echo "Sorry, there was an error!";
|
||||
echo "Your reference ID is " . $event_id;
|
||||
|
||||
// Install error handlers and shutdown function to catch fatal errors
|
||||
$error_handler = new Raven_ErrorHandler($client);
|
||||
$error_handler->registerExceptionHandler();
|
||||
$error_handler->registerErrorHandler();
|
||||
$error_handler->registerShutdownFunction();
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Install with Composer
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you're using `Composer <https://getcomposer.org/>`_ to manage
|
||||
dependencies, you can add Raven with it.
|
||||
|
||||
::
|
||||
|
||||
$ composer require raven/raven:$VERSION
|
||||
|
||||
(replace ``$VERSION`` with one of the available versions on `Packagist <https://packagist.org/packages/raven/raven>`_)
|
||||
or to get the latest version off the master branch:
|
||||
|
||||
::
|
||||
|
||||
$ composer require raven/raven:dev-master
|
||||
|
||||
Note that using unstable versions is not recommended and should be avoided. Also
|
||||
you should define a maximum version, e.g. by doing ``>=0.6,<1.0`` or ``~0.6``.
|
||||
|
||||
Alternatively, use the ``^`` operator for specifying a version, e.g.,
|
||||
|
||||
::
|
||||
|
||||
$ composer require raven/raven:^0.11.0
|
||||
|
||||
Composer will take care of the autoloading for you, so if you require the
|
||||
``vendor/autoload.php``, you're good to go.
|
||||
|
||||
|
||||
Install source from GitHub
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To install the source code:
|
||||
|
||||
::
|
||||
|
||||
$ git clone git://github.com/getsentry/raven-php.git
|
||||
|
||||
And including it using the autoloader:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once '/path/to/Raven/library/Raven/Autoloader.php';
|
||||
Raven_Autoloader::register();
|
||||
|
||||
Testing Your Connection
|
||||
-----------------------
|
||||
|
||||
The PHP client includes a simple helper script to test your connection and credentials with
|
||||
the Sentry master server:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ bin/raven test https://public:secret@app.getsentry.com/1
|
||||
Client configuration:
|
||||
-> servers: [https://sentry.example.com/api/store/]
|
||||
-> project: 1
|
||||
-> public_key: public
|
||||
-> secret_key: secret
|
||||
|
||||
Sending a test event:
|
||||
-> event ID: f1765c9aed4f4ceebe5a93df9eb2d34f
|
||||
|
||||
Done!
|
||||
|
||||
.. note:: The CLI enforces the synchronous option on HTTP requests whereas the default configuration is asyncrhonous.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Several options exist that allow you to configure the behavior of the ``Raven_Client``. These are passed as the
|
||||
second parameter of the constructor, and is expected to be an array of key value pairs:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client = new Raven_Client($dsn, array(
|
||||
'option_name' => 'value',
|
||||
));
|
||||
|
||||
``name``
|
||||
~~~~~~~~
|
||||
|
||||
A string to override the default value for the server's hostname.
|
||||
|
||||
Defaults to ``Raven_Compat::gethostname()``.
|
||||
|
||||
``tags``
|
||||
~~~~~~~~
|
||||
|
||||
An array of tags to apply to events in this context.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'tags' => array(
|
||||
'php_version' => phpversion(),
|
||||
)
|
||||
|
||||
|
||||
``curl_method``
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Defaults to 'sync'.
|
||||
|
||||
Available methods:
|
||||
|
||||
- sync (default): send requests immediately when they're made
|
||||
- async: uses a curl_multi handler for best-effort asynchronous submissions
|
||||
- exec: asynchronously send events by forking a curl process for each item
|
||||
|
||||
``curl_path``
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Defaults to 'curl'.
|
||||
|
||||
Specify the path to the curl binary to be used with the 'exec' curl method.
|
||||
|
||||
|
||||
``trace``
|
||||
~~~~~~~~~
|
||||
|
||||
Set this to ``false`` to disable reflection tracing (function calling arguments) in stacktraces.
|
||||
|
||||
|
||||
``logger``
|
||||
~~~~~~~~~~
|
||||
|
||||
Adjust the default logger name for messages.
|
||||
|
||||
Defaults to ``php``.
|
||||
|
||||
``ca_cert``
|
||||
~~~~~~~~~~~
|
||||
|
||||
The path to the CA certificate bundle.
|
||||
|
||||
Defaults to the common bundle which includes getsentry.com: ./data/cacert.pem
|
||||
|
||||
Caveats:
|
||||
|
||||
- The CA bundle is ignored unless curl throws an error suggesting it needs a cert.
|
||||
- The option is only currently used within the synchronous curl transport.
|
||||
|
||||
``curl_ssl_version``
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The SSL version (2 or 3) to use.
|
||||
By default PHP will try to determine this itself, although in some cases this must be set manually.
|
||||
|
||||
``message_limit``
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Defaults to 1024 characters.
|
||||
|
||||
This value is used to truncate message and frame variables. However it is not guarantee that length of whole message will be restricted by this value.
|
||||
|
||||
``processors``
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
An array of classes to use to process data before it is sent to Sentry. By default, Raven_SanitizeDataProcessor is used
|
||||
|
||||
``processorOptions``
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Options that will be passed on to a setProcessorOptions() function in a Raven_Processor sub-class before that Processor is added to the list of processors used by Raven_Client
|
||||
|
||||
An example of overriding the regular expressions in Raven_SanitizeDataProcessor is below:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'processorOptions' => array(
|
||||
'Raven_SanitizeDataProcessor' => array(
|
||||
'fields_re' => '/(user_password|user_token|user_secret)/i',
|
||||
'values_re' => '/^(?:\d[ -]*?){15,16}$/'
|
||||
)
|
||||
)
|
||||
|
||||
Providing Request Context
|
||||
-------------------------
|
||||
|
||||
Most of the time you're not actually calling out to Raven directly, but you still want to provide some additional context. This lifecycle generally constists of something like the following:
|
||||
|
||||
- Set some context via a middleware (e.g. the logged in user)
|
||||
- Send all given context with any events during the request lifecycle
|
||||
- Cleanup context
|
||||
|
||||
There are three primary methods for providing request context:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// bind the logged in user
|
||||
$client->user_context(array('email' => 'foo@example.com'));
|
||||
|
||||
// tag the request with something interesting
|
||||
$client->tags_context(array('interesting' => 'yes'));
|
||||
|
||||
// provide a bit of additional context
|
||||
$client->extra_context(array('happiness' => 'very'));
|
||||
|
||||
|
||||
If you're performing additional requests during the lifecycle, you'll also need to ensure you cleanup the context (to reset its state):
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client->context->clear();
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
First, make sure you can run the test suite. Install development dependencies :
|
||||
|
||||
::
|
||||
|
||||
$ composer install
|
||||
|
||||
You may now use phpunit :
|
||||
|
||||
::
|
||||
|
||||
$ vendor/bin/phpunit
|
||||
|
||||
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* `Bug Tracker <http://github.com/getsentry/raven-php/issues>`_
|
||||
* `Code <http://github.com/getsentry/raven-php>`_
|
||||
* `Mailing List <https://groups.google.com/group/getsentry>`_
|
||||
* `IRC <irc://irc.freenode.net/sentry>`_ (irc.freenode.net, #sentry)
|
||||
@@ -1,88 +0,0 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
|
||||
// Maximize error reporting
|
||||
error_reporting(E_ALL | E_STRICT);
|
||||
|
||||
// TODO: if we could get rid of this and have composer figure things out it'd make it
|
||||
// a bit more sane
|
||||
require(dirname(__file__) . '/../lib/Raven/Autoloader.php');
|
||||
Raven_Autoloader::register();
|
||||
|
||||
function raven_cli_test($command, $args)
|
||||
{
|
||||
// Do something silly
|
||||
try {
|
||||
throw new Exception('This is a test exception sent from the Raven CLI.');
|
||||
} catch (Exception $ex) {
|
||||
return $ex;
|
||||
}
|
||||
}
|
||||
|
||||
function cmd_test($dsn)
|
||||
{
|
||||
if (empty($dsn)) {
|
||||
exit('ERROR: Missing DSN value');
|
||||
}
|
||||
|
||||
// Parse DSN as a test
|
||||
try {
|
||||
$parsed = Raven_Client::parseDSN($dsn);
|
||||
} catch (InvalidArgumentException $ex) {
|
||||
exit("ERROR: There was an error parsing your DSN:\n " . $ex->getMessage());
|
||||
}
|
||||
|
||||
$client = new Raven_Client($dsn, array(
|
||||
'trace' => true,
|
||||
'curl_method' => 'sync',
|
||||
));
|
||||
|
||||
$config = get_object_vars($client);
|
||||
$required_keys = array('servers', 'project', 'public_key', 'secret_key');
|
||||
|
||||
echo "Client configuration:\n";
|
||||
foreach ($required_keys as $key) {
|
||||
if (empty($config[$key])) {
|
||||
exit("ERROR: Missing configuration for $key");
|
||||
}
|
||||
if (is_array($config[$key])) {
|
||||
echo "-> $key: [".implode(", ", $config[$key])."]\n";
|
||||
} else {
|
||||
echo "-> $key: $config[$key]\n";
|
||||
}
|
||||
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
echo "Sending a test event:\n";
|
||||
|
||||
$ex = raven_cli_test("command name", array("foo" => "bar"));
|
||||
$event_id = $client->captureException($ex);
|
||||
|
||||
echo "-> event ID: $event_id\n";
|
||||
|
||||
$last_error = $client->getLastError();
|
||||
if (!empty($last_error)) {
|
||||
exit("ERROR: There was an error sending the test event:\n " . $last_error);
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
echo "Done!";
|
||||
}
|
||||
|
||||
|
||||
function main() {
|
||||
global $argv;
|
||||
|
||||
$cmd = $argv[1];
|
||||
|
||||
switch ($cmd) {
|
||||
case 'test':
|
||||
cmd_test(@$argv[2]);
|
||||
break;
|
||||
default:
|
||||
exit('Usage: raven test <dsn>');
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -1,35 +0,0 @@
|
||||
{
|
||||
"name": "raven/raven",
|
||||
"type": "library",
|
||||
"description": "A PHP client for Sentry (http://getsentry.com)",
|
||||
"keywords": ["log", "logging"],
|
||||
"homepage": "http://getsentry.com",
|
||||
"license": "BSD",
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Cramer",
|
||||
"email": "dcramer@gmail.com"
|
||||
}
|
||||
],
|
||||
"require-dev": {
|
||||
"fabpot/php-cs-fixer": "^1.8.0",
|
||||
"phpunit/phpunit": "^4.6.6"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.4",
|
||||
"ext-curl": "*"
|
||||
},
|
||||
"bin": [
|
||||
"bin/raven"
|
||||
],
|
||||
"autoload": {
|
||||
"psr-0" : {
|
||||
"Raven_" : "lib/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.12.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Autoloads Raven classes.
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
class Raven_Autoloader
|
||||
{
|
||||
/**
|
||||
* Registers Raven_Autoloader as an SPL autoloader.
|
||||
*/
|
||||
public static function register()
|
||||
{
|
||||
ini_set('unserialize_callback_func', 'spl_autoload_call');
|
||||
spl_autoload_register(array('Raven_Autoloader', 'autoload'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles autoloading of classes.
|
||||
*
|
||||
* @param string $class A class name.
|
||||
*/
|
||||
public static function autoload($class)
|
||||
{
|
||||
if (0 !== strpos($class, 'Raven')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) {
|
||||
require $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,915 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Raven PHP Client
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
|
||||
class Raven_Client
|
||||
{
|
||||
const VERSION = '0.12.1';
|
||||
const PROTOCOL = '6';
|
||||
|
||||
const DEBUG = 'debug';
|
||||
const INFO = 'info';
|
||||
const WARN = 'warning';
|
||||
const WARNING = 'warning';
|
||||
const ERROR = 'error';
|
||||
const FATAL = 'fatal';
|
||||
|
||||
const MESSAGE_LIMIT = 1024;
|
||||
|
||||
public $severity_map;
|
||||
public $extra_data;
|
||||
|
||||
public $store_errors_for_bulk_send = false;
|
||||
|
||||
public function __construct($options_or_dsn=null, $options=array())
|
||||
{
|
||||
if (is_null($options_or_dsn) && !empty($_SERVER['SENTRY_DSN'])) {
|
||||
// Read from environment
|
||||
$options_or_dsn = $_SERVER['SENTRY_DSN'];
|
||||
}
|
||||
if (!is_array($options_or_dsn)) {
|
||||
if (!empty($options_or_dsn)) {
|
||||
// Must be a valid DSN
|
||||
$options_or_dsn = self::parseDSN($options_or_dsn);
|
||||
} else {
|
||||
$options_or_dsn = array();
|
||||
}
|
||||
}
|
||||
$options = array_merge($options_or_dsn, $options);
|
||||
|
||||
$this->logger = Raven_Util::get($options, 'logger', 'php');
|
||||
$this->servers = Raven_Util::get($options, 'servers');
|
||||
$this->secret_key = Raven_Util::get($options, 'secret_key');
|
||||
$this->public_key = Raven_Util::get($options, 'public_key');
|
||||
$this->project = Raven_Util::get($options, 'project', 1);
|
||||
$this->auto_log_stacks = (bool) Raven_Util::get($options, 'auto_log_stacks', false);
|
||||
$this->name = Raven_Util::get($options, 'name', Raven_Compat::gethostname());
|
||||
$this->site = Raven_Util::get($options, 'site', $this->_server_variable('SERVER_NAME'));
|
||||
$this->tags = Raven_Util::get($options, 'tags', array());
|
||||
$this->release = Raven_util::get($options, 'release', null);
|
||||
$this->trace = (bool) Raven_Util::get($options, 'trace', true);
|
||||
$this->timeout = Raven_Util::get($options, 'timeout', 2);
|
||||
$this->message_limit = Raven_Util::get($options, 'message_limit', self::MESSAGE_LIMIT);
|
||||
$this->exclude = Raven_Util::get($options, 'exclude', array());
|
||||
$this->severity_map = null;
|
||||
$this->shift_vars = (bool) Raven_Util::get($options, 'shift_vars', true);
|
||||
$this->http_proxy = Raven_Util::get($options, 'http_proxy');
|
||||
$this->extra_data = Raven_Util::get($options, 'extra', array());
|
||||
$this->send_callback = Raven_Util::get($options, 'send_callback', null);
|
||||
$this->curl_method = Raven_Util::get($options, 'curl_method', 'sync');
|
||||
$this->curl_path = Raven_Util::get($options, 'curl_path', 'curl');
|
||||
$this->curl_ipv4 = Raven_util::get($options, 'curl_ipv4', true);
|
||||
$this->ca_cert = Raven_util::get($options, 'ca_cert', $this->get_default_ca_cert());
|
||||
$this->verify_ssl = Raven_util::get($options, 'verify_ssl', true);
|
||||
$this->curl_ssl_version = Raven_Util::get($options, 'curl_ssl_version');
|
||||
|
||||
$this->processors = $this->setProcessorsFromOptions($options);
|
||||
|
||||
$this->_lasterror = null;
|
||||
$this->_user = null;
|
||||
$this->context = new Raven_Context();
|
||||
|
||||
if ($this->curl_method == 'async') {
|
||||
$this->_curl_handler = new Raven_CurlHandler($this->get_curl_options());
|
||||
}
|
||||
}
|
||||
|
||||
public static function getDefaultProcessors()
|
||||
{
|
||||
return array(
|
||||
'Raven_SanitizeDataProcessor',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Raven_Processor sub-classes to be used when data is processed before being
|
||||
* sent to Sentry.
|
||||
*
|
||||
* @param $options
|
||||
* @return array
|
||||
*/
|
||||
public function setProcessorsFromOptions($options)
|
||||
{
|
||||
$processors = array();
|
||||
foreach (Raven_util::get($options, 'processors', self::getDefaultProcessors()) as $processor) {
|
||||
$new_processor = new $processor($this);
|
||||
|
||||
if (isset($options['processorOptions']) && is_array($options['processorOptions'])) {
|
||||
if (isset($options['processorOptions'][$processor]) && method_exists($processor, 'setProcessorOptions')) {
|
||||
$new_processor->setProcessorOptions($options['processorOptions'][$processor]);
|
||||
}
|
||||
}
|
||||
$processors[] = $new_processor;
|
||||
}
|
||||
return $processors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a Raven-compatible DSN and returns an array of its values.
|
||||
*
|
||||
* @param string $dsn Raven compatible DSN: http://raven.readthedocs.org/en/latest/config/#the-sentry-dsn
|
||||
* @return array parsed DSN
|
||||
*/
|
||||
public static function parseDSN($dsn)
|
||||
{
|
||||
$url = parse_url($dsn);
|
||||
$scheme = (isset($url['scheme']) ? $url['scheme'] : '');
|
||||
if (!in_array($scheme, array('http', 'https'))) {
|
||||
throw new InvalidArgumentException('Unsupported Sentry DSN scheme: ' . (!empty($scheme) ? $scheme : '<not set>'));
|
||||
}
|
||||
$netloc = (isset($url['host']) ? $url['host'] : null);
|
||||
$netloc.= (isset($url['port']) ? ':'.$url['port'] : null);
|
||||
$rawpath = (isset($url['path']) ? $url['path'] : null);
|
||||
if ($rawpath) {
|
||||
$pos = strrpos($rawpath, '/', 1);
|
||||
if ($pos !== false) {
|
||||
$path = substr($rawpath, 0, $pos);
|
||||
$project = substr($rawpath, $pos + 1);
|
||||
} else {
|
||||
$path = '';
|
||||
$project = substr($rawpath, 1);
|
||||
}
|
||||
} else {
|
||||
$project = null;
|
||||
$path = '';
|
||||
}
|
||||
$username = (isset($url['user']) ? $url['user'] : null);
|
||||
$password = (isset($url['pass']) ? $url['pass'] : null);
|
||||
if (empty($netloc) || empty($project) || empty($username) || empty($password)) {
|
||||
throw new InvalidArgumentException('Invalid Sentry DSN: ' . $dsn);
|
||||
}
|
||||
|
||||
return array(
|
||||
'servers' => array(sprintf('%s://%s%s/api/%s/store/', $scheme, $netloc, $path, $project)),
|
||||
'project' => $project,
|
||||
'public_key' => $username,
|
||||
'secret_key' => $password,
|
||||
);
|
||||
}
|
||||
|
||||
public function getLastError()
|
||||
{
|
||||
return $this->_lasterror;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an identifier, returns a Sentry searchable string.
|
||||
*/
|
||||
public function getIdent($ident)
|
||||
{
|
||||
// XXX: We don't calculate checksums yet, so we only have the ident.
|
||||
return $ident;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated
|
||||
*/
|
||||
public function message($message, $params=array(), $level=self::INFO,
|
||||
$stack=false, $vars = null)
|
||||
{
|
||||
return $this->captureMessage($message, $params, $level, $stack, $vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated
|
||||
*/
|
||||
public function exception($exception)
|
||||
{
|
||||
return $this->captureException($exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message to sentry
|
||||
*/
|
||||
public function captureMessage($message, $params=array(), $level_or_options=array(),
|
||||
$stack=false, $vars = null)
|
||||
{
|
||||
// Gracefully handle messages which contain formatting characters, but were not
|
||||
// intended to be used with formatting.
|
||||
if (!empty($params)) {
|
||||
$formatted_message = vsprintf($message, $params);
|
||||
} else {
|
||||
$formatted_message = $message;
|
||||
}
|
||||
|
||||
if ($level_or_options === null) {
|
||||
$data = array();
|
||||
} elseif (!is_array($level_or_options)) {
|
||||
$data = array(
|
||||
'level' => $level_or_options,
|
||||
);
|
||||
} else {
|
||||
$data = $level_or_options;
|
||||
}
|
||||
|
||||
$data['message'] = $formatted_message;
|
||||
$data['sentry.interfaces.Message'] = array(
|
||||
'message' => $message,
|
||||
'params' => $params,
|
||||
);
|
||||
|
||||
return $this->capture($data, $stack, $vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an exception to sentry
|
||||
*/
|
||||
public function captureException($exception, $culprit_or_options=null, $logger=null, $vars=null)
|
||||
{
|
||||
$has_chained_exceptions = version_compare(PHP_VERSION, '5.3.0', '>=');
|
||||
|
||||
if (in_array(get_class($exception), $this->exclude)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!is_array($culprit_or_options)) {
|
||||
$data = array();
|
||||
if ($culprit_or_options !== null) {
|
||||
$data['culprit'] = $culprit_or_options;
|
||||
}
|
||||
} else {
|
||||
$data = $culprit_or_options;
|
||||
}
|
||||
|
||||
// TODO(dcramer): DRY this up
|
||||
$message = $exception->getMessage();
|
||||
if (empty($message)) {
|
||||
$message = get_class($exception);
|
||||
}
|
||||
|
||||
$exc = $exception;
|
||||
do {
|
||||
$exc_data = array(
|
||||
'value' => $exc->getMessage(),
|
||||
'type' => get_class($exc),
|
||||
'module' => $exc->getFile() .':'. $exc->getLine(),
|
||||
);
|
||||
|
||||
/**'sentry.interfaces.Exception'
|
||||
* Exception::getTrace doesn't store the point at where the exception
|
||||
* was thrown, so we have to stuff it in ourselves. Ugh.
|
||||
*/
|
||||
$trace = $exc->getTrace();
|
||||
$frame_where_exception_thrown = array(
|
||||
'file' => $exc->getFile(),
|
||||
'line' => $exc->getLine(),
|
||||
);
|
||||
|
||||
array_unshift($trace, $frame_where_exception_thrown);
|
||||
|
||||
// manually trigger autoloading, as it's not done in some edge cases due to PHP bugs (see #60149)
|
||||
if (!class_exists('Raven_Stacktrace')) {
|
||||
spl_autoload_call('Raven_Stacktrace');
|
||||
}
|
||||
|
||||
$exc_data['stacktrace'] = array(
|
||||
'frames' => Raven_Stacktrace::get_stack_info(
|
||||
$trace, $this->trace, $this->shift_vars, $vars, $this->message_limit
|
||||
),
|
||||
);
|
||||
|
||||
$exceptions[] = $exc_data;
|
||||
} while ($has_chained_exceptions && $exc = $exc->getPrevious());
|
||||
|
||||
$data['message'] = $message;
|
||||
$data['sentry.interfaces.Exception'] = array(
|
||||
'values' => array_reverse($exceptions),
|
||||
);
|
||||
if ($logger !== null) {
|
||||
$data['logger'] = $logger;
|
||||
}
|
||||
|
||||
if (empty($data['level'])) {
|
||||
if (method_exists($exception, 'getSeverity')) {
|
||||
$data['level'] = $this->translateSeverity($exception->getSeverity());
|
||||
} else {
|
||||
$data['level'] = self::ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->capture($data, $trace, $vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an query to sentry
|
||||
*/
|
||||
public function captureQuery($query, $level=self::INFO, $engine = '')
|
||||
{
|
||||
$data = array(
|
||||
'message' => $query,
|
||||
'level' => $level,
|
||||
'sentry.interfaces.Query' => array(
|
||||
'query' => $query
|
||||
)
|
||||
);
|
||||
|
||||
if ($engine !== '') {
|
||||
$data['sentry.interfaces.Query']['engine'] = $engine;
|
||||
}
|
||||
return $this->capture($data, false);
|
||||
}
|
||||
|
||||
protected function is_http_request()
|
||||
{
|
||||
return isset($_SERVER['REQUEST_METHOD']) && PHP_SAPI !== 'cli';
|
||||
}
|
||||
|
||||
protected function get_http_data()
|
||||
{
|
||||
$env = $headers = array();
|
||||
|
||||
foreach ($_SERVER as $key => $value) {
|
||||
if (0 === strpos($key, 'HTTP_')) {
|
||||
if (in_array($key, array('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'))) {
|
||||
continue;
|
||||
}
|
||||
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($key, 5)))))] = $value;
|
||||
} elseif (in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH'))) {
|
||||
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key))))] = $value;
|
||||
} else {
|
||||
$env[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$result = array(
|
||||
'method' => $this->_server_variable('REQUEST_METHOD'),
|
||||
'url' => $this->get_current_url(),
|
||||
'query_string' => $this->_server_variable('QUERY_STRING'),
|
||||
);
|
||||
|
||||
// dont set this as an empty array as PHP will treat it as a numeric array
|
||||
// instead of a mapping which goes against the defined Sentry spec
|
||||
if (!empty($_POST)) {
|
||||
$result['data'] = $_POST;
|
||||
}
|
||||
if (!empty($_COOKIE)) {
|
||||
$result['cookies'] = $_COOKIE;
|
||||
}
|
||||
if (!empty($headers)) {
|
||||
$result['headers'] = $headers;
|
||||
}
|
||||
if (!empty($env)) {
|
||||
$result['env'] = $env;
|
||||
}
|
||||
|
||||
return array(
|
||||
'sentry.interfaces.Http' => $result,
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_user_data()
|
||||
{
|
||||
$user = $this->context->user;
|
||||
if ($user === null) {
|
||||
if (!session_id()) {
|
||||
return array();
|
||||
}
|
||||
$user = array(
|
||||
'id' => session_id(),
|
||||
);
|
||||
if (!empty($_SESSION)) {
|
||||
$user['data'] = $_SESSION;
|
||||
}
|
||||
}
|
||||
return array(
|
||||
'sentry.interfaces.User' => $user,
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_extra_data()
|
||||
{
|
||||
return $this->extra_data;
|
||||
}
|
||||
|
||||
public function get_default_data()
|
||||
{
|
||||
return array(
|
||||
'server_name' => $this->name,
|
||||
'project' => $this->project,
|
||||
'site' => $this->site,
|
||||
'logger' => $this->logger,
|
||||
'tags' => $this->tags,
|
||||
'platform' => 'php',
|
||||
);
|
||||
}
|
||||
|
||||
public function capture($data, $stack, $vars = null)
|
||||
{
|
||||
if (!isset($data['timestamp'])) {
|
||||
$data['timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
|
||||
}
|
||||
if (!isset($data['level'])) {
|
||||
$data['level'] = self::ERROR;
|
||||
}
|
||||
if (!isset($data['tags'])) {
|
||||
$data['tags'] = array();
|
||||
}
|
||||
if (!isset($data['extra'])) {
|
||||
$data['extra'] = array();
|
||||
}
|
||||
if (!isset($data['event_id'])) {
|
||||
$data['event_id'] = $this->uuid4();
|
||||
}
|
||||
|
||||
if (isset($data['message'])) {
|
||||
$data['message'] = substr($data['message'], 0, $this->message_limit);
|
||||
}
|
||||
|
||||
$data = array_merge($this->get_default_data(), $data);
|
||||
|
||||
if ($this->is_http_request()) {
|
||||
$data = array_merge($this->get_http_data(), $data);
|
||||
}
|
||||
|
||||
$data = array_merge($this->get_user_data(), $data);
|
||||
|
||||
if ($this->release) {
|
||||
$data['release'] = $this->release;
|
||||
}
|
||||
|
||||
$data['tags'] = array_merge(
|
||||
$this->tags,
|
||||
$this->context->tags,
|
||||
$data['tags']);
|
||||
|
||||
$data['extra'] = array_merge(
|
||||
$this->get_extra_data(),
|
||||
$this->context->extra,
|
||||
$data['extra']);
|
||||
|
||||
// avoid empty arrays (which dont convert to dicts)
|
||||
if (empty($data['extra']))
|
||||
unset($data['extra']);
|
||||
if (empty($data['tags']))
|
||||
unset($data['tags']);
|
||||
|
||||
if ((!$stack && $this->auto_log_stacks) || $stack === true) {
|
||||
$stack = debug_backtrace();
|
||||
|
||||
// Drop last stack
|
||||
array_shift($stack);
|
||||
}
|
||||
|
||||
if (!empty($stack)) {
|
||||
// manually trigger autoloading, as it's not done in some edge cases due to PHP bugs (see #60149)
|
||||
if (!class_exists('Raven_Stacktrace')) {
|
||||
spl_autoload_call('Raven_Stacktrace');
|
||||
}
|
||||
|
||||
if (!isset($data['sentry.interfaces.Stacktrace'])) {
|
||||
$data['sentry.interfaces.Stacktrace'] = array(
|
||||
'frames' => Raven_Stacktrace::get_stack_info(
|
||||
$stack, $this->trace, $this->shift_vars, $vars, $this->message_limit
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->sanitize($data);
|
||||
$this->process($data);
|
||||
|
||||
if (!$this->store_errors_for_bulk_send) {
|
||||
$this->send($data);
|
||||
} else {
|
||||
if (empty($this->error_data)) {
|
||||
$this->error_data = array();
|
||||
}
|
||||
$this->error_data[] = $data;
|
||||
}
|
||||
|
||||
return $data['event_id'];
|
||||
}
|
||||
|
||||
public function sanitize(&$data)
|
||||
{
|
||||
// manually trigger autoloading, as it's not done in some edge cases due to PHP bugs (see #60149)
|
||||
if (!class_exists('Raven_Serializer')) {
|
||||
spl_autoload_call('Raven_Serializer');
|
||||
}
|
||||
|
||||
$data = Raven_Serializer::serialize($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process data through all defined Raven_Processor sub-classes
|
||||
*
|
||||
* @param array $data Associative array of data to log
|
||||
*/
|
||||
public function process(&$data)
|
||||
{
|
||||
foreach ($this->processors as $processor) {
|
||||
$processor->process($data);
|
||||
}
|
||||
}
|
||||
|
||||
public function sendUnsentErrors()
|
||||
{
|
||||
if (!empty($this->error_data)) {
|
||||
foreach ($this->error_data as $data) {
|
||||
$this->send($data);
|
||||
}
|
||||
unset($this->error_data);
|
||||
}
|
||||
if ($this->store_errors_for_bulk_send) {
|
||||
//in case an error occurs after this is called, on shutdown, send any new errors.
|
||||
$this->store_errors_for_bulk_send = !defined('RAVEN_CLIENT_END_REACHED');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to handle encoding and sending data to all defined Sentry servers
|
||||
*
|
||||
* @param array $data Associative array of data to log
|
||||
*/
|
||||
public function send($data)
|
||||
{
|
||||
if (is_callable($this->send_callback) && !call_user_func($this->send_callback, $data)) {
|
||||
// if send_callback returns falsely, end native send
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->servers) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = Raven_Compat::json_encode($data);
|
||||
|
||||
if (function_exists("gzcompress")) {
|
||||
$message = gzcompress($message);
|
||||
}
|
||||
$message = base64_encode($message); // PHP's builtin curl_* function are happy without this, but the exec method requires it
|
||||
|
||||
foreach ($this->servers as $url) {
|
||||
$client_string = 'raven-php/' . self::VERSION;
|
||||
$timestamp = microtime(true);
|
||||
$headers = array(
|
||||
'User-Agent' => $client_string,
|
||||
'X-Sentry-Auth' => $this->get_auth_header(
|
||||
$timestamp, $client_string, $this->public_key,
|
||||
$this->secret_key),
|
||||
'Content-Type' => 'application/octet-stream'
|
||||
);
|
||||
|
||||
$this->send_remote($url, $message, $headers);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to Sentry
|
||||
*
|
||||
* @param string $url Full URL to Sentry
|
||||
* @param array $data Associative array of data to log
|
||||
* @param array $headers Associative array of headers
|
||||
*/
|
||||
private function send_remote($url, $data, $headers=array())
|
||||
{
|
||||
$parts = parse_url($url);
|
||||
$parts['netloc'] = $parts['host'].(isset($parts['port']) ? ':'.$parts['port'] : null);
|
||||
$this->send_http($url, $data, $headers);
|
||||
}
|
||||
|
||||
protected function get_default_ca_cert()
|
||||
{
|
||||
return dirname(__FILE__) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'cacert.pem';
|
||||
}
|
||||
|
||||
protected function get_curl_options()
|
||||
{
|
||||
$options = array(
|
||||
CURLOPT_VERBOSE => false,
|
||||
CURLOPT_SSL_VERIFYHOST => 2,
|
||||
CURLOPT_SSL_VERIFYPEER => $this->verify_ssl,
|
||||
CURLOPT_CAINFO => $this->ca_cert,
|
||||
CURLOPT_USERAGENT => 'raven-php/' . self::VERSION,
|
||||
);
|
||||
if ($this->http_proxy) {
|
||||
$options[CURLOPT_PROXY] = $this->http_proxy;
|
||||
}
|
||||
if ($this->curl_ssl_version) {
|
||||
$options[CURLOPT_SSLVERSION] = $this->curl_ssl_version;
|
||||
}
|
||||
if ($this->curl_ipv4) {
|
||||
$options[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
|
||||
}
|
||||
if (defined('CURLOPT_TIMEOUT_MS')) {
|
||||
// MS is available in curl >= 7.16.2
|
||||
$timeout = max(1, ceil(1000 * $this->timeout));
|
||||
|
||||
// some versions of PHP 5.3 don't have this defined correctly
|
||||
if (!defined('CURLOPT_CONNECTTIMEOUT_MS')) {
|
||||
//see http://stackoverflow.com/questions/9062798/php-curl-timeout-is-not-working/9063006#9063006
|
||||
define('CURLOPT_CONNECTTIMEOUT_MS', 156);
|
||||
}
|
||||
|
||||
$options[CURLOPT_CONNECTTIMEOUT_MS] = $timeout;
|
||||
$options[CURLOPT_TIMEOUT_MS] = $timeout;
|
||||
} else {
|
||||
// fall back to the lower-precision timeout.
|
||||
$timeout = max(1, ceil($this->timeout));
|
||||
$options[CURLOPT_CONNECTTIMEOUT] = $timeout;
|
||||
$options[CURLOPT_TIMEOUT] = $timeout;
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the message over http to the sentry url given
|
||||
*
|
||||
* @param string $url URL of the Sentry instance to log to
|
||||
* @param array $data Associative array of data to log
|
||||
* @param array $headers Associative array of headers
|
||||
*/
|
||||
private function send_http($url, $data, $headers=array())
|
||||
{
|
||||
if ($this->curl_method == 'async') {
|
||||
$this->_curl_handler->enqueue($url, $data, $headers);
|
||||
} elseif ($this->curl_method == 'exec') {
|
||||
$this->send_http_asynchronous_curl_exec($url, $data, $headers);
|
||||
} else {
|
||||
$this->send_http_synchronous($url, $data, $headers);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the cURL to Sentry asynchronously. No errors will be returned from cURL
|
||||
*
|
||||
* @param string $url URL of the Sentry instance to log to
|
||||
* @param array $data Associative array of data to log
|
||||
* @param array $headers Associative array of headers
|
||||
* @return bool
|
||||
*/
|
||||
private function send_http_asynchronous_curl_exec($url, $data, $headers)
|
||||
{
|
||||
// TODO(dcramer): support ca_cert
|
||||
$cmd = $this->curl_path.' -X POST ';
|
||||
foreach ($headers as $key => $value) {
|
||||
$cmd .= '-H \''. $key. ': '. $value. '\' ';
|
||||
}
|
||||
$cmd .= '-d \''. $data .'\' ';
|
||||
$cmd .= '\''. $url .'\' ';
|
||||
$cmd .= '-m 5 '; // 5 second timeout for the whole process (connect + send)
|
||||
$cmd .= '> /dev/null 2>&1 &'; // ensure exec returns immediately while curl runs in the background
|
||||
|
||||
exec($cmd);
|
||||
|
||||
return true; // The exec method is just fire and forget, so just assume it always works
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a blocking cURL to Sentry and check for errors from cURL
|
||||
*
|
||||
* @param string $url URL of the Sentry instance to log to
|
||||
* @param array $data Associative array of data to log
|
||||
* @param array $headers Associative array of headers
|
||||
* @return bool
|
||||
*/
|
||||
private function send_http_synchronous($url, $data, $headers)
|
||||
{
|
||||
$new_headers = array();
|
||||
foreach ($headers as $key => $value) {
|
||||
array_push($new_headers, $key .': '. $value);
|
||||
}
|
||||
// XXX(dcramer): Prevent 100-continue response form server (Fixes GH-216)
|
||||
$new_headers[] = 'Expect:';
|
||||
|
||||
$curl = curl_init($url);
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $new_headers);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$options = $this->get_curl_options();
|
||||
$ca_cert = $options[CURLOPT_CAINFO];
|
||||
unset($options[CURLOPT_CAINFO]);
|
||||
curl_setopt_array($curl, $options);
|
||||
|
||||
curl_exec($curl);
|
||||
|
||||
$errno = curl_errno($curl);
|
||||
// CURLE_SSL_CACERT || CURLE_SSL_CACERT_BADFILE
|
||||
if ($errno == 60 || $errno == 77) {
|
||||
curl_setopt($curl, CURLOPT_CAINFO, $ca_cert);
|
||||
curl_exec($curl);
|
||||
}
|
||||
|
||||
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
$success = ($code == 200);
|
||||
if (!$success) {
|
||||
// It'd be nice just to raise an exception here, but it's not very PHP-like
|
||||
$this->_lasterror = curl_error($curl);
|
||||
} else {
|
||||
$this->_lasterror = null;
|
||||
}
|
||||
curl_close($curl);
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a Sentry authorization header string
|
||||
*
|
||||
* @param string $timestamp Timestamp when the event occurred
|
||||
* @param string $client HTTP client name (not Raven_Client object)
|
||||
* @param string $api_key Sentry API key
|
||||
* @param string $secret_key Sentry API key
|
||||
* @return string
|
||||
*/
|
||||
protected function get_auth_header($timestamp, $client, $api_key, $secret_key)
|
||||
{
|
||||
$header = array(
|
||||
sprintf('sentry_timestamp=%F', $timestamp),
|
||||
"sentry_client={$client}",
|
||||
sprintf('sentry_version=%s', self::PROTOCOL),
|
||||
);
|
||||
|
||||
if ($api_key) {
|
||||
$header[] = "sentry_key={$api_key}";
|
||||
}
|
||||
|
||||
if ($secret_key) {
|
||||
$header[] = "sentry_secret={$secret_key}";
|
||||
}
|
||||
|
||||
|
||||
return sprintf('Sentry %s', implode(', ', $header));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an uuid4 value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function uuid4()
|
||||
{
|
||||
$uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||
// 32 bits for "time_low"
|
||||
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
|
||||
|
||||
// 16 bits for "time_mid"
|
||||
mt_rand(0, 0xffff),
|
||||
|
||||
// 16 bits for "time_hi_and_version",
|
||||
// four most significant bits holds version number 4
|
||||
mt_rand(0, 0x0fff) | 0x4000,
|
||||
|
||||
// 16 bits, 8 bits for "clk_seq_hi_res",
|
||||
// 8 bits for "clk_seq_low",
|
||||
// two most significant bits holds zero and one for variant DCE1.1
|
||||
mt_rand(0, 0x3fff) | 0x8000,
|
||||
|
||||
// 48 bits for "node"
|
||||
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
|
||||
);
|
||||
|
||||
return str_replace('-', '', $uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URL for the current request
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function get_current_url()
|
||||
{
|
||||
// When running from commandline the REQUEST_URI is missing.
|
||||
if (!isset($_SERVER['REQUEST_URI'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$schema = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'
|
||||
|| $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
|
||||
|
||||
// HTTP_HOST is a client-supplied header that is optional in HTTP 1.0
|
||||
$host = (!empty($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
|
||||
: (!empty($_SERVER['LOCAL_ADDR']) ? $_SERVER['LOCAL_ADDR']
|
||||
: (!empty($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '')));
|
||||
|
||||
return $schema . $host . $_SERVER['REQUEST_URI'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a key from $_SERVER
|
||||
*
|
||||
* @param string $key Key whose value you wish to obtain
|
||||
* @return string Key's value
|
||||
*/
|
||||
private function _server_variable($key)
|
||||
{
|
||||
if (isset($_SERVER[$key])) {
|
||||
return $_SERVER[$key];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a PHP Error constant into a Sentry log level group
|
||||
*
|
||||
* @param string $severity PHP E_$x error constant
|
||||
* @return string Sentry log level group
|
||||
*/
|
||||
public function translateSeverity($severity)
|
||||
{
|
||||
if (is_array($this->severity_map) && isset($this->severity_map[$severity])) {
|
||||
return $this->severity_map[$severity];
|
||||
}
|
||||
switch ($severity) {
|
||||
case E_ERROR: return Raven_Client::ERROR;
|
||||
case E_WARNING: return Raven_Client::WARN;
|
||||
case E_PARSE: return Raven_Client::ERROR;
|
||||
case E_NOTICE: return Raven_Client::INFO;
|
||||
case E_CORE_ERROR: return Raven_Client::ERROR;
|
||||
case E_CORE_WARNING: return Raven_Client::WARN;
|
||||
case E_COMPILE_ERROR: return Raven_Client::ERROR;
|
||||
case E_COMPILE_WARNING: return Raven_Client::WARN;
|
||||
case E_USER_ERROR: return Raven_Client::ERROR;
|
||||
case E_USER_WARNING: return Raven_Client::WARN;
|
||||
case E_USER_NOTICE: return Raven_Client::INFO;
|
||||
case E_STRICT: return Raven_Client::INFO;
|
||||
case E_RECOVERABLE_ERROR: return Raven_Client::ERROR;
|
||||
}
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
|
||||
switch ($severity) {
|
||||
case E_DEPRECATED: return Raven_Client::WARN;
|
||||
case E_USER_DEPRECATED: return Raven_Client::WARN;
|
||||
}
|
||||
}
|
||||
return Raven_Client::ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a map of PHP Error constants to Sentry logging groups to use instead
|
||||
* of the defaults in translateSeverity()
|
||||
*
|
||||
* @param array $map
|
||||
*/
|
||||
public function registerSeverityMap($map)
|
||||
{
|
||||
$this->severity_map = $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function for setting a user's ID and Email
|
||||
*
|
||||
* @param string $id User's ID
|
||||
* @param string|null $email User's email
|
||||
* @param array $data Additional user data
|
||||
*/
|
||||
public function set_user_data($id, $email=null, $data=array())
|
||||
{
|
||||
$this->user_context(array_merge(array(
|
||||
'id' => $id,
|
||||
'email' => $email,
|
||||
), $data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets user context.
|
||||
*
|
||||
* @param array $data Associative array of user data
|
||||
*/
|
||||
public function user_context($data)
|
||||
{
|
||||
$this->context->user = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends tags context.
|
||||
*
|
||||
* @param array $data Associative array of tags
|
||||
*/
|
||||
public function tags_context($data)
|
||||
{
|
||||
$this->context->tags = array_merge($this->context->tags, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends additional context.
|
||||
*
|
||||
* @param array $data Associative array of extra data
|
||||
*/
|
||||
public function extra_context($data)
|
||||
{
|
||||
$this->context->extra = array_merge($this->context->extra, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $processors
|
||||
*/
|
||||
public function setProcessors(array $processors)
|
||||
{
|
||||
$this->processors = $processors;
|
||||
}
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Raven_Compat
|
||||
{
|
||||
|
||||
public static function gethostname()
|
||||
{
|
||||
if (function_exists('gethostname')) {
|
||||
return gethostname();
|
||||
}
|
||||
|
||||
return self::_gethostname();
|
||||
}
|
||||
|
||||
public static function _gethostname()
|
||||
{
|
||||
return php_uname('n');
|
||||
}
|
||||
|
||||
public static function hash_hmac($algo, $data, $key, $raw_output=false)
|
||||
{
|
||||
if (function_exists('hash_hmac')) {
|
||||
return hash_hmac($algo, $data, $key, $raw_output);
|
||||
}
|
||||
|
||||
return self::_hash_hmac($algo, $data, $key, $raw_output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation from 'KC Cloyd'.
|
||||
* See http://nl2.php.net/manual/en/function.hash-hmac.php
|
||||
*/
|
||||
public static function _hash_hmac($algo, $data, $key, $raw_output=false)
|
||||
{
|
||||
$algo = strtolower($algo);
|
||||
$pack = 'H'.strlen($algo('test'));
|
||||
$size = 64;
|
||||
$opad = str_repeat(chr(0x5C), $size);
|
||||
$ipad = str_repeat(chr(0x36), $size);
|
||||
|
||||
if (strlen($key) > $size) {
|
||||
$key = str_pad(pack($pack, $algo($key)), $size, chr(0x00));
|
||||
} else {
|
||||
$key = str_pad($key, $size, chr(0x00));
|
||||
}
|
||||
|
||||
$keyLastPos = strlen($key) - 1;
|
||||
for ($i = 0; $i < $keyLastPos; $i++) {
|
||||
$opad[$i] = $opad[$i] ^ $key[$i];
|
||||
$ipad[$i] = $ipad[$i] ^ $key[$i];
|
||||
}
|
||||
|
||||
$output = $algo($opad.pack($pack, $algo($ipad.$data)));
|
||||
|
||||
return ($raw_output) ? pack($pack, $output) : $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that we discard the options given to be compatible
|
||||
* with PHP < 5.3
|
||||
*/
|
||||
public static function json_encode($value, $options=0)
|
||||
{
|
||||
if (function_exists('json_encode')) {
|
||||
return json_encode($value);
|
||||
}
|
||||
|
||||
return self::_json_encode($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation taken from
|
||||
* http://www.mike-griffiths.co.uk/php-json_encode-alternative/
|
||||
*/
|
||||
public static function _json_encode($value)
|
||||
{
|
||||
static $jsonReplaces = array(
|
||||
array('\\', '/', "\n", "\t", "\r", "\b", "\f", '"'),
|
||||
array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
|
||||
|
||||
if (is_null($value)) {
|
||||
return 'null';
|
||||
}
|
||||
if ($value === false) {
|
||||
return 'false';
|
||||
}
|
||||
if ($value === true) {
|
||||
return 'true';
|
||||
}
|
||||
|
||||
if (is_scalar($value)) {
|
||||
|
||||
// Always use '.' for floats.
|
||||
if (is_float($value)) {
|
||||
return floatval(str_replace(',', '.', strval($value)));
|
||||
}
|
||||
if (is_string($value)) {
|
||||
return sprintf('"%s"',
|
||||
str_replace($jsonReplaces[0], $jsonReplaces[1], $value));
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
$isList = true;
|
||||
for ($i = 0, reset($value); $i<count($value); $i++, next($value)) {
|
||||
if (key($value) !== $i) {
|
||||
$isList = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$result = array();
|
||||
if ($isList) {
|
||||
foreach ($value as $v) {
|
||||
$result[] = self::_json_encode($v);
|
||||
}
|
||||
|
||||
return '[' . join(',', $result) . ']';
|
||||
} else {
|
||||
foreach ($value as $k => $v) {
|
||||
$result[] = self::_json_encode($k) . ':' . self::_json_encode($v);
|
||||
}
|
||||
|
||||
return '{' . join(',', $result) . '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Storage for additional client context.
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
class Raven_Context
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up existing context.
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->tags = array();
|
||||
$this->extra = array();
|
||||
$this->user = null;
|
||||
}
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Asynchronous Curl connection manager.
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
|
||||
// TODO(dcramer): handle ca_cert
|
||||
class Raven_CurlHandler
|
||||
{
|
||||
private $join_timeout;
|
||||
private $multi_handle;
|
||||
private $options;
|
||||
private $requests;
|
||||
|
||||
public function __construct($options, $join_timeout=5)
|
||||
{
|
||||
$this->options = $options;
|
||||
$this->multi_handle = curl_multi_init();
|
||||
$this->requests = array();
|
||||
$this->join_timeout = 5;
|
||||
|
||||
register_shutdown_function(array($this, 'join'));
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->join();
|
||||
}
|
||||
|
||||
public function enqueue($url, $data=null, $headers=array())
|
||||
{
|
||||
$ch = curl_init();
|
||||
|
||||
$new_headers = array();
|
||||
foreach ($headers as $key => $value) {
|
||||
array_push($new_headers, $key .': '. $value);
|
||||
}
|
||||
// XXX(dcramer): Prevent 100-continue response form server (Fixes GH-216)
|
||||
$new_headers[] = 'Expect:';
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $new_headers);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
|
||||
curl_setopt_array($ch, $this->options);
|
||||
|
||||
if (isset($data)) {
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
|
||||
curl_multi_add_handle($this->multi_handle, $ch);
|
||||
|
||||
$fd = (int)$ch;
|
||||
$this->requests[$fd] = 1;
|
||||
|
||||
$this->select();
|
||||
|
||||
return $fd;
|
||||
}
|
||||
|
||||
public function join($timeout=null)
|
||||
{
|
||||
if (!isset($timeout)) {
|
||||
$timeout = $this->join_timeout;
|
||||
}
|
||||
$start = time();
|
||||
do {
|
||||
$this->select();
|
||||
if (count($this->requests) === 0) {
|
||||
break;
|
||||
}
|
||||
usleep(10000);
|
||||
} while ($timeout !== 0 && time() - $start > $timeout);
|
||||
}
|
||||
|
||||
// http://se2.php.net/manual/en/function.curl-multi-exec.php
|
||||
private function select()
|
||||
{
|
||||
do {
|
||||
$mrc = curl_multi_exec($this->multi_handle, $active);
|
||||
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
|
||||
|
||||
while ($active && $mrc == CURLM_OK) {
|
||||
if (curl_multi_select($this->multi_handle) !== -1) {
|
||||
do {
|
||||
$mrc = curl_multi_exec($this->multi_handle, $active);
|
||||
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while ($info = curl_multi_info_read($this->multi_handle)) {
|
||||
$ch = $info['handle'];
|
||||
$fd = (int)$ch;
|
||||
|
||||
curl_multi_remove_handle($this->multi_handle, $ch);
|
||||
|
||||
if (!isset($this->requests[$fd])) {
|
||||
return;
|
||||
}
|
||||
|
||||
unset($this->requests[$fd]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Event handlers for exceptions and errors
|
||||
*
|
||||
* $client = new Raven_Client('http://public:secret/example.com/1');
|
||||
* $error_handler = new Raven_ErrorHandler($client);
|
||||
* $error_handler->registerExceptionHandler();
|
||||
* $error_handler->registerErrorHandler();
|
||||
* $error_handler->registerShutdownFunction();
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
|
||||
class Raven_ErrorHandler
|
||||
{
|
||||
private $old_exception_handler;
|
||||
private $call_existing_exception_handler = false;
|
||||
private $old_error_handler;
|
||||
private $call_existing_error_handler = false;
|
||||
private $reservedMemory;
|
||||
private $send_errors_last = false;
|
||||
private $error_types = -1;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* Error types that can be processed by the handler
|
||||
*/
|
||||
private $validErrorTypes = array(
|
||||
E_ERROR,
|
||||
E_WARNING,
|
||||
E_PARSE,
|
||||
E_NOTICE,
|
||||
E_CORE_ERROR,
|
||||
E_CORE_WARNING,
|
||||
E_COMPILE_ERROR,
|
||||
E_COMPILE_WARNING,
|
||||
E_USER_ERROR,
|
||||
E_USER_WARNING,
|
||||
E_USER_NOTICE,
|
||||
E_STRICT,
|
||||
E_RECOVERABLE_ERROR,
|
||||
E_DEPRECATED,
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* Error types that are always processed by the handler
|
||||
*/
|
||||
private $defaultErrorTypes = array(
|
||||
E_ERROR,
|
||||
E_PARSE,
|
||||
E_CORE_ERROR,
|
||||
E_CORE_WARNING,
|
||||
E_COMPILE_ERROR,
|
||||
E_COMPILE_WARNING,
|
||||
E_STRICT,
|
||||
);
|
||||
|
||||
public function __construct($client, $send_errors_last = false)
|
||||
{
|
||||
$this->client = $client;
|
||||
register_shutdown_function(array($this, 'detectShutdown'));
|
||||
if ($send_errors_last) {
|
||||
$this->send_errors_last = true;
|
||||
$this->client->store_errors_for_bulk_send = true;
|
||||
register_shutdown_function(array($this->client, 'sendUnsentErrors'));
|
||||
}
|
||||
}
|
||||
|
||||
public function handleException($e, $isError = false, $vars = null)
|
||||
{
|
||||
$e->event_id = $this->client->getIdent($this->client->captureException($e, null, null, $vars));
|
||||
|
||||
if (!$isError && $this->call_existing_exception_handler && $this->old_exception_handler) {
|
||||
call_user_func($this->old_exception_handler, $e);
|
||||
}
|
||||
}
|
||||
|
||||
public function handleError($code, $message, $file = '', $line = 0, $context=array())
|
||||
{
|
||||
if ($this->error_types & $code & error_reporting()) {
|
||||
$e = new ErrorException($message, 0, $code, $file, $line);
|
||||
$this->handleException($e, true, $context);
|
||||
}
|
||||
|
||||
if ($this->call_existing_error_handler) {
|
||||
if ($this->old_error_handler) {
|
||||
return call_user_func($this->old_error_handler, $code, $message, $file, $line, $context);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Nothing by default, use it in child classes for catching other types of errors
|
||||
* Only constants from $this->validErrorTypes can be used
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getAdditionalErrorTypesToProcess()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getErrorTypesToProcess()
|
||||
{
|
||||
$additionalErrorTypes = array_intersect($this->getAdditionalErrorTypesToProcess(), $this->validErrorTypes);
|
||||
// array_unique so bitwise "or" operation wouldn't fail if some error type gets repeated
|
||||
return array_unique($this->defaultErrorTypes + $additionalErrorTypes);
|
||||
}
|
||||
|
||||
public function handleFatalError()
|
||||
{
|
||||
if (null === $lastError = error_get_last()) {
|
||||
return;
|
||||
}
|
||||
|
||||
unset($this->reservedMemory);
|
||||
|
||||
$errors = 0;
|
||||
foreach ($this->getErrorTypesToProcess() as $errorType) {
|
||||
$errors |= $errorType;
|
||||
}
|
||||
|
||||
if ($lastError['type'] & $errors) {
|
||||
$e = new ErrorException(
|
||||
@$lastError['message'], @$lastError['type'], @$lastError['type'],
|
||||
@$lastError['file'], @$lastError['line']
|
||||
);
|
||||
$this->handleException($e, true);
|
||||
}
|
||||
}
|
||||
|
||||
public function registerExceptionHandler($call_existing_exception_handler = true)
|
||||
{
|
||||
$this->old_exception_handler = set_exception_handler(array($this, 'handleException'));
|
||||
$this->call_existing_exception_handler = $call_existing_exception_handler;
|
||||
}
|
||||
|
||||
public function registerErrorHandler($call_existing_error_handler = true, $error_types = -1)
|
||||
{
|
||||
$this->error_types = $error_types;
|
||||
$this->old_error_handler = set_error_handler(array($this, 'handleError'), error_reporting());
|
||||
$this->call_existing_error_handler = $call_existing_error_handler;
|
||||
}
|
||||
|
||||
public function registerShutdownFunction($reservedMemorySize = 10)
|
||||
{
|
||||
register_shutdown_function(array($this, 'handleFatalError'));
|
||||
|
||||
$this->reservedMemory = str_repeat('x', 1024 * $reservedMemorySize);
|
||||
}
|
||||
|
||||
public function detectShutdown()
|
||||
{
|
||||
if (!defined('RAVEN_CLIENT_END_REACHED')) {
|
||||
define('RAVEN_CLIENT_END_REACHED', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Base class for data processing.
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
abstract class Raven_Processor
|
||||
{
|
||||
public function __construct(Raven_Client $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process and sanitize data, modifying the existing value if necessary.
|
||||
*
|
||||
* @param array $data Array of log data
|
||||
*/
|
||||
abstract public function process(&$data);
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Asterisk out passwords from password fields in frames, http,
|
||||
* and basic extra data.
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
class Raven_SanitizeDataProcessor extends Raven_Processor
|
||||
{
|
||||
const MASK = '********';
|
||||
const FIELDS_RE = '/(authorization|password|passwd|secret|password_confirmation|card_number|auth_pw)/i';
|
||||
const VALUES_RE = '/^(?:\d[ -]*?){13,16}$/';
|
||||
|
||||
private $client;
|
||||
private $fields_re;
|
||||
private $values_re;
|
||||
|
||||
public function __construct(Raven_Client $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
$this->fields_re = self::FIELDS_RE;
|
||||
$this->values_re = self::VALUES_RE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default processor options
|
||||
*
|
||||
* @param array $options Associative array of processor options
|
||||
*/
|
||||
public function setProcessorOptions(array $options)
|
||||
{
|
||||
if (isset($options['fields_re'])) {
|
||||
$this->fields_re = $options['fields_re'];
|
||||
}
|
||||
|
||||
if (isset($options['values_re'])) {
|
||||
$this->values_re = $options['values_re'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any array values with our mask if the field name or the value matches a respective regex
|
||||
*
|
||||
* @param mixed $item Associative array value
|
||||
* @param string $key Associative array key
|
||||
*/
|
||||
public function sanitize(&$item, $key)
|
||||
{
|
||||
if (empty($item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (preg_match($this->values_re, $item)) {
|
||||
$item = self::MASK;
|
||||
}
|
||||
|
||||
if (empty($key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (preg_match($this->fields_re, $key)) {
|
||||
$item = self::MASK;
|
||||
}
|
||||
}
|
||||
|
||||
public function process(&$data)
|
||||
{
|
||||
array_walk_recursive($data, array($this, 'sanitize'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFieldsRe()
|
||||
{
|
||||
return $this->fields_re;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fields_re
|
||||
*/
|
||||
public function setFieldsRe($fields_re)
|
||||
{
|
||||
$this->fields_re = $fields_re;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getValuesRe()
|
||||
{
|
||||
return $this->values_re;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $values_re
|
||||
*/
|
||||
public function setValuesRe($values_re)
|
||||
{
|
||||
$this->values_re = $values_re;
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This helper is based on code from Facebook's Phabricator project
|
||||
*
|
||||
* https://github.com/facebook/phabricator
|
||||
*
|
||||
* Specifically, it is an adaptation of the PhutilReadableSerializer class.
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
class Raven_Serializer
|
||||
{
|
||||
/**
|
||||
* Serialize an object (recursively) into something safe for data
|
||||
* sanitization and encoding.
|
||||
*/
|
||||
public static function serialize($value, $max_depth=9, $_depth=0)
|
||||
{
|
||||
if (is_object($value) || is_resource($value)) {
|
||||
return self::serializeValue($value);
|
||||
} elseif ($_depth < $max_depth && is_array($value)) {
|
||||
$new = array();
|
||||
foreach ($value as $k => $v) {
|
||||
$new[self::serializeValue($k)] = self::serialize($v, $max_depth, $_depth + 1);
|
||||
}
|
||||
|
||||
return $new;
|
||||
} else {
|
||||
return self::serializeValue($value);
|
||||
}
|
||||
}
|
||||
|
||||
public static function serializeValue($value)
|
||||
{
|
||||
if ($value === null) {
|
||||
return 'null';
|
||||
} elseif ($value === false) {
|
||||
return 'false';
|
||||
} elseif ($value === true) {
|
||||
return 'true';
|
||||
} elseif (is_float($value) && (int) $value == $value) {
|
||||
return $value.'.0';
|
||||
} elseif (is_object($value) || gettype($value) == 'object') {
|
||||
return 'Object '.get_class($value);
|
||||
} elseif (is_resource($value)) {
|
||||
return 'Resource '.get_resource_type($value);
|
||||
} elseif (is_array($value)) {
|
||||
return 'Array of length ' . count($value);
|
||||
} elseif (is_integer($value)) {
|
||||
return (integer) $value;
|
||||
} else {
|
||||
$value = (string) $value;
|
||||
|
||||
if (function_exists('mb_convert_encoding')) {
|
||||
$value = mb_convert_encoding($value, 'UTF-8', 'UTF-8');
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,252 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Small helper class to inspect the stacktrace
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
class Raven_Stacktrace
|
||||
{
|
||||
public static $statements = array(
|
||||
'include',
|
||||
'include_once',
|
||||
'require',
|
||||
'require_once',
|
||||
);
|
||||
|
||||
public static function get_stack_info($frames, $trace = false, $shiftvars = true, $errcontext = null,
|
||||
$frame_var_limit = Raven_Client::MESSAGE_LIMIT)
|
||||
{
|
||||
/**
|
||||
* PHP's way of storing backstacks seems bass-ackwards to me
|
||||
* 'function' is not the function you're in; it's any function being
|
||||
* called, so we have to shift 'function' down by 1. Ugh.
|
||||
*/
|
||||
$result = array();
|
||||
for ($i = 0; $i < count($frames); $i++) {
|
||||
$frame = $frames[$i];
|
||||
$nextframe = isset($frames[$i + 1]) ? $frames[$i + 1] : null;
|
||||
|
||||
if (!array_key_exists('file', $frame)) {
|
||||
// XXX: Disable capturing of anonymous functions until we can implement a better grouping mechanism.
|
||||
// In our examples these generally didn't help with debugging as the information was found elsewhere
|
||||
// within the exception or the stacktrace
|
||||
continue;
|
||||
// if (isset($frame['args'])) {
|
||||
// $args = is_string($frame['args']) ? $frame['args'] : @json_encode($frame['args']);
|
||||
// }
|
||||
// else {
|
||||
// $args = array();
|
||||
// }
|
||||
// if (!empty($nextframe['class'])) {
|
||||
// $context['line'] = sprintf('%s%s%s(%s)',
|
||||
// $nextframe['class'], $nextframe['type'], $nextframe['function'],
|
||||
// $args);
|
||||
// }
|
||||
// else {
|
||||
// $context['line'] = sprintf('%s(%s)', $nextframe['function'], $args);
|
||||
// }
|
||||
// $abs_path = '';
|
||||
// $context['prefix'] = '';
|
||||
// $context['suffix'] = '';
|
||||
// $context['filename'] = $filename = '[Anonymous function]';
|
||||
// $context['lineno'] = 0;
|
||||
} else {
|
||||
$context = self::read_source_file($frame['file'], $frame['line']);
|
||||
$abs_path = $frame['file'];
|
||||
$filename = basename($frame['file']);
|
||||
}
|
||||
|
||||
$module = $filename;
|
||||
if (isset($nextframe['class'])) {
|
||||
$module .= ':' . $nextframe['class'];
|
||||
}
|
||||
|
||||
if (empty($result) && isset($errcontext)) {
|
||||
// If we've been given an error context that can be used as the vars for the first frame.
|
||||
$vars = $errcontext;
|
||||
} else {
|
||||
if ($trace) {
|
||||
if ($shiftvars) {
|
||||
$vars = self::get_frame_context($nextframe, $frame_var_limit);
|
||||
} else {
|
||||
$vars = self::get_caller_frame_context($frame);
|
||||
}
|
||||
} else {
|
||||
$vars = array();
|
||||
}
|
||||
}
|
||||
|
||||
$frame = array(
|
||||
'abs_path' => $abs_path,
|
||||
'filename' => $context['filename'],
|
||||
'lineno' => (int) $context['lineno'],
|
||||
'module' => $module,
|
||||
'function' => $nextframe['function'],
|
||||
'pre_context' => $context['prefix'],
|
||||
'context_line' => $context['line'],
|
||||
'post_context' => $context['suffix'],
|
||||
);
|
||||
// dont set this as an empty array as PHP will treat it as a numeric array
|
||||
// instead of a mapping which goes against the defined Sentry spec
|
||||
if (!empty($vars)) {
|
||||
foreach ($vars as $key => $value) {
|
||||
if (is_string($value) || is_numeric($value)) {
|
||||
$vars[$key] = substr($value, 0, $frame_var_limit);
|
||||
}
|
||||
}
|
||||
$frame['vars'] = $vars;
|
||||
}
|
||||
|
||||
$result[] = $frame;
|
||||
}
|
||||
|
||||
return array_reverse($result);
|
||||
}
|
||||
|
||||
public static function get_caller_frame_context($frame)
|
||||
{
|
||||
if (!isset($frame['args'])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$i = 1;
|
||||
$args = array();
|
||||
foreach ($frame['args'] as $arg) {
|
||||
$args['param'.$i] = $arg;
|
||||
$i++;
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
|
||||
public static function get_frame_context($frame, $frame_arg_limit = Raven_Client::MESSAGE_LIMIT)
|
||||
{
|
||||
// The reflection API seems more appropriate if we associate it with the frame
|
||||
// where the function is actually called (since we're treating them as function context)
|
||||
if (!isset($frame['function'])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (!isset($frame['args'])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (strpos($frame['function'], '__lambda_func') !== false) {
|
||||
return array();
|
||||
}
|
||||
if (isset($frame['class']) && $frame['class'] == 'Closure') {
|
||||
return array();
|
||||
}
|
||||
if (strpos($frame['function'], '{closure}') !== false) {
|
||||
return array();
|
||||
}
|
||||
if (in_array($frame['function'], self::$statements)) {
|
||||
if (empty($frame['args'])) {
|
||||
// No arguments
|
||||
return array();
|
||||
} else {
|
||||
// Sanitize the file path
|
||||
return array($frame['args'][0]);
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (isset($frame['class'])) {
|
||||
if (method_exists($frame['class'], $frame['function'])) {
|
||||
$reflection = new ReflectionMethod($frame['class'], $frame['function']);
|
||||
} elseif ($frame['type'] === '::') {
|
||||
$reflection = new ReflectionMethod($frame['class'], '__callStatic');
|
||||
} else {
|
||||
$reflection = new ReflectionMethod($frame['class'], '__call');
|
||||
}
|
||||
} else {
|
||||
$reflection = new ReflectionFunction($frame['function']);
|
||||
}
|
||||
} catch (ReflectionException $e) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$params = $reflection->getParameters();
|
||||
|
||||
$args = array();
|
||||
foreach ($frame['args'] as $i => $arg) {
|
||||
if (isset($params[$i])) {
|
||||
// Assign the argument by the parameter name
|
||||
if (is_array($arg)) {
|
||||
foreach ($arg as $key => $value) {
|
||||
if (is_string($value) || is_numeric($value)) {
|
||||
$arg[$key] = substr($value, 0, $frame_arg_limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
$args[$params[$i]->name] = $arg;
|
||||
} else {
|
||||
// TODO: Sentry thinks of these as context locals, so they must be named
|
||||
// Assign the argument by number
|
||||
// $args[$i] = $arg;
|
||||
}
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
private static function read_source_file($filename, $lineno, $context_lines = 5)
|
||||
{
|
||||
$frame = array(
|
||||
'prefix' => array(),
|
||||
'line' => '',
|
||||
'suffix' => array(),
|
||||
'filename' => $filename,
|
||||
'lineno' => $lineno,
|
||||
);
|
||||
|
||||
if ($filename === null || $lineno === null) {
|
||||
return $frame;
|
||||
}
|
||||
|
||||
// Code which is eval'ed have a modified filename.. Extract the
|
||||
// correct filename + linenumber from the string.
|
||||
$matches = array();
|
||||
$matched = preg_match("/^(.*?)\((\d+)\) : eval\(\)'d code$/",
|
||||
$filename, $matches);
|
||||
if ($matched) {
|
||||
$frame['filename'] = $filename = $matches[1];
|
||||
$frame['lineno'] = $lineno = $matches[2];
|
||||
}
|
||||
|
||||
// In the case of an anonymous function, the filename is sent as:
|
||||
// "</path/to/filename>(<lineno>) : runtime-created function"
|
||||
// Extract the correct filename + linenumber from the string.
|
||||
$matches = array();
|
||||
$matched = preg_match("/^(.*?)\((\d+)\) : runtime-created function$/",
|
||||
$filename, $matches);
|
||||
if ($matched) {
|
||||
$frame['filename'] = $filename = $matches[1];
|
||||
$frame['lineno'] = $lineno = $matches[2];
|
||||
}
|
||||
|
||||
try {
|
||||
$file = new SplFileObject($filename);
|
||||
$target = max(0, ($lineno - ($context_lines + 1)));
|
||||
$file->seek($target);
|
||||
$cur_lineno = $target+1;
|
||||
while (!$file->eof()) {
|
||||
$line = rtrim($file->current(), "\r\n");
|
||||
if ($cur_lineno == $lineno) {
|
||||
$frame['line'] = $line;
|
||||
} elseif ($cur_lineno < $lineno) {
|
||||
$frame['prefix'][] = $line;
|
||||
} elseif ($cur_lineno > $lineno) {
|
||||
$frame['suffix'][] = $line;
|
||||
}
|
||||
$cur_lineno++;
|
||||
if ($cur_lineno > $lineno + $context_lines) {
|
||||
break;
|
||||
}
|
||||
$file->next();
|
||||
}
|
||||
} catch (RuntimeException $exc) {
|
||||
return $frame;
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
|
||||
class Raven_Util
|
||||
{
|
||||
/**
|
||||
* Because we love Python, this works much like dict.get() in Python.
|
||||
*
|
||||
* Returns $var from $array if set, otherwise returns $default.
|
||||
*/
|
||||
public static function get($array, $var, $default=null)
|
||||
{
|
||||
if (isset($array[$var])) {
|
||||
return $array[$var];
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="test/bootstrap.php"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Raven Test Suite">
|
||||
<directory>./test/Raven/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">./lib/Raven/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
@@ -1,635 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
// XXX: Is there a better way to stub the client?
|
||||
class Dummy_Raven_Client extends Raven_Client
|
||||
{
|
||||
private $__sent_events = array();
|
||||
|
||||
public function getSentEvents()
|
||||
{
|
||||
return $this->__sent_events;
|
||||
}
|
||||
public function send($data)
|
||||
{
|
||||
if (is_callable($this->send_callback) && !call_user_func($this->send_callback, $data)) {
|
||||
// if send_callback returns falsely, end native send
|
||||
return;
|
||||
}
|
||||
$this->__sent_events[] = $data;
|
||||
}
|
||||
public function is_http_request()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public function get_auth_header($timestamp, $client, $api_key, $secret_key)
|
||||
{
|
||||
return parent::get_auth_header($timestamp, $client, $api_key, $secret_key);
|
||||
}
|
||||
public function get_http_data()
|
||||
{
|
||||
return parent::get_http_data();
|
||||
}
|
||||
public function get_user_data()
|
||||
{
|
||||
return parent::get_user_data();
|
||||
}
|
||||
}
|
||||
|
||||
class Raven_Tests_ClientTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
private function create_exception()
|
||||
{
|
||||
try {
|
||||
throw new Exception('Foo bar');
|
||||
} catch (Exception $ex) {
|
||||
return $ex;
|
||||
}
|
||||
}
|
||||
|
||||
private function create_chained_exception()
|
||||
{
|
||||
try {
|
||||
throw new Exception('Foo bar');
|
||||
} catch (Exception $ex) {
|
||||
try {
|
||||
throw new Exception('Child exc', 0, $ex);
|
||||
} catch (Exception $ex2) {
|
||||
return $ex2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testParseDsnHttp()
|
||||
{
|
||||
$result = Raven_Client::parseDsn('http://public:secret@example.com/1');
|
||||
|
||||
$this->assertEquals($result['project'], 1);
|
||||
$this->assertEquals($result['servers'], array('http://example.com/api/1/store/'));
|
||||
$this->assertEquals($result['public_key'], 'public');
|
||||
$this->assertEquals($result['secret_key'], 'secret');
|
||||
}
|
||||
|
||||
public function testParseDsnHttps()
|
||||
{
|
||||
$result = Raven_Client::parseDsn('https://public:secret@example.com/1');
|
||||
|
||||
$this->assertEquals($result['project'], 1);
|
||||
$this->assertEquals($result['servers'], array('https://example.com/api/1/store/'));
|
||||
$this->assertEquals($result['public_key'], 'public');
|
||||
$this->assertEquals($result['secret_key'], 'secret');
|
||||
}
|
||||
|
||||
public function testParseDsnPath()
|
||||
{
|
||||
$result = Raven_Client::parseDsn('http://public:secret@example.com/app/1');
|
||||
|
||||
$this->assertEquals($result['project'], 1);
|
||||
$this->assertEquals($result['servers'], array('http://example.com/app/api/1/store/'));
|
||||
$this->assertEquals($result['public_key'], 'public');
|
||||
$this->assertEquals($result['secret_key'], 'secret');
|
||||
}
|
||||
|
||||
public function testParseDsnPort()
|
||||
{
|
||||
$result = Raven_Client::parseDsn('http://public:secret@example.com:9000/app/1');
|
||||
|
||||
$this->assertEquals($result['project'], 1);
|
||||
$this->assertEquals($result['servers'], array('http://example.com:9000/app/api/1/store/'));
|
||||
$this->assertEquals($result['public_key'], 'public');
|
||||
$this->assertEquals($result['secret_key'], 'secret');
|
||||
}
|
||||
|
||||
public function testParseDsnInvalidScheme()
|
||||
{
|
||||
try {
|
||||
Raven_Client::parseDsn('gopher://public:secret@/1');
|
||||
$this->fail();
|
||||
} catch (Exception $e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public function testParseDsnMissingNetloc()
|
||||
{
|
||||
try {
|
||||
Raven_Client::parseDsn('http://public:secret@/1');
|
||||
$this->fail();
|
||||
} catch (Exception $e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public function testParseDsnMissingProject()
|
||||
{
|
||||
try {
|
||||
Raven_Client::parseDsn('http://public:secret@example.com');
|
||||
$this->fail();
|
||||
} catch (Exception $e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testParseDsnMissingPublicKey()
|
||||
{
|
||||
Raven_Client::parseDsn('http://:secret@example.com/1');
|
||||
}
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testParseDsnMissingSecretKey()
|
||||
{
|
||||
Raven_Client::parseDsn('http://public@example.com/1');
|
||||
}
|
||||
|
||||
public function testDsnFirstArgument()
|
||||
{
|
||||
$client = new Raven_Client('http://public:secret@example.com/1');
|
||||
|
||||
$this->assertEquals($client->project, 1);
|
||||
$this->assertEquals($client->servers, array('http://example.com/api/1/store/'));
|
||||
$this->assertEquals($client->public_key, 'public');
|
||||
$this->assertEquals($client->secret_key, 'secret');
|
||||
}
|
||||
|
||||
public function testDsnFirstArgumentWithOptions()
|
||||
{
|
||||
$client = new Raven_Client('http://public:secret@example.com/1', array(
|
||||
'site' => 'foo',
|
||||
));
|
||||
|
||||
$this->assertEquals($client->project, 1);
|
||||
$this->assertEquals($client->servers, array('http://example.com/api/1/store/'));
|
||||
$this->assertEquals($client->public_key, 'public');
|
||||
$this->assertEquals($client->secret_key, 'secret');
|
||||
$this->assertEquals($client->site, 'foo');
|
||||
}
|
||||
|
||||
public function testOptionsFirstArgument()
|
||||
{
|
||||
$client = new Raven_Client(array(
|
||||
'servers' => array('http://example.com/api/1/store/'),
|
||||
'project' => 1,
|
||||
));
|
||||
|
||||
$this->assertEquals($client->servers, array('http://example.com/api/1/store/'));
|
||||
}
|
||||
|
||||
public function testOptionsFirstArgumentWithOptions()
|
||||
{
|
||||
$client = new Raven_Client(array(
|
||||
'servers' => array('http://example.com/api/1/store/'),
|
||||
'project' => 1,
|
||||
), array(
|
||||
'site' => 'foo',
|
||||
));
|
||||
|
||||
$this->assertEquals($client->servers, array('http://example.com/api/1/store/'));
|
||||
$this->assertEquals($client->site, 'foo');
|
||||
}
|
||||
|
||||
public function testOptionsExtraData()
|
||||
{
|
||||
$client = new Dummy_Raven_Client(array('extra' => array('foo' => 'bar')));
|
||||
|
||||
$client->captureMessage('Test Message %s', array('foo'));
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['extra']['foo'], 'bar');
|
||||
}
|
||||
|
||||
public function testEmptyExtraData()
|
||||
{
|
||||
$client = new Dummy_Raven_Client(array('extra' => array()));
|
||||
|
||||
$client->captureMessage('Test Message %s', array('foo'));
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals(array_key_exists('extra', $event), false);
|
||||
}
|
||||
|
||||
public function testCaptureMessageDoesHandleUninterpolatedMessage()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->captureMessage('Test Message %s');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['message'], 'Test Message %s');
|
||||
}
|
||||
|
||||
public function testCaptureMessageDoesHandleInterpolatedMessage()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->captureMessage('Test Message %s', array('foo'));
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['message'], 'Test Message foo');
|
||||
}
|
||||
|
||||
public function testCaptureMessageSetsInterface()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->captureMessage('Test Message %s', array('foo'));
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['sentry.interfaces.Message'], array(
|
||||
'message' => 'Test Message %s',
|
||||
'params' => array('foo'),
|
||||
));
|
||||
}
|
||||
|
||||
public function testCaptureMessageHandlesOptionsAsThirdArg()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->captureMessage('Test Message %s', array('foo'), array(
|
||||
'level' => Dummy_Raven_Client::WARNING,
|
||||
'extra' => array('foo' => 'bar')
|
||||
));
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['level'], Dummy_Raven_Client::WARNING);
|
||||
$this->assertEquals($event['extra']['foo'], 'bar');
|
||||
}
|
||||
|
||||
public function testCaptureMessageHandlesLevelAsThirdArg()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->captureMessage('Test Message %s', array('foo'), Dummy_Raven_Client::WARNING);
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['level'], Dummy_Raven_Client::WARNING);
|
||||
}
|
||||
|
||||
public function testCaptureExceptionSetsInterfaces()
|
||||
{
|
||||
# TODO: it'd be nice if we could mock the stacktrace extraction function here
|
||||
$client = new Dummy_Raven_Client();
|
||||
$ex = $this->create_exception();
|
||||
$client->captureException($ex);
|
||||
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
|
||||
$exc = $event['sentry.interfaces.Exception'];
|
||||
$this->assertEquals(count($exc['values']), 1);
|
||||
$this->assertEquals($exc['values'][0]['value'], 'Foo bar');
|
||||
$this->assertEquals($exc['values'][0]['type'], 'Exception');
|
||||
$this->assertFalse(empty($exc['values'][0]['module']));
|
||||
|
||||
$this->assertFalse(empty($exc['values'][0]['stacktrace']['frames']));
|
||||
$frames = $exc['values'][0]['stacktrace']['frames'];
|
||||
$frame = $frames[count($frames) - 1];
|
||||
$this->assertTrue($frame['lineno'] > 0);
|
||||
$this->assertEquals($frame['module'], 'ClientTest.php:Raven_Tests_ClientTest');
|
||||
$this->assertEquals($frame['function'], 'create_exception');
|
||||
$this->assertFalse(isset($frame['vars']));
|
||||
$this->assertEquals($frame['context_line'], ' throw new Exception(\'Foo bar\');');
|
||||
$this->assertFalse(empty($frame['pre_context']));
|
||||
$this->assertFalse(empty($frame['post_context']));
|
||||
}
|
||||
|
||||
public function testCaptureExceptionChainedException()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
$this->markTestSkipped('PHP 5.3 required for chained exceptions.');
|
||||
}
|
||||
|
||||
# TODO: it'd be nice if we could mock the stacktrace extraction function here
|
||||
$client = new Dummy_Raven_Client();
|
||||
$ex = $this->create_chained_exception();
|
||||
$client->captureException($ex);
|
||||
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
|
||||
$exc = $event['sentry.interfaces.Exception'];
|
||||
$this->assertEquals(count($exc['values']), 2);
|
||||
$this->assertEquals($exc['values'][0]['value'], 'Foo bar');
|
||||
$this->assertEquals($exc['values'][1]['value'], 'Child exc');
|
||||
}
|
||||
|
||||
public function testCaptureExceptionDifferentLevelsInChainedExceptionsBug()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
$this->markTestSkipped('PHP 5.3 required for chained exceptions.');
|
||||
}
|
||||
|
||||
$client = new Dummy_Raven_Client();
|
||||
$e1 = new ErrorException('First', 0, E_DEPRECATED);
|
||||
$e2 = new ErrorException('Second', 0, E_NOTICE, __FILE__, __LINE__, $e1);
|
||||
$e3 = new ErrorException('Third', 0, E_ERROR, __FILE__, __LINE__, $e2);
|
||||
|
||||
$client->captureException($e1);
|
||||
$client->captureException($e2);
|
||||
$client->captureException($e3);
|
||||
$events = $client->getSentEvents();
|
||||
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['level'], Dummy_Raven_Client::ERROR);
|
||||
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['level'], Dummy_Raven_Client::INFO);
|
||||
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['level'], Dummy_Raven_Client::WARNING);
|
||||
}
|
||||
|
||||
public function testCaptureExceptionHandlesOptionsAsSecondArg()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
$ex = $this->create_exception();
|
||||
$client->captureException($ex, array('culprit' => 'test'));
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['culprit'], 'test');
|
||||
}
|
||||
|
||||
public function testCaptureExceptionHandlesCulpritAsSecondArg()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
$ex = $this->create_exception();
|
||||
$client->captureException($ex, 'test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['culprit'], 'test');
|
||||
}
|
||||
|
||||
public function testCaptureExceptionHandlesExcludeOption()
|
||||
{
|
||||
$client = new Dummy_Raven_Client(array(
|
||||
'exclude' => array('Exception'),
|
||||
));
|
||||
$ex = $this->create_exception();
|
||||
$client->captureException($ex, 'test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 0);
|
||||
}
|
||||
|
||||
public function testDoesRegisterProcessors()
|
||||
{
|
||||
$client = new Dummy_Raven_Client(array(
|
||||
'processors' => array('Raven_SanitizeDataProcessor'),
|
||||
));
|
||||
$this->assertEquals(count($client->processors), 1);
|
||||
$this->assertTrue($client->processors[0] instanceof Raven_SanitizeDataProcessor);
|
||||
}
|
||||
|
||||
public function testProcessDoesCallProcessors()
|
||||
{
|
||||
$data = array("key"=>"value");
|
||||
|
||||
$processor = $this->getMock('Processor', array('process'));
|
||||
$processor->expects($this->once())
|
||||
->method('process')
|
||||
->with($data);
|
||||
|
||||
$client = new Dummy_Raven_Client();
|
||||
$client->processors[] = $processor;
|
||||
$client->process($data);
|
||||
}
|
||||
|
||||
public function testDefaultProcessorsAreUsed()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
$defaults = Dummy_Raven_Client::getDefaultProcessors();
|
||||
|
||||
$this->assertEquals(count($client->processors), count($defaults));
|
||||
}
|
||||
|
||||
public function testDefaultProcessorsContainSanitizeDataProcessor()
|
||||
{
|
||||
$defaults = Dummy_Raven_Client::getDefaultProcessors();
|
||||
|
||||
$this->assertTrue(in_array('Raven_SanitizeDataProcessor', $defaults));
|
||||
}
|
||||
|
||||
public function testGetDefaultData()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
$expected = array(
|
||||
'platform' => 'php',
|
||||
'project' => $client->project,
|
||||
'server_name' => $client->name,
|
||||
'site' => $client->site,
|
||||
'logger' => $client->logger,
|
||||
'tags' => $client->tags,
|
||||
);
|
||||
$this->assertEquals($expected, $client->get_default_data());
|
||||
}
|
||||
|
||||
/**
|
||||
* @backupGlobals
|
||||
*/
|
||||
public function testGetHttpData()
|
||||
{
|
||||
$_SERVER = array(
|
||||
'REDIRECT_STATUS' => '200',
|
||||
'CONTENT_TYPE' => 'text/xml',
|
||||
'CONTENT_LENGTH' => '99',
|
||||
'HTTP_HOST' => 'getsentry.com',
|
||||
'HTTP_ACCEPT' => 'text/html',
|
||||
'HTTP_ACCEPT_CHARSET' => 'utf-8',
|
||||
'HTTP_COOKIE' => 'cupcake: strawberry',
|
||||
'HTTP_CONTENT_TYPE' => 'text/html',
|
||||
'HTTP_CONTENT_LENGTH' => '1000',
|
||||
'SERVER_PORT' => '443',
|
||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||
'REQUEST_METHOD' => 'PATCH',
|
||||
'QUERY_STRING' => 'q=bitch&l=en',
|
||||
'REQUEST_URI' => '/welcome/',
|
||||
'SCRIPT_NAME' => '/index.php',
|
||||
);
|
||||
$_POST = array(
|
||||
'stamp' => '1c',
|
||||
);
|
||||
$_COOKIE = array(
|
||||
'donut' => 'chocolat',
|
||||
);
|
||||
|
||||
$expected = array(
|
||||
'sentry.interfaces.Http' => array(
|
||||
'method' => 'PATCH',
|
||||
'url' => 'https://getsentry.com/welcome/',
|
||||
'query_string' => 'q=bitch&l=en',
|
||||
'data' => array(
|
||||
'stamp' => '1c',
|
||||
),
|
||||
'cookies' => array(
|
||||
'donut' => 'chocolat',
|
||||
),
|
||||
'headers' => array(
|
||||
'Host' => 'getsentry.com',
|
||||
'Accept' => 'text/html',
|
||||
'Accept-Charset' => 'utf-8',
|
||||
'Cookie' => 'cupcake: strawberry',
|
||||
'Content-Type' => 'text/xml',
|
||||
'Content-Length' => '99',
|
||||
),
|
||||
'env' => array(
|
||||
'REDIRECT_STATUS' => '200',
|
||||
'SERVER_PORT' => '443',
|
||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||
'REQUEST_METHOD' => 'PATCH',
|
||||
'QUERY_STRING' => 'q=bitch&l=en',
|
||||
'REQUEST_URI' => '/welcome/',
|
||||
'SCRIPT_NAME' => '/index.php',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$client = new Dummy_Raven_Client();
|
||||
$this->assertEquals($expected, $client->get_http_data());
|
||||
}
|
||||
|
||||
public function testGetUserDataWithSetUser()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$id = 'unique_id';
|
||||
$email = 'foo@example.com';
|
||||
|
||||
$user = array(
|
||||
'username' => 'my_user',
|
||||
);
|
||||
|
||||
$client->set_user_data($id, $email, $user);
|
||||
|
||||
$expected = array(
|
||||
'sentry.interfaces.User' => array(
|
||||
'id' => 'unique_id',
|
||||
'username' => 'my_user',
|
||||
'email' => 'foo@example.com',
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $client->get_user_data());
|
||||
}
|
||||
|
||||
public function testGetUserDataWithNoUser()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$expected = array(
|
||||
'sentry.interfaces.User' => array(
|
||||
'id' => session_id(),
|
||||
)
|
||||
);
|
||||
$this->assertEquals($expected, $client->get_user_data());
|
||||
}
|
||||
|
||||
public function testGetAuthHeader()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$clientstring = 'raven-php/test';
|
||||
$timestamp = '1234341324.340000';
|
||||
|
||||
$expected = "Sentry sentry_timestamp={$timestamp}, sentry_client={$clientstring}, " .
|
||||
"sentry_version=" . Dummy_Raven_Client::PROTOCOL . ", " .
|
||||
"sentry_key=publickey, sentry_secret=secretkey";
|
||||
|
||||
$this->assertEquals($expected, $client->get_auth_header($timestamp, 'raven-php/test', 'publickey', 'secretkey'));
|
||||
}
|
||||
|
||||
public function testCaptureMessageWithUserContext()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->user_context(array('email' => 'foo@example.com'));
|
||||
|
||||
$client->captureMessage('test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(1, count($events));
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals(array(
|
||||
'email' => 'foo@example.com',
|
||||
), $event['sentry.interfaces.User']);
|
||||
}
|
||||
|
||||
public function testCaptureMessageWithTagsContext()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->tags_context(array('foo' => 'bar'));
|
||||
$client->tags_context(array('biz' => 'boz'));
|
||||
$client->tags_context(array('biz' => 'baz'));
|
||||
|
||||
$client->captureMessage('test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(1, count($events));
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals(array(
|
||||
'foo' => 'bar',
|
||||
'biz' => 'baz',
|
||||
), $event['tags']);
|
||||
}
|
||||
|
||||
public function testCaptureMessageWithExtraContext()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->extra_context(array('foo' => 'bar'));
|
||||
$client->extra_context(array('biz' => 'boz'));
|
||||
$client->extra_context(array('biz' => 'baz'));
|
||||
|
||||
$client->captureMessage('test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(1, count($events));
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals(array(
|
||||
'foo' => 'bar',
|
||||
'biz' => 'baz',
|
||||
), $event['extra']);
|
||||
}
|
||||
|
||||
public function cb1($data)
|
||||
{
|
||||
$this->assertEquals('test', $data['message']);
|
||||
return false;
|
||||
}
|
||||
|
||||
public function cb2($data)
|
||||
{
|
||||
$this->assertEquals('test', $data['message']);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function testSendCallback()
|
||||
{
|
||||
$client = new Dummy_Raven_Client(array('send_callback' => array($this, 'cb1')));
|
||||
$client->captureMessage('test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(0, count($events));
|
||||
|
||||
$client = new Dummy_Raven_Client(array('send_callback' => array($this, 'cb2')));
|
||||
$client->captureMessage('test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(1, count($events));
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Raven_Tests_CompatTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function test_gethostname()
|
||||
{
|
||||
$this->assertEquals(Raven_Compat::gethostname(), Raven_Compat::_gethostname());
|
||||
$this->assertTrue(strlen(Raven_Compat::_gethostname()) > 0);
|
||||
}
|
||||
|
||||
public function test_hash_hmac()
|
||||
{
|
||||
$result = Raven_Compat::hash_hmac('sha1', 'foo', 'bar');
|
||||
$this->assertEquals('85d155c55ed286a300bd1cf124de08d87e914f3a', $result);
|
||||
|
||||
$result = Raven_Compat::_hash_hmac('sha1', 'foo', 'bar');
|
||||
$this->assertEquals('85d155c55ed286a300bd1cf124de08d87e914f3a', $result);
|
||||
}
|
||||
|
||||
public function test_json_encode()
|
||||
{
|
||||
$result = Raven_Compat::json_encode(array('foo' => array('bar' => 1)));
|
||||
$this->assertEquals('{"foo":{"bar":1}}', $result);
|
||||
|
||||
$result = Raven_Compat::_json_encode(array('foo' => array('bar' => 1)));
|
||||
$this->assertEquals('{"foo":{"bar":1}}', $result);
|
||||
|
||||
$result = Raven_Compat::_json_encode(array(1, 2, 3, 4, 'foo', 'bar'));
|
||||
$this->assertEquals('[1,2,3,4,"foo","bar"]', $result);
|
||||
|
||||
$result = Raven_Compat::_json_encode(array(1, 'foo', 'foobar' => 'bar'));
|
||||
$this->assertEquals('{0:1,1:"foo","foobar":"bar"}', $result);
|
||||
|
||||
$result = Raven_Compat::_json_encode(array(array()));
|
||||
$this->assertEquals('[[]]', $result);
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Raven_Tests_ErrorHandlerTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $errorLevel;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->errorLevel = error_reporting();
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
error_reporting($this->errorLevel);
|
||||
}
|
||||
|
||||
public function testErrorsAreLoggedAsExceptions()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent'));
|
||||
$client->expects($this->once())
|
||||
->method('captureException')
|
||||
->with($this->isInstanceOf('ErrorException'));
|
||||
|
||||
$handler = new Raven_ErrorHandler($client);
|
||||
$handler->handleError(E_WARNING, 'message');
|
||||
}
|
||||
|
||||
public function testExceptionsAreLogged()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent'));
|
||||
$client->expects($this->once())
|
||||
->method('captureException')
|
||||
->with($this->isInstanceOf('ErrorException'));
|
||||
|
||||
$e = new ErrorException('message', 0, E_WARNING, '', 0);
|
||||
|
||||
$handler = new Raven_ErrorHandler($client);
|
||||
$handler->handleException($e);
|
||||
}
|
||||
|
||||
public function testErrorHandlerCheckSilentReporting()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent'));
|
||||
$client->expects($this->never())
|
||||
->method('captureException');
|
||||
|
||||
$handler = new Raven_ErrorHandler($client);
|
||||
$handler->registerErrorHandler(false);
|
||||
|
||||
@trigger_error('Silent', E_USER_WARNING);
|
||||
}
|
||||
|
||||
public function testErrorHandlerBlockErrorReporting()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent'));
|
||||
$client->expects($this->never())
|
||||
->method('captureException');
|
||||
|
||||
$handler = new Raven_ErrorHandler($client);
|
||||
$handler->registerErrorHandler(false);
|
||||
|
||||
error_reporting(E_USER_ERROR);
|
||||
trigger_error('Warning', E_USER_WARNING);
|
||||
}
|
||||
|
||||
public function testErrorHandlerPassErrorReportingPass()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent'));
|
||||
$client->expects($this->once())
|
||||
->method('captureException');
|
||||
|
||||
$handler = new Raven_ErrorHandler($client);
|
||||
$handler->registerErrorHandler(false);
|
||||
|
||||
error_reporting(E_USER_WARNING);
|
||||
trigger_error('Warning', E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user