diff --git a/README.md b/README.md index 2bc7c00..9951685 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ There are some default arguments that you can override. At the very least, you s log_url: '/log?type=log', // The url to which standard logs are sent log_level: 1, // The level at which to log. This allows you to keep the calls to the logging in your code and just change this variable to log varying degrees. 1 = only error, 2 = error & log, 3 = error, log & info native_error:true, // Whether or not to send native js errors as well (using window.onerror). - use_console:false, // Whether to show a console.error/info/log as well (when a console is present) + hijack_console:true, // Hijacks the default console functionality (ie: all your console.error/info/log are belong to us). query_var: 'msg', // The variable to send the log message through as. client_info: { // Configuration for what info about the client's browser is logged. location:true, // The url to the page on which the error occurred. @@ -44,7 +44,10 @@ The log will be sent to the backend as a normal `POST` request, which might look $.post('/log?type=error&msg=YOUR_ERROR_MESSAGE'); -`native_error` is set to `true` by default. This means that all browser errors will also be captured and passed to the backend. +#### Notes + +* `native_error` is set to `true` by default. This means that all browser errors will also be captured and passed to the backend. +* `hijack_console` is set to `true` by default and will log to the server as well as display your normal console.error/info/log. If you wish to keep the functionality for $.error and console.error (for example) separate, set hijack_console to false. ### Backend @@ -60,4 +63,8 @@ Also included with the distribution is a PHP frontend for parsing and displaying ## Credit -jQuery.clientSideLogging was developed by [Remy Bach](https://github.com/remybach) (JavaScript) and [Rob Miller](https://github.com/robmiller) (PHP).p \ No newline at end of file +jQuery.clientSideLogging was developed by [Remy Bach](https://github.com/remybach) (JavaScript) and [Rob Miller](https://github.com/robmiller) (PHP). + +## License + +MIT License - [http://remybach.mit-license.org/](http://remybach.mit-license.org/) diff --git a/clientSideLogging.jquery.json b/clientSideLogging.jquery.json new file mode 100644 index 0000000..cd819ad --- /dev/null +++ b/clientSideLogging.jquery.json @@ -0,0 +1,30 @@ +{ + "name": "clientSideLogging", + "version": "1.1.2", + "title": "jQuery Client Side Logging", + "author": { + "name": "Rémy Bach", + "url": "http://remy.bach.me.uk" + }, + "licenses": [{ + "type": "MIT", + "url": "http://remybach.mit-license.org/" + }], + "dependencies": { + "jquery": ">=1.5" + }, + "description": "This plugin allows you to store front end log/info/error messages on the server (note: you will need to have something set up on your server to handle the actual logging).", + "keywords": [ + "errors", + "logging", + "debug", + "debugging" + ], + "homepage": "https://github.com/remybach/jQuery.clientSideLogging", + "docs": "https://github.com/remybach/jQuery.clientSideLogging", + "bugs": "https://github.com/remybach/jQuery.clientSideLogging/issues", + "maintainers": [{ + "name":"Rob Miller", + "url":"https://github.com/robmiller" + }] +} \ No newline at end of file diff --git a/jQuery.clientSideLogging.js b/jQuery.clientSideLogging.js index 3213ca9..7218baa 100644 --- a/jQuery.clientSideLogging.js +++ b/jQuery.clientSideLogging.js @@ -1,156 +1,200 @@ -/* - * Title: jQuery Client Side Logging Plugin - * Author: Rémy Bach - * Version: 1.0.0 - * License: http://remybach.mit-license.org - * Url: http://github.com/remybach/jQuery.clientSideLogging - * Description: - * This plugin allows you to store front end log/info/error messages on the server (note: you will need to have something set up on your server to handle the actual logging). - * The idea was born after reading the following article: http://openmymind.net/2012/4/4/You-Really-Should-Log-Client-Side-Error/ - */ -(function($) { - var defaults = { - error_url: '/log?type=error', - info_url: '/log?type=info', - log_url: '/log?type=log', - log_level: 1, - native_error:true, - use_console:false, - query_var: 'msg', - client_info: { - location:true, - screen_size:true, - user_agent:true, - window_size:true - } - }; - - /** - * Initializing with custom options. Not strictly necessary, but recommended. - * @param options The custom options. - */ - $.clientSideLogging = function(options) { - $.extend(defaults, options || {}); - }; - - /** - * The function that will send error logs to the server. Also logs to the console using console.error() (if available and requested by the user) - * @param what What you want to be logged (String, or JSON object) - */ - $.error = function(what) { - if (defaults.log_level >= 1) { - _send(defaults.error_url, what); - } - - if(window.console&&window.console.error&&defaults.use_console)console.error(what); - }; - - /** - * The function that will send info logs to the server. Also logs to the console using console.info() (if available and requested by the user) - * @param what What you want to be logged (String, or JSON object) - */ - $.info = function(what) { - if (defaults.log_level >= 3) { - _send(defaults.info_url, what); - } - - if(window.console&&window.console.info&&defaults.use_console)console.info(what); - }; - - /** - * The function that will send standard logs to the server. Also logs to the console using console.log() (if available and requested by the user) - * @param what What you want to be logged (String, or JSON object) - */ - $.log = function(what) { - if (defaults.log_level >= 2) { - _send(defaults.log_url, what); - } - - if(window.console&&window.console.log&&defaults.use_console)console.log(what); - }; - - // Log errors whenever there's a generic js error on the page. - window.onerror = function(message, file, line) { - if (defaults.native_error) { - _send(defaults.error_url, { - message: message, - file: file, - line: line - }); - } - }; - - /*===== Private Functions =====*/ - /** - * Send the log information to the server. - * @param url The url to submit the information to. - * @param what The information to be logged. - */ - _send = function(url, what) { - // If the url already has a ? in it. - if (url.match(/\?.+$/)) { - url += '&'; - } else { - url += '?'; - } - - format = 'text'; - if (typeof what === 'object') { - format = 'json'; - - // Let's grab the additional logging info before we send this off. - $.extend(what, _buildClientInfo()); - what = JSON.stringify(what); - } - - url += 'format=' + format + '&' + defaults.query_var + '=' + what; - $.post(url); - }; - - /** - * Build up an object containing the requested information about the client (as specified in defaults). - * @return _info The object containing the requested information. - */ - _buildClientInfo = function() { - var _info = {}; - - if (defaults.client_info.user_agent) { - _info.user_agent = navigator.userAgent; - } - if (defaults.client_info.window_size) { - _info.window_size = $(window).width()+' x '+$(window).height(); - } - if (defaults.client_info.screen_size) { - _info.screen_size = window.screen.availWidth+' x '+window.screen.availHeight; - } - if (defaults.client_info.location) { - _info.location = window.location.href; - } - - return _info; - }; - - /** - * Fallback for older browsers that don't implement JSON.stringify - * @param obj The JSON object to turn into a string. - * @return A string representation of the JSON object. - */ - JSON.stringify = JSON.stringify || function (obj) { - var t = typeof (obj); - if (t != "object" || obj === null) { - // simple data type - if (t == "string") obj = '"'+obj+'"'; - return String(obj); - } else { - // recurse array or object - var n, v, json = [], arr = (obj && obj.constructor == Array); - for (n in obj) { - v = obj[n]; t = typeof(v); - if (t == "string") v = '"'+v+'"'; - else if (t == "object" && v !== null) v = JSON.stringify(v); - json.push((arr ? "" : '"' + n + '":') + String(v)); - } - return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}"); - } - }; -})(jQuery); \ No newline at end of file +/* + * Title: jQuery Client Side Logging Plugin + * Author: Rémy Bach + * Version: 1.1.2 + * License: http://remybach.mit-license.org + * Url: http://github.com/remybach/jQuery.clientSideLogging + * Description: + * This plugin allows you to store front end log/info/error messages on the server (note: you will need to have something set up on your server to handle the actual logging). + * The idea was born after reading the following article: http://openmymind.net/2012/4/4/You-Really-Should-Log-Client-Side-Error/ + */ +(function($) { + /*===== Run polyfill for console first. =====*/ + // Make sure browsers that don't have console don't completely die. + if (!window.console) { + console = {}; + } + // Make console.* behave like proper Functions in IE. + if (window.console && typeof console.log == "object") { + $.each(["log","info","warn","error","assert","dir","clear","profile","profileEnd"], function(i, method) { + console[method] = $.proxy(console[method], console); + }); + } + /*===== End polyfill for console. =====*/ + + var defaults = { + error_url: '/log/?type=error', // The url to which errors logs are sent + info_url: '/log/?type=info', // The url to which info logs are sent + log_url: '/log/?type=log', // The url to which standard logs are sent + log_level: 1, // The level at which to log. This allows you to keep the calls to the logging in your code and just change this variable to log varying degrees. 1 = only error, 2 = error & log, 3 = error, log & info + native_error:true, // Whether or not to send native js errors as well (using window.onerror). + hijack_console:true, // Hijacks the default console functionality (ie: all your console.error/info/log are belong to us). + query_var: 'msg', // The variable to send the log message through as. + client_info: { // Configuration for what info about the client's browser is logged. + location:true, // The url to the page on which the error occurred. + screen_size:true, // The size of the user's screen (different to the window size because the window might not be maximized) + user_agent:true, // The user agent string. + window_size:true // The window size. + } + }, + original_error = console.error, + original_info = console.info, + original_log = console.log; + + /** + * Initializing with custom options. Not strictly necessary, but recommended. + * @param options The custom options. + */ + $.clientSideLogging = function(options) { + defaults = $.extend(defaults, options || {}); + + // We need to unset these again if they were set the first time. + if (!defaults.hijack_console) { + console.error = original_error; + console.info = original_info; + console.log = original_log; + } else { + console.error = $.error; + console.info = $.info; + console.log = $.log; + } + }; + + /** + * The function that will send error logs to the server. Also logs to the console using console.error() (if available and requested by the user) + * @param what What you want to be logged (String, or JSON object) + */ + $.error = function(what) { + if (defaults.log_level >= 1) { + _send(defaults.error_url, what); + } + + if (defaults.hijack_console && original_error && original_error.apply) { + original_error.apply(console, arguments); + } + }; + console.error = $.error; + + /** + * The function that will send info logs to the server. Also logs to the console using console.info() (if available and requested by the user) + * @param what What you want to be logged (String, or JSON object) + */ + $.info = function(what) { + if (defaults.log_level >= 3) { + _send(defaults.info_url, what); + } + + if (defaults.hijack_console && original_info && original_info.apply) { + original_info.apply(console, arguments); + } + }; + console.info = $.info; + + /** + * The function that will send standard logs to the server. Also logs to the console using console.log() (if available and requested by the user) + * @param what What you want to be logged (String, or JSON object) + */ + $.log = function(what) { + if (defaults.log_level >= 2) { + _send(defaults.log_url, what); + } + + if (defaults.hijack_console && original_log && original_log.apply) { + original_log.apply(console, arguments); + } + }; + console.log = $.log; + + // Log errors whenever there's a generic js error on the page. + window.onerror = function(message, file, line) { + if (defaults.native_error) { + _send(defaults.error_url, { + message: message, + file: file, + line: line + }); + } + }; + + /*===== Private Functions =====*/ + /** + * Send the log information to the server. + * @param url The url to submit the information to. + * @param what The information to be logged. + */ + _send = function(url, what) { + url += url.match(/\?.+$/) ? '&' : '?'; + + if (typeof what === 'object') { + // Let's grab the additional logging info before we send this off. + $.extend(what, _buildClientInfo()); + + _data = {}; + _data[defaults.query_var] = JSON.stringify(what); + + $.ajax({ + type:'POST', + url:url+'format=json', + data:_data + }); + } else { + if (what.indexOf(defaults.error_url) > 0) { + // Prevent trying to send error messages to non existing error_url + return; + } + $.post(url+'format=text&' + defaults.query_var + '=' + what); + } + }; + + /** + * Build up an object containing the requested information about the client (as specified in defaults). + * @return _info The object containing the requested information. + */ + _buildClientInfo = function() { + var _info = {}; + + if (defaults.client_info.user_agent) { + _info.user_agent = navigator.userAgent; + } + if (defaults.client_info.window_size) { + _info.window_size = $(window).width()+' x '+$(window).height(); + } + if (defaults.client_info.screen_size) { + _info.screen_size = window.screen.availWidth+' x '+window.screen.availHeight; + } + if (defaults.client_info.location) { + _info.location = window.location.href; + } + + return _info; + }; + + /*===== Compatibility Functions =====*/ + /** + * Fallback for older browsers that don't implement JSON.stringify + * @param obj The JSON object to turn into a string. + * @return A string representation of the JSON object. + */ + var JSON; + if (!JSON) { + JSON = {}; + } + JSON.stringify = JSON.stringify || function (obj) { + var t = typeof (obj); + if (t != "object" || obj === null) { + // simple data type + if (t == "string") obj = '"'+obj+'"'; + return String(obj); + } else { + // recurse array or object + var n, v, json = [], arr = (obj && obj.constructor == Array); + for (n in obj) { + v = obj[n]; t = typeof(v); + if (t == "string") v = '"'+v+'"'; + else if (t == "object" && v !== null) v = JSON.stringify(v); + json.push((arr ? "" : '"' + n + '":') + String(v)); + } + return (arr ? "[" : "{") + String(json) + (arr ? "]" : "}"); + } + }; +})(jQuery); diff --git a/test/css/bootstrap-responsive.css b/log/css/bootstrap-responsive.css similarity index 100% rename from test/css/bootstrap-responsive.css rename to log/css/bootstrap-responsive.css diff --git a/test/css/bootstrap-responsive.min.css b/log/css/bootstrap-responsive.min.css similarity index 100% rename from test/css/bootstrap-responsive.min.css rename to log/css/bootstrap-responsive.min.css diff --git a/test/css/bootstrap.css b/log/css/bootstrap.css similarity index 100% rename from test/css/bootstrap.css rename to log/css/bootstrap.css diff --git a/test/css/bootstrap.min.css b/log/css/bootstrap.min.css similarity index 100% rename from test/css/bootstrap.min.css rename to log/css/bootstrap.min.css diff --git a/log/css/style.css b/log/css/style.css new file mode 100644 index 0000000..6b40ec6 --- /dev/null +++ b/log/css/style.css @@ -0,0 +1,52 @@ +body { padding:10px; } + +.navbar .brand { padding-top:14px; } +.nav li.error:hover, .nav li.log:hover, .nav li.info:hover, +.nav li.error.active, .nav li.log.active, .nav li.info.active { + margin-bottom:0; +} +.nav li.error:hover, +.nav li.error.active { + border-bottom:5px solid #B94A48; +} +.nav li.log:hover, +.nav li.log.active { + border-bottom:5px solid #B9D5E2; +} +.nav li.info:hover, +.nav li.info.active { + border-bottom:5px solid #BED5BE; +} + +ul { list-style:none; margin-left:5px; } +li { margin:5px 0; } +.checkbox label { display:inline-block; } + +.log_info { height:150px; overflow:auto; } + +.table td.type { + overflow:hidden; + position:relative; + text-align:center; + width:30px; +} +.type:before { + content:''; + display:block; + height:100%; + left:0; + position:absolute; + top:0; + width:5px; +} +.type.error:before { + background:#B94A48; +} +.type.log:before { + background:#B9D5E2; +} +.type.info:before { + background:#BED5BE; +} + +.table th.span1 { text-align:center; } \ No newline at end of file diff --git a/log/css/test.css b/log/css/test.css new file mode 100644 index 0000000..07baee2 --- /dev/null +++ b/log/css/test.css @@ -0,0 +1,3 @@ +ul { list-style:none; margin-left:5px; } +li { margin:5px 0; } +.checkbox label { display:inline-block; } \ No newline at end of file diff --git a/test/img/glyphicons-halflings-white.png b/log/img/glyphicons-halflings-white.png similarity index 100% rename from test/img/glyphicons-halflings-white.png rename to log/img/glyphicons-halflings-white.png diff --git a/test/img/glyphicons-halflings.png b/log/img/glyphicons-halflings.png similarity index 100% rename from test/img/glyphicons-halflings.png rename to log/img/glyphicons-halflings.png diff --git a/test/log.php b/log/index.php similarity index 80% rename from test/log.php rename to log/index.php index 05021a8..3fa2697 100644 --- a/test/log.php +++ b/log/index.php @@ -25,8 +25,10 @@ function stripslashes_deep($value) { define('LOG_FILE', dirname(__FILE__) . '/log.txt'); define('ACCESS_FILE', dirname(__FILE__) . '/access.txt'); -// Only allow one entry per … seconds. -define('THROTTLE_TIME', 60); +// Only allow X entries per Y seconds. The default is to allow 15 entries +// every 2 minutes. +define('THROTTLE_COUNT', 15); +define('THROTTLE_TIME', 120); define('IP_ADDRESS', $_SERVER['REMOTE_ADDR']); @@ -48,9 +50,6 @@ function stripslashes_deep($value) { $format = $_REQUEST['format']; } -// Initially, assume that this client hasn't logged anything in the last minute. -$has_accessed = false; - if ( !file_exists(ACCESS_FILE) ) { if ( is_writable(dirname(ACCESS_FILE)) ) { touch(ACCESS_FILE); @@ -62,37 +61,45 @@ function stripslashes_deep($value) { $accesses = file(ACCESS_FILE); // Clear out old access logs. +$access_count = 0; $accesses = array_filter( $accesses, function($access) { - global $has_accessed; + global $access_count; + + if ( trim($access) == '' ) { + return false; + } list($date, $ip) = explode("\t", $access); $date = trim($date); $ip = trim($ip); - $fresh = ( strtotime($date) + THROTTLE_TIME > time() ); + // Keep entries for twice as long as the throttle time… + $to_keep = ( strtotime($date) + ( THROTTLE_TIME * 2 ) > time() ); + // …but only consider ones within the throttle time. + $to_consider = ( strtotime($date) + THROTTLE_TIME > time() ); // If the user has accessed within the last minute, proceed with the // filtering — but we won't be logging anything later. - if ( $fresh && $ip == IP_ADDRESS ) { - $has_accessed = true; + if ( $to_consider && $ip == IP_ADDRESS ) { + $access_count++; } - return $fresh; + return $to_keep; } ); // Log an access from this IP. -if ( !$has_accessed ) { +if ( $access_count < THROTTLE_COUNT ) { $accesses[] = date('Y-m-d H:i:s') . "\t" . IP_ADDRESS; } file_put_contents(ACCESS_FILE, join("\n", $accesses)); -// If the user has submitted a log in the last minute, bail out silently. -if ( $has_accessed ) { +// If the user has been throttled, bail out silently. +if ( $access_count >= THROTTLE_COUNT ) { die; } diff --git a/log/js/test.js b/log/js/test.js new file mode 100644 index 0000000..bc23732 --- /dev/null +++ b/log/js/test.js @@ -0,0 +1,63 @@ +jQuery(function($) { + $('.no-js').removeClass('no-js'); + $('iframe').height($(document).height()); + + var location = false; + var screen_size = false; + var user_agent = false; + var window_size = false; + + $('input:button').click(function(e) { + e.preventDefault(); + updateLogging(); + + if (!location && !screen_size && !user_agent && !window_size) { + if ($(this).hasClass('error')) { + $.error($(this).parents('li').find('input:text').val()); + } else if ($(this).hasClass('info')) { + $.info($(this).parents('li').find('input:text').val()); + } else if ($(this).hasClass('log')) { + $.log($(this).parents('li').find('input:text').val()); + } + } else { + if ($(this).hasClass('error')) { + $.error({msg:$(this).parents('li').find('input:text').val()}); + } else if ($(this).hasClass('info')) { + $.info({msg:$(this).parents('li').find('input:text').val()}); + } else if ($(this).hasClass('log')) { + $.log({msg:$(this).parents('li').find('input:text').val()}); + } + } + + // Give the ajax request a chance to log this before refreshing the iframe. + setTimeout(function() { + // Refresh the iframe. + $('iframe').attr('src', $('iframe').attr('src')); + }, 500); + }); + + $('input:checkbox').click(function(e) { + // toggle our variables + if (this.name == 'location') { + location = !location; + } else if (this.name == 'screen_size') { + screen_size = !screen_size; + } else if (this.name == 'user_agent') { + user_agent = !user_agent; + } else if (this.name == 'window_size') { + window_size = !window_size; + } + }); + + function updateLogging() { + $.clientSideLogging({ + log_level: 3, + client_info: { + location:location, + screen_size:screen_size, + user_agent:user_agent, + window_size:window_size + } + }); + } +}); \ No newline at end of file diff --git a/log/js/view_logs.js b/log/js/view_logs.js new file mode 100644 index 0000000..a27fc45 --- /dev/null +++ b/log/js/view_logs.js @@ -0,0 +1,13 @@ +jQuery(function($) { + $('.navbar input:text').keyup(function(e) { + var filter = new RegExp(this.value, 'gim'); + + $('tr').each(function(i, val) { + if ($(this).html().match(filter)) { + $(this).show(); + } else { + $(this).hide(); + } + }); + }); +}); \ No newline at end of file diff --git a/log/test.php b/log/test.php new file mode 100644 index 0000000..274239d --- /dev/null +++ b/log/test.php @@ -0,0 +1,77 @@ + + + + + + + + + + Client Side Logging Test + + + + + + + + + + + + +
+
+
+

Client Side Logging Test

+
+
+ +
+
+ +
+ + + + + + + + + + diff --git a/log/view_logs.php b/log/view_logs.php new file mode 100644 index 0000000..b12623e --- /dev/null +++ b/log/view_logs.php @@ -0,0 +1,191 @@ +incidence = get_object_vars($logs->incidence); + + function format_log($log) { + $log->decoded_message = $log->message; + if ( $log->format == 'json' ) { + $log->decoded_message = print_r(json_decode($log->message), 1); + $log->decoded_message = preg_replace('/stdClass Object\s*/', '', $log->decoded_message); + $log->decoded_message = htmlentities($log->decoded_message); + $log->decoded_message = '
' . $log->decoded_message . '
'; + } + } + + foreach ( (array) $logs->incidence as $log ) { + $log = format_log($log); + } + + foreach ( (array) $logs->log as $log ) { + $log = format_log($log); + } + + // Show log entries in reverse chronological order. + $logs->log = array_reverse($logs->log); + + // Sort incidence entries by count. + usort( + $logs->incidence, + function($a, $b) { + if ( $a->count == $b->count ) { + // If the counts are the same, sort by most recent. + if ( $a->first_logged == $b->first_logged ) { + return 0; + } + return ( $a->first_logged < $b->first_logged ) ? 1 : -1; + } + // We're sorting descending. + return ( $a->count < $b->count ) ? 1 : -1; + } + ); + + // If we've been given a type, filter by type; otherwise display everything. + if ( !empty($_REQUEST['type']) ) { + $filter_type = function($log) { + return ( $log->type == $_REQUEST['type'] ); + }; + + $logs->incidence = array_filter( + $logs->incidence, + $filter_type + ); + + $logs->log = array_filter( + $logs->log, + $filter_type + ); + } +} + +?> + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+

Overview

+ + + + + + + + + + + + incidence as $log ) : ?> + + + + + + + + + +
type#Details
type ?>count ?> + decoded_message ?> +
+ +

All entries

+ + + + + + + + + + log as $log ) : ?> + + + + + + + + + +
typeTimeMessage
type ?>time ?>decoded_message ?>
+ + + +
+ */ ?> +
+ +
+

No logs available as of yet.

+
+ +
+ + + + + + + + + diff --git a/test/css/style.css b/test/css/style.css deleted file mode 100644 index a351c41..0000000 --- a/test/css/style.css +++ /dev/null @@ -1,7 +0,0 @@ -body { padding:10px; } - -ul { list-style:none; margin-left:5px; } -li { margin:5px 0; } -.checkbox label { display:inline-block; } - -.log_info { height:150px; overflow:auto; } \ No newline at end of file diff --git a/test/js/scripts.js b/test/js/scripts.js deleted file mode 100644 index b8fbd9d..0000000 --- a/test/js/scripts.js +++ /dev/null @@ -1,53 +0,0 @@ -jQuery(function($) { - $('.no-js').removeClass('no-js'); - - var location = false; - var screen_size = false; - var user_agent = false; - var window_size = false; - - $('input:button').click(function(e) { - e.preventDefault(); - initLogging(); - - if ($(this).hasClass('error')) { - $.error($(this).parents('li').find('input:text').val()); - } else if ($(this).hasClass('info')) { - $.info($(this).parents('li').find('input:text').val()); - } else if ($(this).hasClass('log')) { - $.log($(this).parents('li').find('input:text').val()); - } - - location.href = ''; - }); - - $('input:checkbox').click(function(e) { - // toggle our variables - if (this.name == 'location') { - location = !location; - } else if (this.name == 'screen_size') { - screen_size = !screen_size; - } else if (this.name == 'user_agent') { - user_agent = !user_agent; - } else if (this.name == 'window_size') { - window_size = !window_size; - } - }); - - function initLogging() { - $.clientSideLogging({ - error_url: 'log.php?type=error', - info_url: 'log.php?type=info', - log_url: 'log.php?type=log', - log_level: 3, - native_error:true, - use_console:false, - client_info: { - location:location, - screen_size:screen_size, - user_agent:user_agent, - window_size:window_size - } - }); - } -}); \ No newline at end of file diff --git a/test/test.php b/test/test.php deleted file mode 100644 index 1318d15..0000000 --- a/test/test.php +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - -
-
-

Client Side Logging Test

-
-
- -
-
- - - - - - - - - - - - - - - - - diff --git a/test/view_logs.php b/test/view_logs.php deleted file mode 100644 index b526afd..0000000 --- a/test/view_logs.php +++ /dev/null @@ -1,184 +0,0 @@ -incidence = get_object_vars($logs->incidence); - -function format_log($log) { - $log->decoded_message = $log->message; - if ( $log->format == 'json' ) { - $log->decoded_message = print_r(json_decode($log->message), 1); - $log->decoded_message = preg_replace('/stdClass Object\s*/', '', $log->decoded_message); - $log->decoded_message = htmlentities($log->decoded_message); - $log->decoded_message = '
' . $log->decoded_message . '
'; - } -} - -foreach ( (array) $logs->incidence as $log ) { - $log = format_log($log); -} - -foreach ( (array) $logs->log as $log ) { - $log = format_log($log); -} - -// Show log entries in reverse chronological order. -$logs->log = array_reverse($logs->log); - -// Sort incidence entries by count. -usort( - $logs->incidence, - function($a, $b) { - if ( $a->count == $b->count ) { - // If the counts are the same, sort by most recent. - if ( $a->first_logged == $b->first_logged ) { - return 0; - } - return ( $a->first_logged < $b->first_logged ) ? 1 : -1; - } - // We're sorting descending. - return ( $a->count < $b->count ) ? 1 : -1; - } -); - -// If we've been given a type, filter by type; otherwise display everything. -if ( !empty($_REQUEST['type']) ) { - $filter_type = function($log) { - return ( $log->type == $_REQUEST['type'] ); - }; - - $logs->incidence = array_filter( - $logs->incidence, - $filter_type - ); - - $logs->log = array_filter( - $logs->log, - $filter_type - ); -} - -?> - - - - - - - - - - - - - - - - - - - - - - -
-
-

Client Side Logs

-
-
- -
-

Overview

- - - - - - - - - incidence as $log ) : ?> - - - - - - -
# of IncidentsDetails
count ?> - decoded_message ?> -
- -

All entries

- - - - - - - log as $log ) : ?> - - - - - - -
TimeMessage
time ?>decoded_message ?>
- - - -
- */ ?> -
-
- - - - - - - - - - - - - - - - - -