├── .gitignore ├── server ├── dev_public │ ├── lib │ │ ├── js │ │ │ ├── 0_licenses.js │ │ │ ├── 5_ripples.min.js │ │ │ ├── 4_material.min.js │ │ │ ├── 6_morris.min.js │ │ │ └── 3_bootstrap.min.js │ │ ├── fonts │ │ │ ├── Material-Design-Icons.eot │ │ │ ├── Material-Design-Icons.ttf │ │ │ └── Material-Design-Icons.woff │ │ └── css │ │ │ ├── 4_morris.css │ │ │ └── 3_ripples.min.css │ ├── js │ │ ├── PageInitialization.js │ │ ├── LogDetailRoute.js │ │ ├── LogObjectModel.js │ │ ├── StatsRoute.js │ │ ├── Router.js │ │ ├── DataLoader.js │ │ └── LogsRoute.js │ └── less │ │ └── core.less ├── routes │ ├── capture_post.js │ └── rest.js ├── server.js └── views │ └── index.html ├── config.inc.json ├── test ├── config.test.json ├── server.spec.js ├── rest.spec.js └── test_log_storage ├── .travis.yml ├── demo.html ├── LICENSE.txt ├── package.json ├── dist ├── capture.min.js └── capture.js ├── js └── capture.js ├── README.md └── Gruntfile.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | server/store/ 3 | server/public/ 4 | test/log_storage 5 | -------------------------------------------------------------------------------- /server/dev_public/lib/js/0_licenses.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarshallOfSound/OpenLog/HEAD/server/dev_public/lib/js/0_licenses.js -------------------------------------------------------------------------------- /server/dev_public/js/PageInitialization.js: -------------------------------------------------------------------------------- 1 | window.onload = function() { 2 | $.material.init(); 3 | window.Router = new Router(); 4 | }; -------------------------------------------------------------------------------- /config.inc.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [{ 3 | "user": "openlog", 4 | "password": "password" 5 | }], 6 | "server": { 7 | "port": 4783 8 | } 9 | } -------------------------------------------------------------------------------- /test/config.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "auth": [{ 3 | "user": "openlog", 4 | "password": "password" 5 | }], 6 | "server": { 7 | "port": 4782 8 | } 9 | } -------------------------------------------------------------------------------- /server/dev_public/lib/fonts/Material-Design-Icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarshallOfSound/OpenLog/HEAD/server/dev_public/lib/fonts/Material-Design-Icons.eot -------------------------------------------------------------------------------- /server/dev_public/lib/fonts/Material-Design-Icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarshallOfSound/OpenLog/HEAD/server/dev_public/lib/fonts/Material-Design-Icons.ttf -------------------------------------------------------------------------------- /server/dev_public/lib/fonts/Material-Design-Icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarshallOfSound/OpenLog/HEAD/server/dev_public/lib/fonts/Material-Design-Icons.woff -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "0.12" 5 | - "0.11" 6 | - "0.10" 7 | - iojs 8 | before_install: 9 | - "npm install -g grunt-cli" 10 | -------------------------------------------------------------------------------- /server/dev_public/lib/css/4_morris.css: -------------------------------------------------------------------------------- 1 | .morris-hover{position:absolute;z-index:1000}.morris-hover.morris-default-style{border-radius:10px;padding:6px;color:#666;background:rgba(255,255,255,0.8);border:solid 2px rgba(230,230,230,0.8);font-family:sans-serif;font-size:12px;text-align:center}.morris-hover.morris-default-style .morris-hover-row-label{font-weight:bold;margin:0.25em 0} 2 | .morris-hover.morris-default-style .morris-hover-point{white-space:nowrap;margin:0.1em 0} 3 | -------------------------------------------------------------------------------- /demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Demo 6 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /server/dev_public/lib/css/3_ripples.min.css: -------------------------------------------------------------------------------- 1 | .withripple{position:relative}.ripple-wrapper{position:absolute;top:0;left:0;z-index:1;width:100%;height:100%;overflow:hidden;border-radius:inherit;pointer-events:none}.ripple{position:absolute;width:20px;height:20px;margin-left:-10px;margin-top:-10px;border-radius:100%;background-color:rgba(0,0,0,.05);-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1);-webkit-transform-origin:50%;-ms-transform-origin:50%;transform-origin:50%;opacity:0;pointer-events:none}.ripple.ripple-on{transition:opacity .15s ease-in 0s,-webkit-transform .5s cubic-bezier(.4,0,.2,1) .1s;transition:opacity .15s ease-in 0s,transform .5s cubic-bezier(.4,0,.2,1) .1s;opacity:.1}.ripple.ripple-out{transition:opacity .1s linear 0s!important;opacity:0} 2 | /*# sourceMappingURL=ripples.min.css.map */ -------------------------------------------------------------------------------- /server/routes/capture_post.js: -------------------------------------------------------------------------------- 1 | module.exports = function(app, collection, sendError) { 2 | app.post('/log', function(req, res) { 3 | var required = ["type", "message", "trace", "page", "time"], 4 | tmp; 5 | console.log("Received a burst of " + req.body.length + " log" + (req.body.length === 1 ? '' : 's') + " from: " + req.ip); 6 | for (var i = 0; i < req.body.length; i++) { 7 | tmp = req.body[i]; 8 | for (var k = 0; k < required.length; k++) { 9 | if (!tmp[required[k]]) { 10 | sendError("LogObject requires the attribute: " + required[k]); 11 | } 12 | } 13 | tmp.IP = req.ip; 14 | tmp.page = tmp.page.replace(/https?:\/\//g, ''); 15 | collection.insert(tmp); 16 | } 17 | res.end(); 18 | }); 19 | }; -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Samuel Attard 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openlog", 3 | "version": "1.0.3", 4 | "description": "An easy way to aggregate client side logging", 5 | "main": "server/server.js", 6 | "bin": { 7 | "openlog": "./server/server.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/MarshallOfSound/OpenLog.git" 12 | }, 13 | "scripts": { 14 | "test": "grunt test" 15 | }, 16 | "author": "Samuel Attard", 17 | "license": "Apache 2", 18 | "dependencies": { 19 | "basic-auth": "^1.0.2", 20 | "body-parser": "^1.13.1", 21 | "compression": "^1.5.0", 22 | "ejs": "^2.3.1", 23 | "express": "^4.12.4", 24 | "grunt": "^0.4.5", 25 | "grunt-cli": "^0.1.13", 26 | "grunt-contrib-clean": "^0.6.0", 27 | "grunt-contrib-concat": "^0.5.1", 28 | "grunt-contrib-copy": "^0.8.0", 29 | "grunt-contrib-cssmin": "^0.12.3", 30 | "grunt-contrib-jshint": "^0.11.2", 31 | "grunt-contrib-less": "^1.0.1", 32 | "grunt-contrib-uglify": "^0.9.1", 33 | "grunt-contrib-watch": "^0.6.1", 34 | "grunt-text-replace": "^0.4.0", 35 | "moment": "^2.10.3", 36 | "sync-exec": "^0.5.0", 37 | "tingodb": "^0.3.4" 38 | }, 39 | "devDependencies": { 40 | "grunt-mocha-test": "^0.12.7", 41 | "mocha": "^2.3.2", 42 | "should": "^7.1.0", 43 | "supertest": "^1.1.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /server/dev_public/js/LogDetailRoute.js: -------------------------------------------------------------------------------- 1 | var LogDetailRoute = function(conf) { 2 | if (typeof conf.id === 'undefined' || typeof conf.group === 'undefined') { 3 | localStorage.setItem("page", "logs"); 4 | window.location.reload(); 5 | return; 6 | } 7 | this.logID = conf.id; 8 | this.logGroup = conf.group; 9 | this.container = $('.log_detail_container'); 10 | this.container.css({opacity: 0}); 11 | }; 12 | LogDetailRoute.prototype.init = function() { 13 | this.Loader = new DataLoader(); 14 | this.Loader.fetchLogData(this.logID, this.logGroup, $.proxy(function(data) { 15 | var log = new LogObject(data); 16 | 17 | this.container.find('.log_id').text(log._id + (this.logGroup ? ' (Grouped with similar)' : '')); 18 | this.container.find('.log_type').text(log.getNiceType()) 19 | .removeClass('text-info').removeClass('text-danger').removeClass('text-warning').addClass('text-' + log.getBootstrapType()); 20 | this.container.find('.log_time').text(log.getDate()); 21 | this.container.find('.log_page').html('' + log.page + ''); 22 | if (this.logGroup) { 23 | this.container.find('.log_quantity').css('display', 'block'); 24 | this.container.find('.log_quantity_number').text(data.quantity); 25 | } else { 26 | this.container.find('.log_quantity').css('display', 'none'); 27 | } 28 | this.container.find('.log_message').text(log.message); 29 | this.container.find('.log_trace').text(log.trace); 30 | $('.log_detail_container').animate({opacity: 1}); 31 | }, this)); 32 | this.onReady(); 33 | }; -------------------------------------------------------------------------------- /server/dev_public/js/LogObjectModel.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A representation of a Log that was send to OpenLog 3 | * @param obj The JSON object holding the raw Log data 4 | * @constructor 5 | */ 6 | var LogObject = function(obj) { 7 | this.type = obj.type; 8 | this.message = (typeof obj.message === 'object' ? obj.message["0"] : obj.message); 9 | this.trace = obj.trace; 10 | this.UNIXtime = obj.time; 11 | this.page = obj.page; 12 | this.IP = obj.IP; 13 | this.count = obj.count || 1; 14 | this._id = obj._id; 15 | }; 16 | LogObject.prototype = { 17 | /** 18 | * Prettifies the timestamp into a string in the format {dd-mm-yyyy hh:ii:ss} 19 | * @returns {string} 20 | */ 21 | getDate: function() { 22 | var date = new Date(this.UNIXtime), 23 | year = date.getFullYear(), 24 | month = "0" + (date.getMonth() + 1), 25 | day = date.getDate(), 26 | hours = date.getHours(), 27 | minutes = "0" + date.getMinutes(), 28 | seconds = "0" + date.getSeconds(); 29 | 30 | return [day, month.substr(-2), year].join("-") + " " + [hours, minutes.substr(-2), seconds.substr(-2)].join(":"); 31 | }, 32 | /** 33 | * Converts the integer representing a Log type into its corresponding string 34 | * @returns {string} 35 | */ 36 | getNiceType: function() { 37 | return { 38 | info: "Info", 39 | warn: "Warning", 40 | error: "Error" 41 | }[this.type]; 42 | }, 43 | /** 44 | * Converts the integer representing a Log type into its corresponding bootstrap class prefix 45 | * @returns {string} 46 | */ 47 | getBootstrapType: function() { 48 | return { 49 | info: "info", 50 | warn: "warning", 51 | error: "danger" 52 | }[this.type]; 53 | } 54 | }; -------------------------------------------------------------------------------- /dist/capture.min.js: -------------------------------------------------------------------------------- 1 | var Logger=function(){this.l=window.location,this.SERVER=this.l.protocol+"//"+this.l.hostname+":4783/log",this.LOGGING_LEVELS={info:!0,warn:!0,error:!0};var a,b,c="openLogQueue",d=localStorage,e=document.getElementsByTagName("script"),f=this;for(this.o={error:console.error,info:console.info,log:console.log,warn:console.warn},this.queue=JSON.parse(d.getItem(c)||"[]"),d.removeItem(c),window.onbeforeunload=function(){d.setItem(c,JSON.stringify(f.queue))},setInterval(function(){f.sending||f.sendQueue.call(f)},1e3),a=0;a0){var a=new XMLHttpRequest,b=this;b.sending=!0,a.open("post",this.SERVER,!0),a.setRequestHeader("Content-Type","application/json;charset=UTF-8"),a.onload=function(){b.queue=[],b.sending=!1},a.onerror=function(){b.sending=!1},a.send("["+this.queue.join(", ")+"]")}},_send:function(a,b,c){var d=this.LOGGING_LEVELS[a]||!1,e=this.oneEquals(this.DOMAIN_RESTRICTION,this.l.hostname)||!this.DOMAIN_RESTRICTION;d&&e&&this.LOGGING_LEVELS[a]&&this.queue.push(JSON.stringify({type:a,message:b,trace:c||Error().trace,time:Date.now(),page:this.l.href}))},set:function(a,b){"undefined"!=typeof this.LOGGING_LEVELS[a]&&(this.LOGGING_LEVELS[a]=b)}};for(var Log=new Logger,types=["error","info","log","warn"],i=0;i max && key !== 'total') { 62 | max = data[key]; 63 | maxKey = key; 64 | delete data[key]; 65 | } 66 | } 67 | } 68 | if (max !== 0) { 69 | table.append('' + maxKey + '' + max + ''); 70 | } 71 | } 72 | }; -------------------------------------------------------------------------------- /server/dev_public/less/core.less: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-touch-callout: none; 3 | -webkit-user-select: none; 4 | -khtml-user-select: none; 5 | -moz-user-select: none; 6 | -ms-user-select: none; 7 | user-select: none; 8 | } 9 | .container > div { 10 | opacity: 0; 11 | display: none; 12 | .stat-panel { 13 | padding: 12px; 14 | .panel-heading { 15 | text-align: center; 16 | } 17 | .panel-body { 18 | font-size: 44px; 19 | text-align: center; 20 | } 21 | } 22 | .panel-filter { 23 | .panel-heading { 24 | cursor: pointer; 25 | .filter-toggle { 26 | transition: all 0.3s linear; 27 | transform: rotate(0deg); 28 | margin-top: -4px; 29 | &.up { 30 | transform: rotate(180deg); 31 | } 32 | } 33 | } 34 | .filter-bar { 35 | height: 0; 36 | overflow: hidden; 37 | transition: all 0.3s linear; 38 | .col-md-6 { 39 | margin-top: 18px; 40 | &:first-child { 41 | margin-top: 0; 42 | } 43 | &:nth-child(2) { 44 | margin-top: 0; 45 | } 46 | } 47 | } 48 | } 49 | #logTable { 50 | tr { 51 | td { 52 | cursor: pointer; 53 | &:first-child { 54 | font-weight: bold; 55 | } 56 | &:nth-child(2) { 57 | font-weight: bold; 58 | } 59 | } 60 | &.bg-info:hover { 61 | background-color: #e2f6ff; 62 | } 63 | &.bg-warning { 64 | background-color: #f5f1de; 65 | &:hover { 66 | background-color: #fffbe8; 67 | } 68 | } 69 | &.bg-danger:hover { 70 | background-color: #ffecec; 71 | } 72 | } 73 | } 74 | .pagination { 75 | width: 100%; 76 | text-align: center; 77 | .btn { 78 | background: #FFFFFF; 79 | color: #4B8BFA; 80 | padding: 12px; 81 | min-width: 44px; 82 | height:44px; 83 | font-weight: bold; 84 | border-radius: 50%; 85 | margin: 0 4px; 86 | &.active { 87 | background: #4B8BFA; 88 | color: #fff; 89 | &:hover { 90 | background: #5271e7; 91 | } 92 | } 93 | &:hover { 94 | background: #efefef; 95 | } 96 | } 97 | } 98 | } 99 | .modal { 100 | background: rgba(0, 0, 0, 0.8); 101 | &#progressModal { 102 | .progress { 103 | margin: 20px 0; 104 | height: 20px; 105 | } 106 | } 107 | } 108 | svg { 109 | width: 100% !important; 110 | } -------------------------------------------------------------------------------- /server/dev_public/lib/js/5_ripples.min.js: -------------------------------------------------------------------------------- 1 | !function(a,b,c,d){"use strict";function e(b,c){g=this,this.element=a(b),this.options=a.extend({},h,c),this._defaults=h,this._name=f,this.init()}var f="ripples",g=null,h={};e.prototype.init=function(){var c=this.element;c.on("mousedown touchstart",function(d){if(!g.isTouch()||"mousedown"!==d.type){c.find(".ripple-wrapper").length||c.append('
');var e=c.children(".ripple-wrapper"),f=g.getRelY(e,d),h=g.getRelX(e,d);if(f||h){var i=g.getRipplesColor(c),j=a("
");j.addClass("ripple").css({left:h,top:f,"background-color":i}),e.append(j),function(){return b.getComputedStyle(j[0]).opacity}(),g.rippleOn(c,j),setTimeout(function(){g.rippleEnd(j)},500),c.on("mouseup mouseleave touchend",function(){j.data("mousedown","off"),"off"===j.data("animating")&&g.rippleOut(j)})}}})},e.prototype.getNewSize=function(a,b){return Math.max(a.outerWidth(),a.outerHeight())/b.outerWidth()*2.5},e.prototype.getRelX=function(a,b){var c=a.offset();return g.isTouch()?(b=b.originalEvent,1!==b.touches.length?b.touches[0].pageX-c.left:!1):b.pageX-c.left},e.prototype.getRelY=function(a,b){var c=a.offset();return g.isTouch()?(b=b.originalEvent,1!==b.touches.length?b.touches[0].pageY-c.top:!1):b.pageY-c.top},e.prototype.getRipplesColor=function(a){var c=a.data("ripple-color")?a.data("ripple-color"):b.getComputedStyle(a[0]).color;return c},e.prototype.hasTransitionSupport=function(){var a=c.body||c.documentElement,b=a.style,e=b.transition!==d||b.WebkitTransition!==d||b.MozTransition!==d||b.MsTransition!==d||b.OTransition!==d;return e},e.prototype.isTouch=function(){return/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)},e.prototype.rippleEnd=function(a){a.data("animating","off"),"off"===a.data("mousedown")&&g.rippleOut(a)},e.prototype.rippleOut=function(a){a.off(),g.hasTransitionSupport()?a.addClass("ripple-out"):a.animate({opacity:0},100,function(){a.trigger("transitionend")}),a.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",function(){a.remove()})},e.prototype.rippleOn=function(a,b){var c=g.getNewSize(a,b);g.hasTransitionSupport()?b.css({"-ms-transform":"scale("+c+")","-moz-transform":"scale("+c+")","-webkit-transform":"scale("+c+")",transform:"scale("+c+")"}).addClass("ripple-on").data("animating","on").data("mousedown","on"):b.animate({width:2*Math.max(a.outerWidth(),a.outerHeight()),height:2*Math.max(a.outerWidth(),a.outerHeight()),"margin-left":-1*Math.max(a.outerWidth(),a.outerHeight()),"margin-top":-1*Math.max(a.outerWidth(),a.outerHeight()),opacity:.2},500,function(){b.trigger("transitionend")})},a.fn.ripples=function(b){return this.each(function(){a.data(this,"plugin_"+f)||a.data(this,"plugin_"+f,new e(this,b))})}}(jQuery,window,document); 2 | //# sourceMappingURL=ripples.min.js.map 3 | -------------------------------------------------------------------------------- /server/dev_public/lib/js/4_material.min.js: -------------------------------------------------------------------------------- 1 | !function(a){function b(a){return"undefined"==typeof a.which?!0:"number"==typeof a.which&&a.which>0?!a.ctrlKey&&!a.metaKey&&!a.altKey&&8!=a.which&&9!=a.which:!1}a.expr[":"].notmdproc=function(b){return a(b).data("mdproc")?!1:!0},a.material={options:{input:!0,ripples:!0,checkbox:!0,togglebutton:!0,radio:!0,arrive:!0,autofill:!1,withRipples:[".btn:not(.btn-link)",".card-image",".navbar a:not(.withoutripple)",".dropdown-menu a",".nav-tabs a:not(.withoutripple)",".withripple"].join(","),inputElements:"input.form-control, textarea.form-control, select.form-control",checkboxElements:".checkbox > label > input[type=checkbox]",togglebuttonElements:".togglebutton > label > input[type=checkbox]",radioElements:".radio > label > input[type=radio]"},checkbox:function(b){a(b?b:this.options.checkboxElements).filter(":notmdproc").data("mdproc",!0).after("")},togglebutton:function(b){a(b?b:this.options.togglebuttonElements).filter(":notmdproc").data("mdproc",!0).after("")},radio:function(b){a(b?b:this.options.radioElements).filter(":notmdproc").data("mdproc",!0).after("")},input:function(c){a(c?c:this.options.inputElements).filter(":notmdproc").data("mdproc",!0).each(function(){var b=a(this);if(a(this).attr("data-hint")||b.hasClass("floating-label")){if(b.wrap("
"),b.after(""),b.hasClass("floating-label")){var c=b.attr("placeholder");b.attr("placeholder",null).removeClass("floating-label"),b.after("
"+c+"
")}if(b.attr("data-hint")&&b.after("
"+b.attr("data-hint")+"
"),(null===b.val()||"undefined"==b.val()||""===b.val())&&b.addClass("empty"),b.parent().next().is("[type=file]")){b.parent().addClass("fileinput");var d=b.parent().next().detach();b.after(d)}}}),a(document).on("change",".checkbox input[type=checkbox]",function(){a(this).blur()}).on("keydown paste",".form-control",function(c){b(c)&&a(this).removeClass("empty")}).on("keyup change",".form-control",function(){var b=a(this);""===b.val()&&"undefined"!=typeof b[0].checkValidity&&b[0].checkValidity()?b.addClass("empty"):b.removeClass("empty")}).on("focus",".form-control-wrapper.fileinput",function(){a(this).find("input").addClass("focus")}).on("blur",".form-control-wrapper.fileinput",function(){a(this).find("input").removeClass("focus")}).on("change",".form-control-wrapper.fileinput [type=file]",function(){var b="";a.each(a(this)[0].files,function(a,c){b+=c.name+", "}),b=b.substring(0,b.length-2),b?a(this).prev().removeClass("empty"):a(this).prev().addClass("empty"),a(this).prev().val(b)})},ripples:function(b){a(b?b:this.options.withRipples).ripples()},autofill:function(){var b=setInterval(function(){a("input[type!=checkbox]").each(function(){a(this).val()&&a(this).val()!==a(this).attr("value")&&a(this).trigger("change")})},100);setTimeout(function(){clearInterval(b)},1e4);var c;a(document).on("focus","input",function(){var b=a(this).parents("form").find("input").not("[type=file]");c=setInterval(function(){b.each(function(){a(this).val()!==a(this).attr("value")&&a(this).trigger("change")})},100)}).on("blur","input",function(){clearInterval(c)})},init:function(){a.fn.ripples&&this.options.ripples&&this.ripples(),this.options.input&&this.input(),this.options.checkbox&&this.checkbox(),this.options.togglebutton&&this.togglebutton(),this.options.radio&&this.radio(),this.options.autofill&&this.autofill(),document.arrive&&this.options.arrive&&(a.fn.ripples&&this.options.ripples&&a(document).arrive(this.options.withRipples,function(){a.material.ripples(a(this))}),this.options.input&&a(document).arrive(this.options.inputElements,function(){a.material.input(a(this))}),this.options.checkbox&&a(document).arrive(this.options.checkboxElements,function(){a.material.checkbox(a(this))}),this.options.radio&&a(document).arrive(this.options.radioElements,function(){a.material.radio(a(this))}),this.options.togglebutton&&a(document).arrive(this.options.togglebuttonElements,function(){a.material.togglebutton(a(this))}))}}}(jQuery); 2 | //# sourceMappingURL=material.min.js.map 3 | -------------------------------------------------------------------------------- /dist/capture.js: -------------------------------------------------------------------------------- 1 | var Logger = function() { 2 | this.l = window.location; 3 | this.SERVER = this.l.protocol + "//" + this.l.hostname + ":4783/log"; 4 | this.LOGGING_LEVELS = { 5 | info: true, 6 | warn: true, 7 | error: true 8 | }; 9 | 10 | var key = "openLogQueue", store = localStorage, tags = document.getElementsByTagName('script'), self = this, i, d; 11 | this.o = { 12 | error: console.error, 13 | info: console.info, 14 | log: console.log, 15 | warn: console.warn 16 | }; 17 | this.queue = JSON.parse(store.getItem(key) || "[]"); 18 | store.removeItem(key); 19 | 20 | window.onbeforeunload = function() { 21 | store.setItem(key, JSON.stringify(self.queue)); 22 | }; 23 | setInterval(function() { 24 | if (!self.sending) { 25 | self.sendQueue.call(self); 26 | } 27 | }, 1000); 28 | 29 | for (i = 0; i < tags.length; i++) { 30 | d = tags[i].getAttribute('data-capture'); 31 | url = tags[i].getAttribute('data-log-url'); 32 | url = (/\/log\/?$/i.test(url)) ? url : url + '/log'; 33 | // This option is set to only send logs when running on a specific hostname 34 | r = tags[i].getAttribute('data-restrict-to'); 35 | if (url) { 36 | this.SERVER = url; 37 | } 38 | if (d) { 39 | d = d.split(" "); 40 | this.LOGGING_LEVELS = { 41 | info: false, 42 | warn: false, 43 | error: false 44 | }; 45 | for (i = 0; i < d.length; i++) { 46 | this.set(d[i], true); 47 | } 48 | break; 49 | } 50 | if (r) { 51 | this.DOMAIN_RESTRICTION = r; 52 | } 53 | } 54 | 55 | this.oneEquals = function(optionsStr, target) { 56 | if (!optionsStr || !target) { return false; } 57 | return optionsStr.split(' ').indexOf(target) !== -1; 58 | }; 59 | }; 60 | Logger.prototype = { 61 | console: function(msg) { 62 | this.o.log.apply(console, [msg]); 63 | }, 64 | error: function() { 65 | console.error.apply(console, arguments); 66 | }, 67 | info: function() { 68 | console.info.apply(console, arguments); 69 | }, 70 | warn: function() { 71 | console.warn.apply(console, arguments); 72 | }, 73 | sendQueue: function() { 74 | if (this.queue.length > 0) { 75 | var req = new XMLHttpRequest(), 76 | self = this; 77 | self.sending = true; 78 | req.open("post", this.SERVER, true); 79 | req.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); 80 | req.onload = function() { 81 | self.queue = []; 82 | self.sending = false; 83 | }; 84 | req.onerror = function() { 85 | self.sending = false; 86 | }; 87 | req.send("[" + this.queue.join(", ") + "]"); 88 | } 89 | }, 90 | _send: function(type, message, t) { 91 | var a = this.LOGGING_LEVELS[type] || false; 92 | var b = this.oneEquals(this.DOMAIN_RESTRICTION, this.l.hostname) || !this.DOMAIN_RESTRICTION; 93 | if ( a && b && this.LOGGING_LEVELS[type] ) { 94 | this.queue.push(JSON.stringify({type: type, message: message, trace: (t || Error().trace), time: Date.now(), page: this.l.href})); 95 | } 96 | }, 97 | set: function(type, state) { 98 | if (typeof (this.LOGGING_LEVELS[type]) !== 'undefined') { 99 | this.LOGGING_LEVELS[type] = state; 100 | } 101 | } 102 | }; 103 | 104 | var Log = new Logger(), 105 | types = ["error", "info", "log", "warn"]; 106 | 107 | for (var i = 0; i < types.length; i++) { 108 | (function() { 109 | var k = i; 110 | console[types[k]] = function () { 111 | Log._send(types[k], arguments, Error().stack); 112 | Log.o[types[k]].apply(this, arguments); 113 | }; 114 | })(); // jshint ignore:line 115 | } 116 | 117 | window.onerror = function(msg, a, b, c, err) { 118 | Log._send("error", msg, err.stack); 119 | }; 120 | window.Log = Log; 121 | -------------------------------------------------------------------------------- /js/capture.js: -------------------------------------------------------------------------------- 1 | var Logger = function() { 2 | this.l = window.location; 3 | this.SERVER = this.l.protocol + "//" + this.l.hostname + ":{{SERVER_PORT}}/log"; 4 | this.LOGGING_LEVELS = { 5 | info: true, 6 | warn: true, 7 | error: true 8 | }; 9 | 10 | var key = "openLogQueue", store = localStorage, tags = document.getElementsByTagName('script'), self = this, i, d; 11 | this.o = { 12 | error: console.error, 13 | info: console.info, 14 | log: console.log, 15 | warn: console.warn 16 | }; 17 | this.queue = JSON.parse(store.getItem(key) || "[]"); 18 | store.removeItem(key); 19 | 20 | window.onbeforeunload = function() { 21 | store.setItem(key, JSON.stringify(self.queue)); 22 | }; 23 | setInterval(function() { 24 | if (!self.sending) { 25 | self.sendQueue.call(self); 26 | } 27 | }, 1000); 28 | 29 | for (i = 0; i < tags.length; i++) { 30 | d = tags[i].getAttribute('data-capture'); 31 | url = tags[i].getAttribute('data-log-url'); 32 | url = (/\/log\/?$/i.test(url)) ? url : url + '/log'; 33 | // This option is set to only send logs when running on a specific hostname 34 | r = tags[i].getAttribute('data-restrict-to'); 35 | if (url) { 36 | this.SERVER = url; 37 | } 38 | if (d) { 39 | d = d.split(" "); 40 | this.LOGGING_LEVELS = { 41 | info: false, 42 | warn: false, 43 | error: false 44 | }; 45 | for (i = 0; i < d.length; i++) { 46 | this.set(d[i], true); 47 | } 48 | break; 49 | } 50 | if (r) { 51 | this.DOMAIN_RESTRICTION = r; 52 | } 53 | } 54 | 55 | this.oneEquals = function(optionsStr, target) { 56 | if (!optionsStr || !target) { return false; } 57 | return optionsStr.split(' ').indexOf(target) !== -1; 58 | }; 59 | }; 60 | Logger.prototype = { 61 | console: function(msg) { 62 | this.o.log.apply(console, [msg]); 63 | }, 64 | error: function() { 65 | console.error.apply(console, arguments); 66 | }, 67 | info: function() { 68 | console.info.apply(console, arguments); 69 | }, 70 | warn: function() { 71 | console.warn.apply(console, arguments); 72 | }, 73 | sendQueue: function() { 74 | if (this.queue.length > 0) { 75 | var req = new XMLHttpRequest(), 76 | self = this; 77 | self.sending = true; 78 | req.open("post", this.SERVER, true); 79 | req.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); 80 | req.onload = function() { 81 | self.queue = []; 82 | self.sending = false; 83 | }; 84 | req.onerror = function() { 85 | self.sending = false; 86 | }; 87 | req.send("[" + this.queue.join(", ") + "]"); 88 | } 89 | }, 90 | _send: function(type, message, t) { 91 | var a = this.LOGGING_LEVELS[type] || false; 92 | var b = this.oneEquals(this.DOMAIN_RESTRICTION, this.l.hostname) || !this.DOMAIN_RESTRICTION; 93 | if ( a && b && this.LOGGING_LEVELS[type] ) { 94 | this.queue.push(JSON.stringify({type: type, message: message, trace: (t || Error().trace), time: Date.now(), page: this.l.href})); 95 | } 96 | }, 97 | set: function(type, state) { 98 | if (typeof (this.LOGGING_LEVELS[type]) !== 'undefined') { 99 | this.LOGGING_LEVELS[type] = state; 100 | } 101 | } 102 | }; 103 | 104 | var Log = new Logger(), 105 | types = ["error", "info", "log", "warn"]; 106 | 107 | for (var i = 0; i < types.length; i++) { 108 | (function() { 109 | var k = i; 110 | console[types[k]] = function () { 111 | Log._send(types[k], arguments, Error().stack); 112 | Log.o[types[k]].apply(this, arguments); 113 | }; 114 | })(); // jshint ignore:line 115 | } 116 | 117 | window.onerror = function(msg, a, b, c, err) { 118 | Log._send("error", msg, err.stack); 119 | }; 120 | window.Log = Log; 121 | -------------------------------------------------------------------------------- /server/dev_public/js/Router.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Constructs a new Router 3 | * Handles page switching and page state management without the browser actually loading a new page 4 | * @constructor 5 | */ 6 | var Router = function() { 7 | this.page = localStorage.getItem("page") || "stats"; 8 | this.routes = { 9 | "stats": StatsRoute, 10 | "logs": LogsRoute, 11 | "log-detail": LogDetailRoute 12 | }; 13 | this.initialLoad = true; 14 | // Set to null so the first page change happens 15 | localStorage.setItem("page", null); 16 | this.changePage(this.page, true, (localStorage.getItem("conf") || "{}")); 17 | 18 | window.onpopstate = $.proxy(function(state) { 19 | this.changePage(state.state.page, false, JSON.stringify(state.state.conf)); 20 | }, this); 21 | }; 22 | Router.prototype = { 23 | /** 24 | * Adds click listeners on all elements with the data-router attribute 25 | * NOTE: Removes all previous click listeners so you don't end up with multiple fires 26 | */ 27 | listenForRoutes: function() { 28 | $('[data-router]').unbind('click').click($.proxy(function(e) { 29 | var target = $(e.currentTarget).attr('href').substr(1); 30 | 31 | this.changePage(target, true, $(e.currentTarget).attr('data-router-conf')); 32 | e.preventDefault(); 33 | return false; 34 | }, this)); 35 | }, 36 | /** 37 | * Navigates to a new page (the given name variable) 38 | * @param name string Name of the page to change to 39 | * @param pushState boolean True if you want to append the page change to the browser history, False otherwise (By default should be true, can be undefined) 40 | * @param params string A JSON string representing an object that will be passed to the new Route created (By default an empty object, can be undefined) 41 | */ 42 | changePage: function(name, pushState, params) { 43 | var anim = false, 44 | conf = params || "{}", 45 | self = this; 46 | conf = JSON.parse(conf); 47 | pushState = (typeof pushState !== 'undefined' ? pushState : true); 48 | if (name !== localStorage.getItem("page")) { 49 | var nav = $('.navbar .nav.navbar-nav'); 50 | nav.find('li.active a[data-router]').parent().removeClass('active'); 51 | nav.find('li a[href="#' + (name === 'log-detail' ? 'logs' : name) + '"]').parent().addClass('active'); 52 | 53 | localStorage.setItem("page", name); 54 | localStorage.setItem("conf", JSON.stringify(conf)); 55 | this.page = name; 56 | if (pushState) { 57 | if (this.initialLoad) { 58 | history.replaceState({page: name, conf: conf}, null, "/#" + name); 59 | this.initialLoad = false; 60 | } else { 61 | history.pushState({page: name, conf: conf}, null, "/#" + name); 62 | } 63 | } 64 | $('.container > div').each(function() { 65 | var tmp = $(this); 66 | if (tmp.css("opacity") !== "0") { 67 | console.info("Hiding the " + $(this).data('route') + ' page'); 68 | anim = true; 69 | tmp.animate({opacity: 0}, $.proxy(function() { 70 | tmp.css("display", "none"); 71 | console.info("Showing the " + name + ' page'); 72 | this._animEnd(name, conf); 73 | }, self)); 74 | } 75 | }); 76 | if (!anim) { 77 | console.warn("No page detected as active, fading in the new page"); 78 | this._animEnd(name, conf); 79 | } 80 | } 81 | }, 82 | /** 83 | * This function fires once the old page has been faded out or instantly if no page was loaded already 84 | * @param name string The name of the page to switch to 85 | * @param conf object The conf object to be passed to the new page 86 | */ 87 | _animEnd: function(name, conf) { 88 | var self = this; 89 | this.currentRoute = new this.routes[name](conf); 90 | this.currentRoute.onReady = function() { 91 | $('.container > div[data-route=' + name + ']').css("display", "block").animate({opacity: 1}); 92 | self.listenForRoutes(); 93 | }; 94 | this.currentRoute.init(); 95 | } 96 | }; -------------------------------------------------------------------------------- /server/server.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var express = require('express'), 4 | compression = require('compression'), 5 | bodyParser = require('body-parser'), 6 | Engine = require('tingodb')(), 7 | basicAuth = require('basic-auth'), 8 | fs = require('fs'), 9 | execSync = require('sync-exec'), 10 | config = JSON.parse(fs.readFileSync(__dirname + '/../config.inc.json')), 11 | store = (fs.existsSync(__dirname + '/store') ? null : fs.mkdirSync(__dirname + '/store')), 12 | db = new Engine.Db(__dirname + '/store', {}), 13 | collection = db.collection("log_storage"), 14 | app = express(); 15 | 16 | if (process.args) { 17 | if (process.args.config) { 18 | config = process.args.config; 19 | } 20 | if (process.args.db) { 21 | db = process.args.db; 22 | collection = db.collection("log_storage"); 23 | } 24 | } 25 | 26 | const PORT = config.server.port; 27 | 28 | // Simple function to color text in the console output 29 | function logColor(msg, color) { 30 | var colors = { 31 | red: ['\x1b[31m', '\x1b[0m'], 32 | green: ['\x1b[32m', '\x1b[0m'], 33 | yellow: ['\x1b[33m', '\x1b[0m'], 34 | blue: ['\x1b[34m', '\x1b[0m'] 35 | }; 36 | return (!colors[color] ? msg : colors[color][0] + msg + colors[color][1]); 37 | } 38 | 39 | // First lets make sure the server files have been generated 40 | if (!(fs.existsSync(__dirname + '/public') && fs.existsSync(__dirname + '/public/css') && fs.existsSync(__dirname + '/public/fonts') && fs.existsSync(__dirname + '/public/js'))) { 41 | console.warn("Server doesn't appear to be built, attempting to build now"); 42 | var buildLog = execSync('grunt build', {cwd: __dirname + '/../'}); 43 | if (buildLog.stderr === '' && buildLog.status === 0) { 44 | console.log(logColor('Server built successfully', 'green')); 45 | } else { 46 | console.error(logColor(buildLog.stderr, 'yellow')); 47 | console.error(logColor('Server failed to build, please try building manually with the \'grunt build\' command', 'yellow')); 48 | return false; 49 | } 50 | 51 | } 52 | // Basic error function if a request goes wrong 53 | var err = function(error, res) { 54 | res.status(500); 55 | var json = {error: error}; 56 | res.json(json); 57 | }; 58 | // Basic HTTP Authentication function 59 | var auth = function(req, res, next) { 60 | if (req.originalUrl !== '/log' && config.auth !== null && config.auth.length !== 0) { 61 | function notAuthorized(res) { 62 | res.set('WWW-Authenticate', 'Basic realm=Authorization Required'); 63 | return res.sendStatus(401); 64 | } 65 | 66 | var user = basicAuth(req); 67 | if (!user || !user.name || !user.pass) { 68 | return notAuthorized(res); 69 | } 70 | 71 | for (var i = 0; i < config.auth.length; i++) { 72 | if (user.name === config.auth[i].user && user.pass === config.auth[i].password) { 73 | return next(); 74 | } 75 | } 76 | return notAuthorized(res); 77 | } 78 | return next(); 79 | }; 80 | 81 | // Enable basic authentication 82 | app.use(auth); 83 | 84 | // Allow cross origin requests 85 | app.use(function(req, res, next) { 86 | res.header("Access-Control-Allow-Origin", "*"); 87 | res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); 88 | next(); 89 | }); 90 | 91 | // Setup the HTML engine 92 | app.set('views', __dirname + '/views'); 93 | app.engine('html', require('ejs').renderFile); 94 | app.set('view engine', 'html'); 95 | 96 | // Enable gzip compression 97 | app.use(compression()); 98 | 99 | // Make the public directory public 100 | app.use(express.static(__dirname + '/public')); 101 | 102 | // Enable JSON body reading 103 | app.use(bodyParser.json()); 104 | app.use(bodyParser.urlencoded({ 105 | extended: true 106 | })); 107 | 108 | // The base route for the OpenLog console 109 | app.get('/', function(req, res) { 110 | res.render('index'); 111 | }); 112 | 113 | // Require the route files 114 | // The post route to receive logs 115 | require(__dirname + '/routes/capture_post')(app, collection, err); 116 | // The REST routes for the OpenLog console 117 | require(__dirname + '/routes/rest')(app, collection, err); 118 | 119 | console.log("OpenLog server listening on port:", logColor(PORT, 'blue')); 120 | 121 | module.exports = app.listen(PORT); 122 | -------------------------------------------------------------------------------- /server/dev_public/js/DataLoader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Constructs a new DataLoader 3 | * Fetches content from the OpenLog REST services in a UI friendly asynchronous manner 4 | * @constructor 5 | */ 6 | var DataLoader = function() { 7 | this.queryString = ""; 8 | this.inProgress = 0; 9 | this.silent = false; 10 | }; 11 | DataLoader.prototype = { 12 | /** 13 | * Sets the query filter for LogObject REST requests 14 | * @param type string {info | warn | error} 15 | * @param message string {Any regexp} 16 | * @param page string {Any string, has to match the page name exactly} 17 | * @param ip string {Any string, has to match the IP exactly} 18 | * @param id integer {Any integer, should be greater than 0} 19 | * @param group integer {0 | 1} 20 | */ 21 | setFilter: function(type, message, page, ip, id, group) { 22 | this.queryString = ""; 23 | this.queryString += (type ? '&type=' + type : ''); 24 | this.queryString += (message ? '&message=' + message : ''); 25 | this.queryString += (page ? '&page=' + page : ''); 26 | this.queryString += (ip ? '&ip=' + ip : ''); 27 | this.queryString += (id ? '&id=' + id : ''); 28 | this.queryString += (group ? '&group=' + group : ''); 29 | this.queryString = this.queryString.substr(1); 30 | }, 31 | /** 32 | * Fetches a search results page number and returns the results via the callback parameter 33 | * @param num integer The page number to fetch 34 | * @param cb function A callback function that will be provided an array of LogObject's 35 | */ 36 | fetchPage: function(num, cb) { 37 | var pageNumber = num || 0; 38 | this._fetch('/rest/logs/' + pageNumber + '?' + this.queryString, function(data) { 39 | var ret = []; 40 | for (var i = 0; i < data.logs.length; i++) { 41 | ret.push(new LogObject(data.logs[i])); 42 | } 43 | data.logs = ret; 44 | cb(data); 45 | }); 46 | }, 47 | /** 48 | * Fetches the Stats overview data and returns it via the provided callback function 49 | * @param cb function A callback function that will be provided the returns Stats Object 50 | */ 51 | fetchStats: function(cb) { 52 | this._fetch('/rest/logs/stats', cb); 53 | }, 54 | /** 55 | * Fetches a list of all the pages that have submitted logs to OpenLog 56 | * @param cb function A callback function that will be provided an array of all the page URL's 57 | */ 58 | fetchPageList: function(cb) { 59 | this._fetch('/rest/logs/pages', cb); 60 | }, 61 | /** 62 | * Fetches the complete JSON data for a submitted log file, accepts the `group` parameter to determine style of JSON 63 | * @param logID integer The ID of the Log to fetch 64 | * @param group bool Whether to fetch a group of logs that match the given log ID 65 | * @param cb function The function to send the data too 66 | */ 67 | fetchLogData: function(logID, group, cb) { 68 | this._fetch('/rest/logs/details/' + logID + '/' + (group ? 't' : 'f'), cb); 69 | }, 70 | /** 71 | * Fetches the given url and returns the response as JSON to the callback function 72 | * @param url string The URL to fetch 73 | * @param cb function The function to send the data too 74 | * @private 75 | */ 76 | _fetch: function(url, cb) { 77 | var self = this; 78 | self.inProgress++; 79 | console.info((this.silent ? 'Silently fetching' : 'Fetching') + " data from: " + url); 80 | var loadingModal = $('#progressModal'), 81 | start = Date.now(); 82 | if (!this.silent) { 83 | loadingModal.modal('show').on('hide.bs.modal', function (e) { 84 | e.preventDefault(); 85 | return false; 86 | }); 87 | } 88 | $.ajax(url, { 89 | method: 'GET', 90 | success: function(data) { 91 | if (typeof data !== 'object' || data.error) { 92 | console.error("An error occurred while reading the data from: " + url); 93 | console.error(data); 94 | alert("Something went wrong, check the console for more info"); 95 | return true; 96 | } 97 | setTimeout(function() { 98 | self.inProgress--; 99 | cb(data); 100 | if (self.inProgress === 0) { 101 | loadingModal.unbind().modal('hide'); 102 | } 103 | }, Math.max(0, 1200 - (Date.now() - start))); 104 | }, 105 | error: function(x, status, error) { 106 | console.error("An error occurred while requesting the data from: " + url); 107 | console.error(status + " --> " + error); 108 | console.warn("Ensure the OpenLog server is still running"); 109 | alert("Something went wrong, check the console for more info"); 110 | } 111 | }); 112 | } 113 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | OpenLog - Track client side Javascript errors in real time. [![Build Status](https://travis-ci.org/MarshallOfSound/OpenLog.svg?branch=master)](https://travis-ci.org/MarshallOfSound/OpenLog) 2 | ========================================================== 3 | 4 | OpenLog is a lightweight front end Javascript plugin (< 1kb gzipped!) that sends your user's console errors & warnings in real time to a dynamic dashboard built with Node. 5 | 6 | Installation 7 | ------------ 8 | 9 | 1. Include the [dist/capture.min.js](dist/capture.min.js) file on any page you want to capture the errors and logs for 10 | 11 | ````html 12 | 13 | ```` 14 | 15 | 2. Install globally with [npm](https://www.npmjs.com/about): `npm install -g openlog` 16 | 3. Start the open log server: `openlog` 17 | 18 | ...and that's it! Now you can access your instance of OpenLog at http://127.0.0.1:4783. The default login credentials are: 19 | 20 | ```` 21 | username: openlog 22 | password: password 23 | ```` 24 | 25 | Changing Settings 26 | ------------ 27 | 28 | Configuration options for OpenLog are set in `/config.inc.json`. To find where your copy of OpenLog is installed, run the following command: 29 | 30 | ````bash 31 | $ npm root -g 32 | > /usr/local/lib/node_modules 33 | ```` 34 | 35 | This command returns the path where global npm packages are installed on your machine. Once you know this path, you can visit the OpenLog directory with: `cd /openlog`. You can then modify the `/config.inc.json` file... 36 | 37 | | Setting | Description | 38 | |----------|-----------------------------------------------------------------------| 39 | | Username | Username used to access the admin panel with. Default: `openlog` | 40 | | Password | Password used to access the admin panel with. Default: `password` | 41 | | Port | The server port that the OpenLog admin panel runs on. Default: `4783` | 42 | 43 | Once you have modified those values you can build your own version of OpenLog by running these commands in the root OpenLog directory: 44 | 45 | ````bash 46 | npm install -g grunt-cli 47 | npm install 48 | grunt build 49 | ```` 50 | 51 | Amungst other things, this will build a new `dist/capture.min.js` file. It's now simply a matter of including this new file on your HTML pages, and starting up the OpenLog server again with your new compiled settings. 52 | 53 | Usage / Other Configuration 54 | ------------ 55 | If you are already logging using `console.log`, `console.info`, `console.warn` and `console.error` then OpenLog requires no extra work at all. It will capture errors globally on your page and listen to calls to the above `console` functions. Alternatively, if you don't want to explicitly log information to the clients console, you can use OpenLog's built in methods: 56 | 57 | - `Log.error();` 58 | - `Log.warn();` 59 | - `Log.info();` 60 | 61 | `Log` is a globally defined object by the `capture.min.js` file. 62 | 63 | ### Error Limiting 64 | 65 | If you don't want to capture certain logging types you simply add a `data-capture` parameter to the script tag that loaded the `capture.min.js` file and set it to be the types of logs you wish to capture. For instance, if you only want error logs: 66 | 67 | ````html 68 | 69 | ```` 70 | 71 | ...or if you want error and warning logs `data-capture="warn error"` etc etc. 72 | 73 | ### Modify OpenLog Server URL 74 | 75 | By default, OpenLog assumes that the dashboard is running on the same domain as the frontend it sends logs from (default port is 4783). To change this, you can specify the logging URL by setting a `data-log-url=""` attribute on the script tag that loaded the `capture.min.js`: 76 | 77 | ````html 78 | 79 | ```` 80 | 81 | ### Domain Limiting 82 | 83 | A final configurable option is to use `data-restrict-to` parameter on the script tag. This setting allows you to specify domain name(s) permitted to send logs to the OpenLog server, and is particularly useful for reporting console noise only in a staging/production environment (as opposed to developers working locally). By default, OpenLog will send logs from all sources. 84 | 85 | ````html 86 | 87 | 88 | ```` 89 | 90 | To restrict multiple domains, use spaces to separate them, eg - `data-restrict-to="staging.myserver.com production.com"`. 91 | 92 | Updating OpenLog 93 | ----------------- 94 | 95 | Fancy, smooth, no data loss updating method coming soon :) 96 | 97 | Contributing 98 | --------- 99 | 100 | All PR's and issues are welcomed with open arms. 101 | 102 | 1. Fork this repository. 103 | 2. Create a new branch: `git checkout -b my-new-feature`. 104 | 3. Make your changes and add some commits. 105 | 4. Push your changes to GitHub and send in a pull request to this repository. 106 | 107 | Requirements 108 | ------------ 109 | 110 | - `node.js` > 0.10 111 | - `npm` 112 | 113 | Author 114 | ------- 115 | 116 | Samuel Attard - - - 117 | 118 | License 119 | ------- 120 | 121 | OpenLog is licensed under the MIT License - see the LICENSE file for details. 122 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | var fs = require('fs'), 3 | config = JSON.parse(fs.readFileSync('./config.inc.json')); 4 | 5 | grunt.initConfig({ 6 | clean: { 7 | serverPublic: ['server/public'] 8 | }, 9 | concat: { 10 | server: { 11 | options: { 12 | separator: ';\n' 13 | }, 14 | src: ['server/dev_public/js/*.js'], 15 | dest: 'server/public/js/core.js' 16 | }, 17 | libJS: { 18 | options: { 19 | separator: ';\n' 20 | }, 21 | src: ['server/dev_public/lib/js/*.js', '!server/dev_public/lib/js/0_*.js'], 22 | dest: 'server/public/js/lib.js' 23 | }, 24 | libCSS: { 25 | src: ['server/dev_public/lib/css/*.css'], 26 | dest: 'server/public/css/lib.min.css' 27 | }, 28 | libLicense: { 29 | src: ['server/dev_public/lib/js/0_licenses.js', 'server/public/js/lib.min.js'], 30 | dest: 'server/public/js/lib.min.js' 31 | } 32 | }, 33 | copy: { 34 | fonts: { 35 | files: [ 36 | { 37 | expand: true, 38 | cwd: 'server/dev_public/lib/fonts', 39 | src: ['*.*'], 40 | dest: 'server/public/fonts/' 41 | } 42 | ] 43 | } 44 | }, 45 | cssmin: { 46 | lib: { 47 | options: { 48 | keepSpecialComments: 0 49 | }, 50 | files: { 51 | 'server/public/css/lib.min.css': ['server/public/css/lib.min.css'] 52 | } 53 | } 54 | }, 55 | less: { 56 | server: { 57 | options: { 58 | compress: true 59 | }, 60 | files: { 61 | "server/public/css/core.min.css": "server/dev_public/less/core.less" 62 | } 63 | } 64 | }, 65 | uglify: { 66 | dist: { 67 | options: { 68 | mangle: { 69 | except: ['Log'] 70 | } 71 | }, 72 | files: { 73 | 'dist/capture.min.js': ['dist/capture.js'] 74 | } 75 | }, 76 | server: { 77 | files: { 78 | 'server/public/js/core.min.js': ['server/public/js/core.js'], 79 | 'server/public/js/lib.min.js': ['server/public/js/lib.js'] 80 | } 81 | } 82 | }, 83 | jshint: { 84 | options: { 85 | curly: true, 86 | eqeqeq: true, 87 | eqnull: true, 88 | forin: true, 89 | unused: true, 90 | noempty: true, 91 | latedef: true, 92 | globals: { 93 | jQuery: true, 94 | browser: true, 95 | devel: true 96 | } 97 | }, 98 | dist: { 99 | files: [ 100 | { 101 | cwd: 'js', 102 | src: '*.js', 103 | expand: true 104 | } 105 | ] 106 | }, 107 | server: { 108 | files: [{ 109 | cwd: 'server/dev_public/js', 110 | src: '*.js', 111 | expand: true 112 | }], 113 | options: { 114 | globals: { 115 | jQuery: true 116 | } 117 | } 118 | } 119 | }, 120 | replace: { 121 | serverPort: { 122 | src: ['js/capture.js'], 123 | dest: 'dist/', 124 | replacements: [{ 125 | from: '{{SERVER_PORT}}', 126 | to: config.server.port 127 | }] 128 | } 129 | }, 130 | mochaTest: { 131 | test: { 132 | options: { 133 | reporter: 'spec' 134 | }, 135 | src: ['test/*.spec.js'] 136 | } 137 | }, 138 | watch: { 139 | capture: { 140 | files: ['js/capture.js'], 141 | tasks: ['build-capture'] 142 | }, 143 | "server-js": { 144 | files: ['server/dev_public/*.*', 'server/dev_public/**/*.*', 'server/dev_public/*', 'server/dev_public/lib/*.js'], 145 | tasks: ['server-js-prod'] 146 | }, 147 | "server-css": { 148 | files: ['server/dev_public/less/*.less', 'server/dev_public/lib/*.css'], 149 | tasks: ['server-css'] 150 | } 151 | } 152 | }); 153 | 154 | grunt.loadNpmTasks('grunt-contrib-clean'); 155 | grunt.loadNpmTasks('grunt-contrib-concat'); 156 | grunt.loadNpmTasks('grunt-contrib-copy'); 157 | grunt.loadNpmTasks('grunt-contrib-cssmin'); 158 | grunt.loadNpmTasks('grunt-contrib-jshint'); 159 | grunt.loadNpmTasks('grunt-contrib-less'); 160 | grunt.loadNpmTasks('grunt-text-replace'); 161 | grunt.loadNpmTasks('grunt-contrib-uglify'); 162 | grunt.loadNpmTasks('grunt-contrib-watch'); 163 | grunt.loadNpmTasks('grunt-mocha-test'); 164 | 165 | grunt.registerTask('default', ['jshint']); 166 | grunt.registerTask('server-css', ['less', 'concat:libCSS', 'cssmin:lib', 'copy:fonts']); 167 | grunt.registerTask('server-js-prod', ['jshint:server', 'server-js', 'uglify:server', 'concat:libLicense']); 168 | grunt.registerTask('server-js', ['jshint:server', 'concat:server', 'concat:libJS']); 169 | grunt.registerTask('build-capture', ['jshint:dist', 'replace:serverPort', 'uglify:dist']); 170 | grunt.registerTask('build-server', ['server-css', 'server-js-prod']); 171 | grunt.registerTask('build', ['build-capture', 'clean:serverPublic', 'build-server']); 172 | 173 | grunt.registerTask('test', ['build-server', 'mochaTest']); 174 | }; -------------------------------------------------------------------------------- /server/routes/rest.js: -------------------------------------------------------------------------------- 1 | module.exports = function(app, collection, sendError) { 2 | var moment = require('moment'), 3 | generateSearchObject = function(query, params) { 4 | var o = {}; 5 | for (var i = 0; i < params.length; i++) { 6 | if (typeof query[params[i]] !== 'undefined') { 7 | o[params[i]] = query[params[i]]; 8 | } 9 | } 10 | if (o.message) { 11 | console.msg = o.message; 12 | o['$where'] = function() { 13 | var msg = console.msg; 14 | if (typeof obj.message === 'object') { 15 | var ret = 0; 16 | for (var key in obj.message) { 17 | if (obj.message.hasOwnProperty(key)) { 18 | ret += ((new RegExp(".*" + msg + ".*", "gi")).test(obj.message[key]) ? 1 : 0); 19 | } 20 | } 21 | return ret > 0; 22 | } else { 23 | return (new RegExp(".*" + msg + ".*", "gi")).test(obj.message); 24 | } 25 | }; 26 | delete o.message; 27 | } 28 | return o; 29 | }; 30 | 31 | const LOGS_PER_PAGE = 20; 32 | 33 | app.get('/rest/logs/stats', function (req, res) { 34 | collection.find({}).toArray(function (err, logs) { 35 | var stats = { 36 | quantity: { 37 | total: logs.length, 38 | error: 0, 39 | warn: 0, 40 | info: 0 41 | }, 42 | pages: { 43 | total: logs.length 44 | }, 45 | past: [] 46 | }, 47 | tmp, 48 | start = moment(), 49 | end = moment(); 50 | for (var i = 0; i < logs.length; i++) { 51 | if (typeof (stats.quantity[logs[i].type]) !== 'undefined') { 52 | stats.quantity[logs[i].type]++; 53 | } 54 | if (typeof stats.pages[logs[i].page] === 'undefined') { 55 | stats.pages[logs[i].page] = 0; 56 | } 57 | if (logs[i].type === 'error') { 58 | stats.pages[logs[i].page]++; 59 | } 60 | } 61 | stats.pages.total = stats.quantity.error; 62 | for (var week = 0; week < 10; week++) { 63 | tmp = {week: week, total: 0, error: 0, warn: 0, info: 0}; 64 | start = moment(end); 65 | end = moment(start).subtract(7, 'days'); 66 | for (i = 0; i < logs.length; i++) { 67 | if (moment(logs[i].time).isBetween(end, start)) { 68 | tmp.total++; 69 | tmp[logs[i].type]++; 70 | } 71 | } 72 | stats.past.push(tmp); 73 | } 74 | res.json(stats); 75 | }); 76 | }); 77 | 78 | app.get('/rest/logs/pages', function (req, res) { 79 | collection.find({}).toArray(function (err, logs) { 80 | var pages = []; 81 | for (var i = 0; i < logs.length; i++) { 82 | if (pages.indexOf(logs[i].page) < 0) { 83 | pages.push(logs[i].page); 84 | } 85 | } 86 | res.json(pages); 87 | }); 88 | }); 89 | 90 | app.get('/rest/logs/details/:id/:group', function(req, res) { 91 | var search = {"_id": req.params.id}, 92 | logJSON; 93 | collection.find(search).toArray(function (err, logs) { 94 | logJSON = logs[0]; 95 | if (req.params.group === 't') { 96 | var search = generateSearchObject({"IP": logJSON.IP, "type": logJSON.type, "message": logJSON.message}, ["IP", "type", "message"]); 97 | collection.find(search).toArray(function(err, q) { 98 | logJSON.quantity = q.length; 99 | res.json(logJSON); 100 | }); 101 | } else { 102 | res.json(logJSON); 103 | } 104 | }); 105 | }); 106 | 107 | app.get('/rest/logs/:page', function (req, res) { 108 | var search = generateSearchObject(req.query, ["page", "IP", "type", "message", "_id"]); 109 | collection.find(search).toArray(function (err, logs) { 110 | var json = [], 111 | grouped = [], 112 | l, g, tmp, tmpComp, found, page; 113 | 114 | if (/^[0-9]+$/g.test(req.params.page)) { 115 | page = parseInt(req.params.page); 116 | logs.sort(function (a, b) { 117 | return b._id - a._id; 118 | }); 119 | if (req.query.group === '1') { 120 | for (l = 0; l < logs.length; l++) { 121 | tmp = logs[l]; 122 | found = false; 123 | for (g = 0; g < grouped.length; g++) { 124 | tmpComp = grouped[g]; 125 | if (tmp.type === tmpComp.type && JSON.stringify(tmp.message) === JSON.stringify(tmpComp.message) && tmp.trace === tmpComp.trace && tmp.page === tmpComp.page) { 126 | found = true; 127 | grouped[g].count++; 128 | } 129 | } 130 | if (!found) { 131 | tmp.count = 1; 132 | grouped.push(tmp); 133 | } 134 | } 135 | logs = grouped; 136 | } 137 | if (logs.length > page * LOGS_PER_PAGE) { 138 | json = logs.slice(page * LOGS_PER_PAGE, (page * LOGS_PER_PAGE) + LOGS_PER_PAGE); 139 | } 140 | } else { 141 | return sendError("URL parameter expected a number, got: " + req.params.page, res); 142 | } 143 | json = { 144 | logs: json, 145 | max: Math.ceil(logs.length / LOGS_PER_PAGE) - 1 146 | }; 147 | res.json(json); 148 | }); 149 | }); 150 | } -------------------------------------------------------------------------------- /server/dev_public/js/LogsRoute.js: -------------------------------------------------------------------------------- 1 | var LogsRoute = function() { 2 | this.expanded = localStorage.getItem("filterExpanded") || false; 3 | this.currentPage = parseInt(localStorage.getItem("currentPage") || 0); 4 | if (typeof this.expanded === 'string') { 5 | this.expanded = (this.expanded === 'true'); 6 | } 7 | this.filterBar = $('.filter-bar'); 8 | this.toggle = $('.filter-toggle'); 9 | this.filterBar.height(0); 10 | if (this.expanded) { 11 | this.filterBar.css("height", "auto"); 12 | this.toggle.addClass('up'); 13 | } 14 | 15 | this.toggle.closest('.panel-heading').unbind().click($.proxy(function(e) { 16 | var toggle = $(e.currentTarget).find('.filter-toggle'), 17 | h,t; 18 | toggle.toggleClass('up'); 19 | if (this.expanded) { 20 | this.filterBar.height(this.filterBar.height()); 21 | t = document.clientHeight; 22 | this.filterBar.height(0); 23 | } else { 24 | h = this.filterBar.css('height', 'auto').height(); 25 | this.filterBar.height(0); 26 | this.filterBar.height(h); 27 | } 28 | this.expanded = !this.expanded; 29 | localStorage.setItem("filterExpanded", this.expanded); 30 | }, this)); 31 | }; 32 | LogsRoute.prototype.init = function() { 33 | var self = this; 34 | this.loadState = 0; 35 | this.Loader = new DataLoader(); 36 | this.Loader.fetchPageList(function(data) { 37 | self.generatePageList(data); 38 | self.loadState++; 39 | self.done(); 40 | }); 41 | this.updateFilter(); 42 | this.changePage(this.currentPage); 43 | }; 44 | LogsRoute.prototype.initFilterListeners = function() { 45 | var links = { 46 | type: $('#errorType'), 47 | message: null, 48 | page: $('#errorPage'), 49 | ip: null, 50 | id: null, 51 | group: null 52 | }, 53 | self = this; 54 | for (var key in links) { 55 | if (links.hasOwnProperty(key) && links[key] !== null) { 56 | (function() { 57 | var attr = key; 58 | links[attr].unbind('change').change($.proxy(function (e) { 59 | var sel = $(e.currentTarget); 60 | this.filter[attr] = (sel.val() === '*' ? null : sel.val()); 61 | this.updateFilter(); 62 | this.changePage(0); 63 | }, self)).val(self.filter[attr] || '*'); 64 | })(); // jshint ignore:line 65 | } 66 | } 67 | $('#autoGrouping').unbind('change').change($.proxy(function(e) { 68 | var check = $(e.currentTarget); 69 | this.filter.group = (check.is(':checked') ? '1' : '0'); 70 | this.updateFilter(); 71 | this.changePage(0); 72 | }, this)).prop('checked', (this.filter.group === '1')); 73 | $('#messageRegEx').unbind().keydown(function(e) { 74 | if (e.which === 13) { 75 | $(this).blur(); 76 | } 77 | }).change($.proxy(function(e) { 78 | var input = $(e.currentTarget); 79 | this.filter.message = (input.val() === '' ? null : input.val()); 80 | this.updateFilter(); 81 | this.changePage(0); 82 | }, this)).val(this.filter.message); 83 | $('.clear-filter').unbind().click($.proxy(function() { 84 | delete this.filter; 85 | localStorage.removeItem("filterConf"); 86 | this.updateFilter(); 87 | this.changePage(0); 88 | }, this)); 89 | }; 90 | LogsRoute.prototype.updateFilter = function() { 91 | this.filter = this.filter || (localStorage.getItem("filterConf") || {type: null, message: null, page: null, ip: null, id: null, group: null}); 92 | if (typeof this.filter !== 'object') { 93 | this.filter = JSON.parse(this.filter); 94 | } 95 | localStorage.setItem("filterConf", JSON.stringify(this.filter)); 96 | this.Loader.setFilter(this.filter.type, this.filter.message, this.filter.page, this.filter.ip, this.filter.id, this.filter.group); 97 | this.initFilterListeners(); 98 | }; 99 | LogsRoute.prototype.changePage = function(page) { 100 | var self = this; 101 | this.currentPage = page; 102 | localStorage.setItem("currentPage", this.currentPage); 103 | this.Loader.fetchPage(this.currentPage, function(data) { 104 | self.renderPage(data); 105 | self.loadState++; 106 | self.done(); 107 | }); 108 | }; 109 | LogsRoute.prototype.renderPage = function(data) { 110 | var logs = data.logs, 111 | table = $('#logTable'); 112 | 113 | this.renderPagination(data.max); 114 | 115 | table.find('tr:not(:eq(0))').remove(); 116 | for (var i = 0; i < logs.length; i++) { 117 | table.append('' + logs[i]._id + '' + logs[i].getNiceType() + '' + logs[i].message + '' + logs[i].count + '' + logs[i].getDate() + ''); 118 | } 119 | if (this.filter.group !== '1') { 120 | table.find('tr').each(function() { 121 | $(this).find('td:eq(3)').css('display', 'none'); 122 | }); 123 | table.find('tr:eq(0) th:eq(3)').css('display', 'none'); 124 | table.find('tr:eq(0) th:eq(0)').css('display', 'table-cell'); 125 | } else { 126 | table.find('tr').each(function() { 127 | $(this).find('td:eq(0)').css('display', 'none'); 128 | }); 129 | table.find('tr:eq(0) th:eq(0)').css('display', 'none'); 130 | table.find('tr:eq(0) th:eq(3)').css('display', 'table-cell'); 131 | } 132 | console.info("Received " + logs.length + " logs with a max page value of " + data.max); 133 | window.Router.listenForRoutes(); 134 | }; 135 | LogsRoute.prototype.renderPagination = function(maxPage) { 136 | var pagesToRender = [], 137 | PAGES_EACH_WAY = 2, 138 | pagination = $('.pagination'), 139 | tmp; 140 | 141 | for (var direction = -1; direction <= 0; direction++) { 142 | for (var inc = this.currentPage + (direction * PAGES_EACH_WAY); inc <= this.currentPage + ((direction + 1) * PAGES_EACH_WAY) + direction; inc++) { 143 | if (inc >= 0 && inc <= maxPage) { 144 | pagesToRender.push(inc); 145 | } 146 | } 147 | } 148 | console.info("Rendering pagination buttons from " + (pagesToRender[0] + 1) + " to " + (pagesToRender[pagesToRender.length - 1] + 1)); 149 | if (pagesToRender[0] !== 0) { 150 | if (pagesToRender[0] !== 1) { 151 | pagesToRender = ['...'].concat(pagesToRender); 152 | } 153 | pagesToRender = [0].concat(pagesToRender); 154 | } 155 | if (pagesToRender[pagesToRender.length - 1] !== maxPage) { 156 | if (pagesToRender[pagesToRender.length - 1] !== maxPage - 1) { 157 | pagesToRender = pagesToRender.concat(['...']); 158 | } 159 | pagesToRender = pagesToRender.concat([maxPage]); 160 | } 161 | if (maxPage === -1) { 162 | pagesToRender = ['No Logs Found']; 163 | } 164 | pagination.html(''); 165 | for (var i = 0; i < pagesToRender.length; i++) { 166 | tmp = $('' + (pagesToRender[i] + 1) + ''); 167 | if (typeof pagesToRender[i] === 'string') { 168 | tmp.addClass('disabled'); 169 | tmp.text(pagesToRender[i]); 170 | } 171 | if (pagesToRender[i] === this.currentPage) { 172 | tmp.addClass('active'); 173 | } 174 | pagination.append(tmp); 175 | } 176 | pagination.find('.btn').click($.proxy(function(e) { 177 | var newPage = parseInt($(e.currentTarget).data('paginate')); 178 | if (newPage !== this.currentPage) { 179 | this.changePage(newPage); 180 | } 181 | }, this)); 182 | }; 183 | LogsRoute.prototype.done = function() { 184 | if (this.loadState === 2) { 185 | this.onReady(); 186 | } 187 | }; 188 | LogsRoute.prototype.generatePageList = function(data) { 189 | var sel = $('#errorPage'); 190 | sel.find('option:not(:eq(0))').remove(); 191 | for (var i = 0; i < data.length; i++) { 192 | sel.append(""); 193 | } 194 | }; -------------------------------------------------------------------------------- /server/views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Open Log 6 | 7 | 8 | 9 | 10 | 11 | 27 |
28 |
29 |
30 |

Welcome to OpenLog

31 |

Below you can see some pretty statistics for your instance of OpenLog, if you click that Logs button you can start looking at all those errors.

32 |

View Logs

33 |
34 |
35 |
36 |
37 |
38 |

Total Logs

39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |

Info Logs

47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |

Warning Logs

55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |

Error logs

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |

Logging History

73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |

High Frequency Pages

83 |
84 |
85 | 86 | 87 | 88 | 89 | 90 |
PageError Frequency
91 |
92 |
93 |
94 |
95 |
96 |
97 |

Log Viewer

98 |
99 |
100 |

101 | Log Filters: 102 | 103 |

104 |
105 |
106 |
107 |
108 |
109 | 110 | 116 |
117 |
118 | 119 | 122 |
123 |
124 | 125 |
126 | 129 |
130 |
131 |
132 | 133 | 134 |
135 |
136 | Clear Filter 137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |

Logs

145 |
146 |
147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 |
IDTypeMessageCountReported
156 |
157 |
158 | 159 |
160 |
161 |

BackLog Details

162 |
163 |
164 |

Logs Details for Log #

165 |

Type:

166 |

Timestamp:

167 |

Page:

168 |
169 |

Occurrences: This error or similar errors have occurred times

170 |
171 |

Message:

172 |

Stack Trace:

173 |

174 |             
175 |
176 |
177 | 193 | 194 | 195 | 196 | 197 | -------------------------------------------------------------------------------- /server/dev_public/lib/js/6_morris.min.js: -------------------------------------------------------------------------------- 1 | /* @license 2 | morris.js v0.5.0 3 | Copyright 2014 Olly Smith All rights reserved. 4 | Licensed under the BSD-2-Clause License. 5 | */ 6 | (function(){var a,b,c,d,e=[].slice,f=function(a,b){return function(){return a.apply(b,arguments)}},g={}.hasOwnProperty,h=function(a,b){function c(){this.constructor=a}for(var d in b)g.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},i=[].indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(b in this&&this[b]===a)return b;return-1};b=window.Morris={},a=jQuery,b.EventEmitter=function(){function a(){}return a.prototype.on=function(a,b){return null==this.handlers&&(this.handlers={}),null==this.handlers[a]&&(this.handlers[a]=[]),this.handlers[a].push(b),this},a.prototype.fire=function(){var a,b,c,d,f,g,h;if(c=arguments[0],a=2<=arguments.length?e.call(arguments,1):[],null!=this.handlers&&null!=this.handlers[c]){for(g=this.handlers[c],h=[],d=0,f=g.length;f>d;d++)b=g[d],h.push(b.apply(null,a));return h}},a}(),b.commas=function(a){var b,c,d,e;return null!=a?(d=0>a?"-":"",b=Math.abs(a),c=Math.floor(b).toFixed(0),d+=c.replace(/(?=(?:\d{3})+$)(?!^)/g,","),e=b.toString(),e.length>c.length&&(d+=e.slice(c.length)),d):"-"},b.pad2=function(a){return(10>a?"0":"")+a},b.Grid=function(c){function d(b){this.resizeHandler=f(this.resizeHandler,this);var c=this;if(this.el="string"==typeof b.element?a(document.getElementById(b.element)):a(b.element),null==this.el||0===this.el.length)throw new Error("Graph container element not found");"static"===this.el.css("position")&&this.el.css("position","relative"),this.options=a.extend({},this.gridDefaults,this.defaults||{},b),"string"==typeof this.options.units&&(this.options.postUnits=b.units),this.raphael=new Raphael(this.el[0]),this.elementWidth=null,this.elementHeight=null,this.dirty=!1,this.selectFrom=null,this.init&&this.init(),this.setData(this.options.data),this.el.bind("mousemove",function(a){var b,d,e,f,g;return d=c.el.offset(),g=a.pageX-d.left,c.selectFrom?(b=c.data[c.hitTest(Math.min(g,c.selectFrom))]._x,e=c.data[c.hitTest(Math.max(g,c.selectFrom))]._x,f=e-b,c.selectionRect.attr({x:b,width:f})):c.fire("hovermove",g,a.pageY-d.top)}),this.el.bind("mouseleave",function(){return c.selectFrom&&(c.selectionRect.hide(),c.selectFrom=null),c.fire("hoverout")}),this.el.bind("touchstart touchmove touchend",function(a){var b,d;return d=a.originalEvent.touches[0]||a.originalEvent.changedTouches[0],b=c.el.offset(),c.fire("hovermove",d.pageX-b.left,d.pageY-b.top)}),this.el.bind("click",function(a){var b;return b=c.el.offset(),c.fire("gridclick",a.pageX-b.left,a.pageY-b.top)}),this.options.rangeSelect&&(this.selectionRect=this.raphael.rect(0,0,0,this.el.innerHeight()).attr({fill:this.options.rangeSelectColor,stroke:!1}).toBack().hide(),this.el.bind("mousedown",function(a){var b;return b=c.el.offset(),c.startRange(a.pageX-b.left)}),this.el.bind("mouseup",function(a){var b;return b=c.el.offset(),c.endRange(a.pageX-b.left),c.fire("hovermove",a.pageX-b.left,a.pageY-b.top)})),this.options.resize&&a(window).bind("resize",function(){return null!=c.timeoutId&&window.clearTimeout(c.timeoutId),c.timeoutId=window.setTimeout(c.resizeHandler,100)}),this.el.css("-webkit-tap-highlight-color","rgba(0,0,0,0)"),this.postInit&&this.postInit()}return h(d,c),d.prototype.gridDefaults={dateFormat:null,axes:!0,grid:!0,gridLineColor:"#aaa",gridStrokeWidth:.5,gridTextColor:"#888",gridTextSize:12,gridTextFamily:"sans-serif",gridTextWeight:"normal",hideHover:!1,yLabelFormat:null,xLabelAngle:0,numLines:5,padding:25,parseTime:!0,postUnits:"",preUnits:"",ymax:"auto",ymin:"auto 0",goals:[],goalStrokeWidth:1,goalLineColors:["#666633","#999966","#cc6666","#663333"],events:[],eventStrokeWidth:1,eventLineColors:["#005a04","#ccffbb","#3a5f0b","#005502"],rangeSelect:null,rangeSelectColor:"#eef",resize:!1},d.prototype.setData=function(a,c){var d,e,f,g,h,i,j,k,l,m,n,o,p,q,r;return null==c&&(c=!0),this.options.data=a,null==a||0===a.length?(this.data=[],this.raphael.clear(),null!=this.hover&&this.hover.hide(),void 0):(o=this.cumulative?0:null,p=this.cumulative?0:null,this.options.goals.length>0&&(h=Math.min.apply(Math,this.options.goals),g=Math.max.apply(Math,this.options.goals),p=null!=p?Math.min(p,h):h,o=null!=o?Math.max(o,g):g),this.data=function(){var c,d,g;for(g=[],f=c=0,d=a.length;d>c;f=++c)j=a[f],i={src:j},i.label=j[this.options.xkey],this.options.parseTime?(i.x=b.parseDate(i.label),this.options.dateFormat?i.label=this.options.dateFormat(i.x):"number"==typeof i.label&&(i.label=new Date(i.label).toString())):(i.x=f,this.options.xLabelFormat&&(i.label=this.options.xLabelFormat(i))),l=0,i.y=function(){var a,b,c,d;for(c=this.options.ykeys,d=[],e=a=0,b=c.length;b>a;e=++a)n=c[e],q=j[n],"string"==typeof q&&(q=parseFloat(q)),null!=q&&"number"!=typeof q&&(q=null),null!=q&&(this.cumulative?l+=q:null!=o?(o=Math.max(q,o),p=Math.min(q,p)):o=p=q),this.cumulative&&null!=l&&(o=Math.max(l,o),p=Math.min(l,p)),d.push(q);return d}.call(this),g.push(i);return g}.call(this),this.options.parseTime&&(this.data=this.data.sort(function(a,b){return(a.x>b.x)-(b.x>a.x)})),this.xmin=this.data[0].x,this.xmax=this.data[this.data.length-1].x,this.events=[],this.options.events.length>0&&(this.events=this.options.parseTime?function(){var a,c,e,f;for(e=this.options.events,f=[],a=0,c=e.length;c>a;a++)d=e[a],f.push(b.parseDate(d));return f}.call(this):this.options.events,this.xmax=Math.max(this.xmax,Math.max.apply(Math,this.events)),this.xmin=Math.min(this.xmin,Math.min.apply(Math,this.events))),this.xmin===this.xmax&&(this.xmin-=1,this.xmax+=1),this.ymin=this.yboundary("min",p),this.ymax=this.yboundary("max",o),this.ymin===this.ymax&&(p&&(this.ymin-=1),this.ymax+=1),((r=this.options.axes)===!0||"both"===r||"y"===r||this.options.grid===!0)&&(this.options.ymax===this.gridDefaults.ymax&&this.options.ymin===this.gridDefaults.ymin?(this.grid=this.autoGridLines(this.ymin,this.ymax,this.options.numLines),this.ymin=Math.min(this.ymin,this.grid[0]),this.ymax=Math.max(this.ymax,this.grid[this.grid.length-1])):(k=(this.ymax-this.ymin)/(this.options.numLines-1),this.grid=function(){var a,b,c,d;for(d=[],m=a=b=this.ymin,c=this.ymax;k>0?c>=a:a>=c;m=a+=k)d.push(m);return d}.call(this))),this.dirty=!0,c?this.redraw():void 0)},d.prototype.yboundary=function(a,b){var c,d;return c=this.options["y"+a],"string"==typeof c?"auto"===c.slice(0,4)?c.length>5?(d=parseInt(c.slice(5),10),null==b?d:Math[a](b,d)):null!=b?b:0:parseInt(c,10):c},d.prototype.autoGridLines=function(a,b,c){var d,e,f,g,h,i,j,k,l;return h=b-a,l=Math.floor(Math.log(h)/Math.log(10)),j=Math.pow(10,l),e=Math.floor(a/j)*j,d=Math.ceil(b/j)*j,i=(d-e)/(c-1),1===j&&i>1&&Math.ceil(i)!==i&&(i=Math.ceil(i),d=e+i*(c-1)),0>e&&d>0&&(e=Math.floor(a/i)*i,d=Math.ceil(b/i)*i),1>i?(g=Math.floor(Math.log(i)/Math.log(10)),f=function(){var a,b;for(b=[],k=a=e;i>0?d>=a:a>=d;k=a+=i)b.push(parseFloat(k.toFixed(1-g)));return b}()):f=function(){var a,b;for(b=[],k=a=e;i>0?d>=a:a>=d;k=a+=i)b.push(k);return b}(),f},d.prototype._calc=function(){var a,b,c,d,e,f,g,h;return e=this.el.width(),c=this.el.height(),(this.elementWidth!==e||this.elementHeight!==c||this.dirty)&&(this.elementWidth=e,this.elementHeight=c,this.dirty=!1,this.left=this.options.padding,this.right=this.elementWidth-this.options.padding,this.top=this.options.padding,this.bottom=this.elementHeight-this.options.padding,((g=this.options.axes)===!0||"both"===g||"y"===g)&&(f=function(){var a,c,d,e;for(d=this.grid,e=[],a=0,c=d.length;c>a;a++)b=d[a],e.push(this.measureText(this.yAxisFormat(b)).width);return e}.call(this),this.left+=Math.max.apply(Math,f)),((h=this.options.axes)===!0||"both"===h||"x"===h)&&(a=function(){var a,b,c;for(c=[],d=a=0,b=this.data.length;b>=0?b>a:a>b;d=b>=0?++a:--a)c.push(this.measureText(this.data[d].text,-this.options.xLabelAngle).height);return c}.call(this),this.bottom-=Math.max.apply(Math,a)),this.width=Math.max(1,this.right-this.left),this.height=Math.max(1,this.bottom-this.top),this.dx=this.width/(this.xmax-this.xmin),this.dy=this.height/(this.ymax-this.ymin),this.calc)?this.calc():void 0},d.prototype.transY=function(a){return this.bottom-(a-this.ymin)*this.dy},d.prototype.transX=function(a){return 1===this.data.length?(this.left+this.right)/2:this.left+(a-this.xmin)*this.dx},d.prototype.redraw=function(){return this.raphael.clear(),this._calc(),this.drawGrid(),this.drawGoals(),this.drawEvents(),this.draw?this.draw():void 0},d.prototype.measureText=function(a,b){var c,d;return null==b&&(b=0),d=this.raphael.text(100,100,a).attr("font-size",this.options.gridTextSize).attr("font-family",this.options.gridTextFamily).attr("font-weight",this.options.gridTextWeight).rotate(b),c=d.getBBox(),d.remove(),c},d.prototype.yAxisFormat=function(a){return this.yLabelFormat(a)},d.prototype.yLabelFormat=function(a){return"function"==typeof this.options.yLabelFormat?this.options.yLabelFormat(a):""+this.options.preUnits+b.commas(a)+this.options.postUnits},d.prototype.drawGrid=function(){var a,b,c,d,e,f,g,h;if(this.options.grid!==!1||(e=this.options.axes)===!0||"both"===e||"y"===e){for(f=this.grid,h=[],c=0,d=f.length;d>c;c++)a=f[c],b=this.transY(a),((g=this.options.axes)===!0||"both"===g||"y"===g)&&this.drawYAxisLabel(this.left-this.options.padding/2,b,this.yAxisFormat(a)),this.options.grid?h.push(this.drawGridLine("M"+this.left+","+b+"H"+(this.left+this.width))):h.push(void 0);return h}},d.prototype.drawGoals=function(){var a,b,c,d,e,f,g;for(f=this.options.goals,g=[],c=d=0,e=f.length;e>d;c=++d)b=f[c],a=this.options.goalLineColors[c%this.options.goalLineColors.length],g.push(this.drawGoal(b,a));return g},d.prototype.drawEvents=function(){var a,b,c,d,e,f,g;for(f=this.events,g=[],c=d=0,e=f.length;e>d;c=++d)b=f[c],a=this.options.eventLineColors[c%this.options.eventLineColors.length],g.push(this.drawEvent(b,a));return g},d.prototype.drawGoal=function(a,b){return this.raphael.path("M"+this.left+","+this.transY(a)+"H"+this.right).attr("stroke",b).attr("stroke-width",this.options.goalStrokeWidth)},d.prototype.drawEvent=function(a,b){return this.raphael.path("M"+this.transX(a)+","+this.bottom+"V"+this.top).attr("stroke",b).attr("stroke-width",this.options.eventStrokeWidth)},d.prototype.drawYAxisLabel=function(a,b,c){return this.raphael.text(a,b,c).attr("font-size",this.options.gridTextSize).attr("font-family",this.options.gridTextFamily).attr("font-weight",this.options.gridTextWeight).attr("fill",this.options.gridTextColor).attr("text-anchor","end")},d.prototype.drawGridLine=function(a){return this.raphael.path(a).attr("stroke",this.options.gridLineColor).attr("stroke-width",this.options.gridStrokeWidth)},d.prototype.startRange=function(a){return this.hover.hide(),this.selectFrom=a,this.selectionRect.attr({x:a,width:0}).show()},d.prototype.endRange=function(a){var b,c;return this.selectFrom?(c=Math.min(this.selectFrom,a),b=Math.max(this.selectFrom,a),this.options.rangeSelect.call(this.el,{start:this.data[this.hitTest(c)].x,end:this.data[this.hitTest(b)].x}),this.selectFrom=null):void 0},d.prototype.resizeHandler=function(){return this.timeoutId=null,this.raphael.setSize(this.el.width(),this.el.height()),this.redraw()},d}(b.EventEmitter),b.parseDate=function(a){var b,c,d,e,f,g,h,i,j,k,l;return"number"==typeof a?a:(c=a.match(/^(\d+) Q(\d)$/),e=a.match(/^(\d+)-(\d+)$/),f=a.match(/^(\d+)-(\d+)-(\d+)$/),h=a.match(/^(\d+) W(\d+)$/),i=a.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+)(Z|([+-])(\d\d):?(\d\d))?$/),j=a.match(/^(\d+)-(\d+)-(\d+)[ T](\d+):(\d+):(\d+(\.\d+)?)(Z|([+-])(\d\d):?(\d\d))?$/),c?new Date(parseInt(c[1],10),3*parseInt(c[2],10)-1,1).getTime():e?new Date(parseInt(e[1],10),parseInt(e[2],10)-1,1).getTime():f?new Date(parseInt(f[1],10),parseInt(f[2],10)-1,parseInt(f[3],10)).getTime():h?(k=new Date(parseInt(h[1],10),0,1),4!==k.getDay()&&k.setMonth(0,1+(4-k.getDay()+7)%7),k.getTime()+6048e5*parseInt(h[2],10)):i?i[6]?(g=0,"Z"!==i[6]&&(g=60*parseInt(i[8],10)+parseInt(i[9],10),"+"===i[7]&&(g=0-g)),Date.UTC(parseInt(i[1],10),parseInt(i[2],10)-1,parseInt(i[3],10),parseInt(i[4],10),parseInt(i[5],10)+g)):new Date(parseInt(i[1],10),parseInt(i[2],10)-1,parseInt(i[3],10),parseInt(i[4],10),parseInt(i[5],10)).getTime():j?(l=parseFloat(j[6]),b=Math.floor(l),d=Math.round(1e3*(l-b)),j[8]?(g=0,"Z"!==j[8]&&(g=60*parseInt(j[10],10)+parseInt(j[11],10),"+"===j[9]&&(g=0-g)),Date.UTC(parseInt(j[1],10),parseInt(j[2],10)-1,parseInt(j[3],10),parseInt(j[4],10),parseInt(j[5],10)+g,b,d)):new Date(parseInt(j[1],10),parseInt(j[2],10)-1,parseInt(j[3],10),parseInt(j[4],10),parseInt(j[5],10),b,d).getTime()):new Date(parseInt(a,10),0,1).getTime())},b.Hover=function(){function c(c){null==c&&(c={}),this.options=a.extend({},b.Hover.defaults,c),this.el=a("
"),this.el.hide(),this.options.parent.append(this.el)}return c.defaults={"class":"morris-hover morris-default-style"},c.prototype.update=function(a,b,c){return a?(this.html(a),this.show(),this.moveTo(b,c)):this.hide()},c.prototype.html=function(a){return this.el.html(a)},c.prototype.moveTo=function(a,b){var c,d,e,f,g,h;return g=this.options.parent.innerWidth(),f=this.options.parent.innerHeight(),d=this.el.outerWidth(),c=this.el.outerHeight(),e=Math.min(Math.max(0,a-d/2),g-d),null!=b?(h=b-c-10,0>h&&(h=b+10,h+c>f&&(h=f/2-c/2))):h=f/2-c/2,this.el.css({left:e+"px",top:parseInt(h)+"px"})},c.prototype.show=function(){return this.el.show()},c.prototype.hide=function(){return this.el.hide()},c}(),b.Line=function(a){function c(a){return this.hilight=f(this.hilight,this),this.onHoverOut=f(this.onHoverOut,this),this.onHoverMove=f(this.onHoverMove,this),this.onGridClick=f(this.onGridClick,this),this instanceof b.Line?(c.__super__.constructor.call(this,a),void 0):new b.Line(a)}return h(c,a),c.prototype.init=function(){return"always"!==this.options.hideHover?(this.hover=new b.Hover({parent:this.el}),this.on("hovermove",this.onHoverMove),this.on("hoverout",this.onHoverOut),this.on("gridclick",this.onGridClick)):void 0},c.prototype.defaults={lineWidth:3,pointSize:4,lineColors:["#0b62a4","#7A92A3","#4da74d","#afd8f8","#edc240","#cb4b4b","#9440ed"],pointStrokeWidths:[1],pointStrokeColors:["#ffffff"],pointFillColors:[],smooth:!0,xLabels:"auto",xLabelFormat:null,xLabelMargin:24,hideHover:!1},c.prototype.calc=function(){return this.calcPoints(),this.generatePaths()},c.prototype.calcPoints=function(){var a,b,c,d,e,f;for(e=this.data,f=[],c=0,d=e.length;d>c;c++)a=e[c],a._x=this.transX(a.x),a._y=function(){var c,d,e,f;for(e=a.y,f=[],c=0,d=e.length;d>c;c++)b=e[c],null!=b?f.push(this.transY(b)):f.push(b);return f}.call(this),f.push(a._ymax=Math.min.apply(Math,[this.bottom].concat(function(){var c,d,e,f;for(e=a._y,f=[],c=0,d=e.length;d>c;c++)b=e[c],null!=b&&f.push(b);return f}())));return f},c.prototype.hitTest=function(a){var b,c,d,e,f;if(0===this.data.length)return null;for(f=this.data.slice(1),b=d=0,e=f.length;e>d&&(c=f[b],!(a<(c._x+this.data[b]._x)/2));b=++d);return b},c.prototype.onGridClick=function(a,b){var c;return c=this.hitTest(a),this.fire("click",c,this.data[c].src,a,b)},c.prototype.onHoverMove=function(a){var b;return b=this.hitTest(a),this.displayHoverForRow(b)},c.prototype.onHoverOut=function(){return this.options.hideHover!==!1?this.displayHoverForRow(null):void 0},c.prototype.displayHoverForRow=function(a){var b;return null!=a?((b=this.hover).update.apply(b,this.hoverContentForRow(a)),this.hilight(a)):(this.hover.hide(),this.hilight())},c.prototype.hoverContentForRow=function(a){var b,c,d,e,f,g,h;for(d=this.data[a],b="
"+d.label+"
",h=d.y,c=f=0,g=h.length;g>f;c=++f)e=h[c],b+="
\n "+this.options.labels[c]+":\n "+this.yLabelFormat(e)+"\n
";return"function"==typeof this.options.hoverCallback&&(b=this.options.hoverCallback(a,this.options,b,d.src)),[b,d._x,d._ymax]},c.prototype.generatePaths=function(){var a,c,d,e;return this.paths=function(){var f,g,h,j;for(j=[],c=f=0,g=this.options.ykeys.length;g>=0?g>f:f>g;c=g>=0?++f:--f)e="boolean"==typeof this.options.smooth?this.options.smooth:(h=this.options.ykeys[c],i.call(this.options.smooth,h)>=0),a=function(){var a,b,e,f;for(e=this.data,f=[],a=0,b=e.length;b>a;a++)d=e[a],void 0!==d._y[c]&&f.push({x:d._x,y:d._y[c]});return f}.call(this),a.length>1?j.push(b.Line.createPath(a,e,this.bottom)):j.push(null);return j}.call(this)},c.prototype.draw=function(){var a;return((a=this.options.axes)===!0||"both"===a||"x"===a)&&this.drawXAxis(),this.drawSeries(),this.options.hideHover===!1?this.displayHoverForRow(this.data.length-1):void 0},c.prototype.drawXAxis=function(){var a,c,d,e,f,g,h,i,j,k,l=this;for(h=this.bottom+this.options.padding/2,f=null,e=null,a=function(a,b){var c,d,g,i,j;return c=l.drawXAxisLabel(l.transX(b),h,a),j=c.getBBox(),c.transform("r"+-l.options.xLabelAngle),d=c.getBBox(),c.transform("t0,"+d.height/2+"..."),0!==l.options.xLabelAngle&&(i=-.5*j.width*Math.cos(l.options.xLabelAngle*Math.PI/180),c.transform("t"+i+",0...")),d=c.getBBox(),(null==f||f>=d.x+d.width||null!=e&&e>=d.x)&&d.x>=0&&d.x+d.widtha;a++)g=c[a],d.push([g.label,g.x]);return d}.call(this),d.reverse(),k=[],i=0,j=d.length;j>i;i++)c=d[i],k.push(a(c[0],c[1]));return k},c.prototype.drawSeries=function(){var a,b,c,d,e,f;for(this.seriesPoints=[],a=b=d=this.options.ykeys.length-1;0>=d?0>=b:b>=0;a=0>=d?++b:--b)this._drawLineFor(a);for(f=[],a=c=e=this.options.ykeys.length-1;0>=e?0>=c:c>=0;a=0>=e?++c:--c)f.push(this._drawPointFor(a));return f},c.prototype._drawPointFor=function(a){var b,c,d,e,f,g;for(this.seriesPoints[a]=[],f=this.data,g=[],d=0,e=f.length;e>d;d++)c=f[d],b=null,null!=c._y[a]&&(b=this.drawLinePoint(c._x,c._y[a],this.colorFor(c,a,"point"),a)),g.push(this.seriesPoints[a].push(b));return g},c.prototype._drawLineFor=function(a){var b;return b=this.paths[a],null!==b?this.drawLinePath(b,this.colorFor(null,a,"line"),a):void 0},c.createPath=function(a,c,d){var e,f,g,h,i,j,k,l,m,n,o,p,q,r;for(k="",c&&(g=b.Line.gradients(a)),l={y:null},h=q=0,r=a.length;r>q;h=++q)e=a[h],null!=e.y&&(null!=l.y?c?(f=g[h],j=g[h-1],i=(e.x-l.x)/4,m=l.x+i,o=Math.min(d,l.y+i*j),n=e.x-i,p=Math.min(d,e.y-i*f),k+="C"+m+","+o+","+n+","+p+","+e.x+","+e.y):k+="L"+e.x+","+e.y:c&&null==g[h]||(k+="M"+e.x+","+e.y)),l=e;return k},c.gradients=function(a){var b,c,d,e,f,g,h,i;for(c=function(a,b){return(a.y-b.y)/(a.x-b.x)},i=[],d=g=0,h=a.length;h>g;d=++g)b=a[d],null!=b.y?(e=a[d+1]||{y:null},f=a[d-1]||{y:null},null!=f.y&&null!=e.y?i.push(c(f,e)):null!=f.y?i.push(c(f,b)):null!=e.y?i.push(c(b,e)):i.push(null)):i.push(null);return i},c.prototype.hilight=function(a){var b,c,d,e,f;if(null!==this.prevHilight&&this.prevHilight!==a)for(b=c=0,e=this.seriesPoints.length-1;e>=0?e>=c:c>=e;b=e>=0?++c:--c)this.seriesPoints[b][this.prevHilight]&&this.seriesPoints[b][this.prevHilight].animate(this.pointShrinkSeries(b));if(null!==a&&this.prevHilight!==a)for(b=d=0,f=this.seriesPoints.length-1;f>=0?f>=d:d>=f;b=f>=0?++d:--d)this.seriesPoints[b][a]&&this.seriesPoints[b][a].animate(this.pointGrowSeries(b));return this.prevHilight=a},c.prototype.colorFor=function(a,b,c){return"function"==typeof this.options.lineColors?this.options.lineColors.call(this,a,b,c):"point"===c?this.options.pointFillColors[b%this.options.pointFillColors.length]||this.options.lineColors[b%this.options.lineColors.length]:this.options.lineColors[b%this.options.lineColors.length]},c.prototype.drawXAxisLabel=function(a,b,c){return this.raphael.text(a,b,c).attr("font-size",this.options.gridTextSize).attr("font-family",this.options.gridTextFamily).attr("font-weight",this.options.gridTextWeight).attr("fill",this.options.gridTextColor)},c.prototype.drawLinePath=function(a,b,c){return this.raphael.path(a).attr("stroke",b).attr("stroke-width",this.lineWidthForSeries(c))},c.prototype.drawLinePoint=function(a,b,c,d){return this.raphael.circle(a,b,this.pointSizeForSeries(d)).attr("fill",c).attr("stroke-width",this.pointStrokeWidthForSeries(d)).attr("stroke",this.pointStrokeColorForSeries(d))},c.prototype.pointStrokeWidthForSeries=function(a){return this.options.pointStrokeWidths[a%this.options.pointStrokeWidths.length]},c.prototype.pointStrokeColorForSeries=function(a){return this.options.pointStrokeColors[a%this.options.pointStrokeColors.length]},c.prototype.lineWidthForSeries=function(a){return this.options.lineWidth instanceof Array?this.options.lineWidth[a%this.options.lineWidth.length]:this.options.lineWidth},c.prototype.pointSizeForSeries=function(a){return this.options.pointSize instanceof Array?this.options.pointSize[a%this.options.pointSize.length]:this.options.pointSize},c.prototype.pointGrowSeries=function(a){return Raphael.animation({r:this.pointSizeForSeries(a)+3},25,"linear")},c.prototype.pointShrinkSeries=function(a){return Raphael.animation({r:this.pointSizeForSeries(a)},25,"linear")},c}(b.Grid),b.labelSeries=function(c,d,e,f,g){var h,i,j,k,l,m,n,o,p,q,r;if(j=200*(d-c)/e,i=new Date(c),n=b.LABEL_SPECS[f],void 0===n)for(r=b.AUTO_LABEL_ORDER,p=0,q=r.length;q>p;p++)if(k=r[p],m=b.LABEL_SPECS[k],j>=m.span){n=m;break}for(void 0===n&&(n=b.LABEL_SPECS.second),g&&(n=a.extend({},n,{fmt:g})),h=n.start(i),l=[];(o=h.getTime())<=d;)o>=c&&l.push([n.fmt(h),o]),n.incr(h);return l},c=function(a){return{span:60*a*1e3,start:function(a){return new Date(a.getFullYear(),a.getMonth(),a.getDate(),a.getHours())},fmt:function(a){return""+b.pad2(a.getHours())+":"+b.pad2(a.getMinutes())},incr:function(b){return b.setUTCMinutes(b.getUTCMinutes()+a)}}},d=function(a){return{span:1e3*a,start:function(a){return new Date(a.getFullYear(),a.getMonth(),a.getDate(),a.getHours(),a.getMinutes())},fmt:function(a){return""+b.pad2(a.getHours())+":"+b.pad2(a.getMinutes())+":"+b.pad2(a.getSeconds())},incr:function(b){return b.setUTCSeconds(b.getUTCSeconds()+a)}}},b.LABEL_SPECS={decade:{span:1728e8,start:function(a){return new Date(a.getFullYear()-a.getFullYear()%10,0,1)},fmt:function(a){return""+a.getFullYear()},incr:function(a){return a.setFullYear(a.getFullYear()+10)}},year:{span:1728e7,start:function(a){return new Date(a.getFullYear(),0,1)},fmt:function(a){return""+a.getFullYear()},incr:function(a){return a.setFullYear(a.getFullYear()+1)}},month:{span:24192e5,start:function(a){return new Date(a.getFullYear(),a.getMonth(),1)},fmt:function(a){return""+a.getFullYear()+"-"+b.pad2(a.getMonth()+1)},incr:function(a){return a.setMonth(a.getMonth()+1)}},week:{span:6048e5,start:function(a){return new Date(a.getFullYear(),a.getMonth(),a.getDate())},fmt:function(a){return""+a.getFullYear()+"-"+b.pad2(a.getMonth()+1)+"-"+b.pad2(a.getDate())},incr:function(a){return a.setDate(a.getDate()+7)}},day:{span:864e5,start:function(a){return new Date(a.getFullYear(),a.getMonth(),a.getDate())},fmt:function(a){return""+a.getFullYear()+"-"+b.pad2(a.getMonth()+1)+"-"+b.pad2(a.getDate())},incr:function(a){return a.setDate(a.getDate()+1)}},hour:c(60),"30min":c(30),"15min":c(15),"10min":c(10),"5min":c(5),minute:c(1),"30sec":d(30),"15sec":d(15),"10sec":d(10),"5sec":d(5),second:d(1)},b.AUTO_LABEL_ORDER=["decade","year","month","week","day","hour","30min","15min","10min","5min","minute","30sec","15sec","10sec","5sec","second"],b.Area=function(c){function d(c){var f;return this instanceof b.Area?(f=a.extend({},e,c),this.cumulative=!f.behaveLikeLine,"auto"===f.fillOpacity&&(f.fillOpacity=f.behaveLikeLine?.8:1),d.__super__.constructor.call(this,f),void 0):new b.Area(c)}var e;return h(d,c),e={fillOpacity:"auto",behaveLikeLine:!1},d.prototype.calcPoints=function(){var a,b,c,d,e,f,g;for(f=this.data,g=[],d=0,e=f.length;e>d;d++)a=f[d],a._x=this.transX(a.x),b=0,a._y=function(){var d,e,f,g;for(f=a.y,g=[],d=0,e=f.length;e>d;d++)c=f[d],this.options.behaveLikeLine?g.push(this.transY(c)):(b+=c||0,g.push(this.transY(b)));return g}.call(this),g.push(a._ymax=Math.max.apply(Math,a._y));return g},d.prototype.drawSeries=function(){var a,b,c,d,e,f,g,h;for(this.seriesPoints=[],b=this.options.behaveLikeLine?function(){f=[];for(var a=0,b=this.options.ykeys.length-1;b>=0?b>=a:a>=b;b>=0?a++:a--)f.push(a);return f}.apply(this):function(){g=[];for(var a=e=this.options.ykeys.length-1;0>=e?0>=a:a>=0;0>=e?a++:a--)g.push(a);return g}.apply(this),h=[],c=0,d=b.length;d>c;c++)a=b[c],this._drawFillFor(a),this._drawLineFor(a),h.push(this._drawPointFor(a));return h},d.prototype._drawFillFor=function(a){var b;return b=this.paths[a],null!==b?(b+="L"+this.transX(this.xmax)+","+this.bottom+"L"+this.transX(this.xmin)+","+this.bottom+"Z",this.drawFilledPath(b,this.fillForSeries(a))):void 0},d.prototype.fillForSeries=function(a){var b;return b=Raphael.rgb2hsl(this.colorFor(this.data[a],a,"line")),Raphael.hsl(b.h,this.options.behaveLikeLine?.9*b.s:.75*b.s,Math.min(.98,this.options.behaveLikeLine?1.2*b.l:1.25*b.l))},d.prototype.drawFilledPath=function(a,b){return this.raphael.path(a).attr("fill",b).attr("fill-opacity",this.options.fillOpacity).attr("stroke","none")},d}(b.Line),b.Bar=function(c){function d(c){return this.onHoverOut=f(this.onHoverOut,this),this.onHoverMove=f(this.onHoverMove,this),this.onGridClick=f(this.onGridClick,this),this instanceof b.Bar?(d.__super__.constructor.call(this,a.extend({},c,{parseTime:!1})),void 0):new b.Bar(c)}return h(d,c),d.prototype.init=function(){return this.cumulative=this.options.stacked,"always"!==this.options.hideHover?(this.hover=new b.Hover({parent:this.el}),this.on("hovermove",this.onHoverMove),this.on("hoverout",this.onHoverOut),this.on("gridclick",this.onGridClick)):void 0},d.prototype.defaults={barSizeRatio:.75,barGap:3,barColors:["#0b62a4","#7a92a3","#4da74d","#afd8f8","#edc240","#cb4b4b","#9440ed"],barOpacity:1,barRadius:[0,0,0,0],xLabelMargin:50},d.prototype.calc=function(){var a;return this.calcBars(),this.options.hideHover===!1?(a=this.hover).update.apply(a,this.hoverContentForRow(this.data.length-1)):void 0},d.prototype.calcBars=function(){var a,b,c,d,e,f,g;for(f=this.data,g=[],a=d=0,e=f.length;e>d;a=++d)b=f[a],b._x=this.left+this.width*(a+.5)/this.data.length,g.push(b._y=function(){var a,d,e,f;for(e=b.y,f=[],a=0,d=e.length;d>a;a++)c=e[a],null!=c?f.push(this.transY(c)):f.push(null);return f}.call(this));return g},d.prototype.draw=function(){var a;return((a=this.options.axes)===!0||"both"===a||"x"===a)&&this.drawXAxis(),this.drawSeries()},d.prototype.drawXAxis=function(){var a,b,c,d,e,f,g,h,i,j,k,l,m;for(j=this.bottom+(this.options.xAxisLabelTopPadding||this.options.padding/2),g=null,f=null,m=[],a=k=0,l=this.data.length;l>=0?l>k:k>l;a=l>=0?++k:--k)h=this.data[this.data.length-1-a],b=this.drawXAxisLabel(h._x,j,h.label),i=b.getBBox(),b.transform("r"+-this.options.xLabelAngle),c=b.getBBox(),b.transform("t0,"+c.height/2+"..."),0!==this.options.xLabelAngle&&(e=-.5*i.width*Math.cos(this.options.xLabelAngle*Math.PI/180),b.transform("t"+e+",0...")),(null==g||g>=c.x+c.width||null!=f&&f>=c.x)&&c.x>=0&&c.x+c.width=0?this.transY(0):null,this.bars=function(){var h,l,p,q;for(p=this.data,q=[],d=h=0,l=p.length;l>h;d=++h)i=p[d],e=0,q.push(function(){var h,l,p,q;for(p=i._y,q=[],j=h=0,l=p.length;l>h;j=++h)n=p[j],null!==n?(o?(m=Math.min(n,o),b=Math.max(n,o)):(m=n,b=this.bottom),f=this.left+d*c+g,this.options.stacked||(f+=j*(a+this.options.barGap)),k=b-m,this.options.verticalGridCondition&&this.options.verticalGridCondition(i.x)&&this.drawBar(this.left+d*c,this.top,c,Math.abs(this.top-this.bottom),this.options.verticalGridColor,this.options.verticalGridOpacity,this.options.barRadius),this.options.stacked&&(m-=e),this.drawBar(f,m,a,k,this.colorFor(i,j,"bar"),this.options.barOpacity,this.options.barRadius),q.push(e+=k)):q.push(null);return q}.call(this));return q}.call(this)},d.prototype.colorFor=function(a,b,c){var d,e;return"function"==typeof this.options.barColors?(d={x:a.x,y:a.y[b],label:a.label},e={index:b,key:this.options.ykeys[b],label:this.options.labels[b]},this.options.barColors.call(this,d,e,c)):this.options.barColors[b%this.options.barColors.length]},d.prototype.hitTest=function(a){return 0===this.data.length?null:(a=Math.max(Math.min(a,this.right),this.left),Math.min(this.data.length-1,Math.floor((a-this.left)/(this.width/this.data.length))))},d.prototype.onGridClick=function(a,b){var c;return c=this.hitTest(a),this.fire("click",c,this.data[c].src,a,b)},d.prototype.onHoverMove=function(a){var b,c;return b=this.hitTest(a),(c=this.hover).update.apply(c,this.hoverContentForRow(b))},d.prototype.onHoverOut=function(){return this.options.hideHover!==!1?this.hover.hide():void 0},d.prototype.hoverContentForRow=function(a){var b,c,d,e,f,g,h,i;for(d=this.data[a],b="
"+d.label+"
",i=d.y,c=g=0,h=i.length;h>g;c=++g)f=i[c],b+="
\n "+this.options.labels[c]+":\n "+this.yLabelFormat(f)+"\n
";return"function"==typeof this.options.hoverCallback&&(b=this.options.hoverCallback(a,this.options,b,d.src)),e=this.left+(a+.5)*this.width/this.data.length,[b,e]},d.prototype.drawXAxisLabel=function(a,b,c){var d;return d=this.raphael.text(a,b,c).attr("font-size",this.options.gridTextSize).attr("font-family",this.options.gridTextFamily).attr("font-weight",this.options.gridTextWeight).attr("fill",this.options.gridTextColor)},d.prototype.drawBar=function(a,b,c,d,e,f,g){var h,i;return h=Math.max.apply(Math,g),i=0===h||h>d?this.raphael.rect(a,b,c,d):this.raphael.path(this.roundedRect(a,b,c,d,g)),i.attr("fill",e).attr("fill-opacity",f).attr("stroke","none")},d.prototype.roundedRect=function(a,b,c,d,e){return null==e&&(e=[0,0,0,0]),["M",a,e[0]+b,"Q",a,b,a+e[0],b,"L",a+c-e[1],b,"Q",a+c,b,a+c,b+e[1],"L",a+c,b+d-e[2],"Q",a+c,b+d,a+c-e[2],b+d,"L",a+e[3],b+d,"Q",a,b+d,a,b+d-e[3],"Z"]},d}(b.Grid),b.Donut=function(c){function d(c){this.resizeHandler=f(this.resizeHandler,this),this.select=f(this.select,this),this.click=f(this.click,this);var d=this;if(!(this instanceof b.Donut))return new b.Donut(c);if(this.options=a.extend({},this.defaults,c),this.el="string"==typeof c.element?a(document.getElementById(c.element)):a(c.element),null===this.el||0===this.el.length)throw new Error("Graph placeholder not found.");void 0!==c.data&&0!==c.data.length&&(this.raphael=new Raphael(this.el[0]),this.options.resize&&a(window).bind("resize",function(){return null!=d.timeoutId&&window.clearTimeout(d.timeoutId),d.timeoutId=window.setTimeout(d.resizeHandler,100)}),this.setData(c.data))}return h(d,c),d.prototype.defaults={colors:["#0B62A4","#3980B5","#679DC6","#95BBD7","#B0CCE1","#095791","#095085","#083E67","#052C48","#042135"],backgroundColor:"#FFFFFF",labelColor:"#000000",formatter:b.commas,resize:!1},d.prototype.redraw=function(){var a,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x;for(this.raphael.clear(),c=this.el.width()/2,d=this.el.height()/2,n=(Math.min(c,d)-10)/3,l=0,u=this.values,o=0,r=u.length;r>o;o++)m=u[o],l+=m;for(i=5/(2*n),a=1.9999*Math.PI-i*this.data.length,g=0,f=0,this.segments=[],v=this.values,e=p=0,s=v.length;s>p;e=++p)m=v[e],j=g+i+a*(m/l),k=new b.DonutSegment(c,d,2*n,n,g,j,this.data[e].color||this.options.colors[f%this.options.colors.length],this.options.backgroundColor,f,this.raphael),k.render(),this.segments.push(k),k.on("hover",this.select),k.on("click",this.click),g=j,f+=1;for(this.text1=this.drawEmptyDonutLabel(c,d-10,this.options.labelColor,15,800),this.text2=this.drawEmptyDonutLabel(c,d+10,this.options.labelColor,14),h=Math.max.apply(Math,this.values),f=0,w=this.values,x=[],q=0,t=w.length;t>q;q++){if(m=w[q],m===h){this.select(f); 7 | break}x.push(f+=1)}return x},d.prototype.setData=function(a){var b;return this.data=a,this.values=function(){var a,c,d,e;for(d=this.data,e=[],a=0,c=d.length;c>a;a++)b=d[a],e.push(parseFloat(b.value));return e}.call(this),this.redraw()},d.prototype.click=function(a){return this.fire("click",a,this.data[a])},d.prototype.select=function(a){var b,c,d,e,f,g;for(g=this.segments,e=0,f=g.length;f>e;e++)c=g[e],c.deselect();return d=this.segments[a],d.select(),b=this.data[a],this.setLabels(b.label,this.options.formatter(b.value,b))},d.prototype.setLabels=function(a,b){var c,d,e,f,g,h,i,j;return c=2*(Math.min(this.el.width()/2,this.el.height()/2)-10)/3,f=1.8*c,e=c/2,d=c/3,this.text1.attr({text:a,transform:""}),g=this.text1.getBBox(),h=Math.min(f/g.width,e/g.height),this.text1.attr({transform:"S"+h+","+h+","+(g.x+g.width/2)+","+(g.y+g.height)}),this.text2.attr({text:b,transform:""}),i=this.text2.getBBox(),j=Math.min(f/i.width,d/i.height),this.text2.attr({transform:"S"+j+","+j+","+(i.x+i.width/2)+","+i.y})},d.prototype.drawEmptyDonutLabel=function(a,b,c,d,e){var f;return f=this.raphael.text(a,b,"").attr("font-size",d).attr("fill",c),null!=e&&f.attr("font-weight",e),f},d.prototype.resizeHandler=function(){return this.timeoutId=null,this.raphael.setSize(this.el.width(),this.el.height()),this.redraw()},d}(b.EventEmitter),b.DonutSegment=function(a){function b(a,b,c,d,e,g,h,i,j,k){this.cx=a,this.cy=b,this.inner=c,this.outer=d,this.color=h,this.backgroundColor=i,this.index=j,this.raphael=k,this.deselect=f(this.deselect,this),this.select=f(this.select,this),this.sin_p0=Math.sin(e),this.cos_p0=Math.cos(e),this.sin_p1=Math.sin(g),this.cos_p1=Math.cos(g),this.is_long=g-e>Math.PI?1:0,this.path=this.calcSegment(this.inner+3,this.inner+this.outer-5),this.selectedPath=this.calcSegment(this.inner+3,this.inner+this.outer),this.hilight=this.calcArc(this.inner)}return h(b,a),b.prototype.calcArcPoints=function(a){return[this.cx+a*this.sin_p0,this.cy+a*this.cos_p0,this.cx+a*this.sin_p1,this.cy+a*this.cos_p1]},b.prototype.calcSegment=function(a,b){var c,d,e,f,g,h,i,j,k,l;return k=this.calcArcPoints(a),c=k[0],e=k[1],d=k[2],f=k[3],l=this.calcArcPoints(b),g=l[0],i=l[1],h=l[2],j=l[3],"M"+c+","+e+("A"+a+","+a+",0,"+this.is_long+",0,"+d+","+f)+("L"+h+","+j)+("A"+b+","+b+",0,"+this.is_long+",1,"+g+","+i)+"Z"},b.prototype.calcArc=function(a){var b,c,d,e,f;return f=this.calcArcPoints(a),b=f[0],d=f[1],c=f[2],e=f[3],"M"+b+","+d+("A"+a+","+a+",0,"+this.is_long+",0,"+c+","+e)},b.prototype.render=function(){var a=this;return this.arc=this.drawDonutArc(this.hilight,this.color),this.seg=this.drawDonutSegment(this.path,this.color,this.backgroundColor,function(){return a.fire("hover",a.index)},function(){return a.fire("click",a.index)})},b.prototype.drawDonutArc=function(a,b){return this.raphael.path(a).attr({stroke:b,"stroke-width":2,opacity:0})},b.prototype.drawDonutSegment=function(a,b,c,d,e){return this.raphael.path(a).attr({fill:b,stroke:c,"stroke-width":3}).hover(d).click(e)},b.prototype.select=function(){return this.selected?void 0:(this.seg.animate({path:this.selectedPath},150,"<>"),this.arc.animate({opacity:1},150,"<>"),this.selected=!0)},b.prototype.deselect=function(){return this.selected?(this.seg.animate({path:this.path},150,"<>"),this.arc.animate({opacity:0},150,"<>"),this.selected=!1):void 0},b}(b.EventEmitter)}).call(this); -------------------------------------------------------------------------------- /server/dev_public/lib/js/3_bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.4 (http://getbootstrap.com) 3 | * Copyright 2011-2015 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.4",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a(f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.4",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active"));a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.4",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));return a>this.$items.length-1||0>a?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.4",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=c(d),f={relatedTarget:this};e.hasClass("open")&&(e.trigger(b=a.Event("hide.bs.dropdown",f)),b.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger("hidden.bs.dropdown",f)))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.4",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport),this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c&&c.$tip&&c.$tip.is(":visible")?void(c.hoverState="in"):(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.options.container?a(this.options.container):this.$element.parent(),p=this.getPosition(o);h="bottom"==h&&k.bottom+m>p.bottom?"top":"top"==h&&k.top-mp.width?"left":"left"==h&&k.left-lg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type)})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||!/destroy|hide/.test(b))&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.4",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.4",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b=e[a]&&(void 0===e[a+1]||b .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.4",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return c>e?"top":!1;if("bottom"==this.affixed)return null!=c?e+this.unpin<=f.top?!1:"bottom":a-d>=e+g?!1:"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&c>=e?"top":null!=d&&i+j>=a-d?"bottom":!1},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=a(document.body).height();"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); -------------------------------------------------------------------------------- /test/test_log_storage: -------------------------------------------------------------------------------- 1 | {"k":"0000000078","o":"0000000373","v":"001"} 2 | {"_id":2,"_uid":2,"_dt":1434867081433,"_s":"eefb2929a46f389789e95003139a9915"} 3 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1434867079207,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":2}} 4 | {"k":"0000000078","o":"0000000393","v":"001"} 5 | {"_id":3,"_uid":3,"_dt":1434867081435,"_s":"4f976cf05b2bb61e44facdb84fc3d2fb"} 6 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1434867079214,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":3}} 7 | {"k":"0000000078","o":"0000000378","v":"001"} 8 | {"_id":4,"_uid":4,"_dt":1434867081435,"_s":"c40997049cc1414d01d23f3d00341ebc"} 9 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1434867079214,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":4}} 10 | {"k":"0000000078","o":"0000000373","v":"001"} 11 | {"_id":5,"_uid":5,"_dt":1434867089112,"_s":"654bc0f95bc5a5a8f19f564b0cf223d8"} 12 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1434867085015,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":5}} 13 | {"k":"0000000078","o":"0000000393","v":"001"} 14 | {"_id":6,"_uid":6,"_dt":1434867089112,"_s":"c4a5b6b7b557e818a73c946a8c68644e"} 15 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1434867085023,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":6}} 16 | {"k":"0000000078","o":"0000000378","v":"001"} 17 | {"_id":7,"_uid":7,"_dt":1434867089112,"_s":"efc87bffd3070213e087429f5d25c74f"} 18 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1434867085023,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":7}} 19 | {"k":"0000000078","o":"0000000373","v":"001"} 20 | {"_id":8,"_uid":8,"_dt":1434867089113,"_s":"a921964414b7a09675c854493efabf8e"} 21 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1434867085781,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":8}} 22 | {"k":"0000000078","o":"0000000393","v":"001"} 23 | {"_id":9,"_uid":9,"_dt":1434867089113,"_s":"ab7792dfc46cd77442fabac48e9e254c"} 24 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1434867085789,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":9}} 25 | {"k":"0000000080","o":"0000000379","v":"001"} 26 | {"_id":10,"_uid":10,"_dt":1434867089114,"_s":"2b1f38ecbb4fea197cb7350b8ceba5cf"} 27 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1434867085789,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":10}} 28 | {"k":"0000000080","o":"0000000374","v":"001"} 29 | {"_id":11,"_uid":11,"_dt":1434867089115,"_s":"d0182016540e0b15aad180141bf19cf6"} 30 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1434867086281,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":11}} 31 | {"k":"0000000080","o":"0000000394","v":"001"} 32 | {"_id":12,"_uid":12,"_dt":1434867089115,"_s":"da39b4f754efe4333e5d5b4525a85c96"} 33 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1434867086287,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":12}} 34 | {"k":"0000000080","o":"0000000379","v":"001"} 35 | {"_id":13,"_uid":13,"_dt":1434867089116,"_s":"87b5ffff65723330ab5a675d7a5e7aa4"} 36 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1434867086288,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":13}} 37 | {"k":"0000000080","o":"0000000374","v":"001"} 38 | {"_id":14,"_uid":14,"_dt":1434867089116,"_s":"08121aee8b25a48440dcd808d08e7be7"} 39 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1434867087006,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":14}} 40 | {"k":"0000000080","o":"0000000394","v":"001"} 41 | {"_id":15,"_uid":15,"_dt":1434867089116,"_s":"6a2723b9778ef3dc26285eddc5d6b759"} 42 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1434867087014,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":15}} 43 | {"k":"0000000080","o":"0000000379","v":"001"} 44 | {"_id":16,"_uid":16,"_dt":1434867089117,"_s":"5ef4c2f035ce301442d27a5c996ebfd3"} 45 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1434867087014,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":16}} 46 | {"k":"0000000080","o":"0000000374","v":"001"} 47 | {"_id":17,"_uid":17,"_dt":1434867089117,"_s":"d1105f0cc0502d7cb1f448c83a64c5a1"} 48 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1434867087938,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":17}} 49 | {"k":"0000000080","o":"0000000394","v":"001"} 50 | {"_id":18,"_uid":18,"_dt":1434867089118,"_s":"5d7be04d140c0d77d7079918cab81c36"} 51 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1434867087944,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":18}} 52 | {"k":"0000000080","o":"0000000379","v":"001"} 53 | {"_id":19,"_uid":19,"_dt":1434867089119,"_s":"954b8f728d5d8b37d5e9524cb983403a"} 54 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1434867087945,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":19}} 55 | {"k":"0000000080","o":"0000000374","v":"001"} 56 | {"_id":20,"_uid":20,"_dt":1434867141095,"_s":"2a10d6ffa3d0bdcf35eb75fd4a1792f2"} 57 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1434867138091,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":20}} 58 | {"k":"0000000080","o":"0000000394","v":"001"} 59 | {"_id":21,"_uid":21,"_dt":1434867141095,"_s":"fd6763fdb8107f115a3bfe89085bf465"} 60 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1434867138098,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":21}} 61 | {"k":"0000000080","o":"0000000379","v":"001"} 62 | {"_id":22,"_uid":22,"_dt":1434867141096,"_s":"5ae4d006dfb983cb12faa16335b92701"} 63 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1434867138098,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":22}} 64 | {"k":"0000000080","o":"0000000374","v":"001"} 65 | {"_id":23,"_uid":23,"_dt":1434867141096,"_s":"8763277e741c5dd8a0c8c9f7c2bb259e"} 66 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1434867138861,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":23}} 67 | {"k":"0000000080","o":"0000000394","v":"001"} 68 | {"_id":24,"_uid":24,"_dt":1434867141097,"_s":"1b0bc394a4d5f3720d1edb3dd2772436"} 69 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1434867138869,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":24}} 70 | {"k":"0000000080","o":"0000000379","v":"001"} 71 | {"_id":25,"_uid":25,"_dt":1434867141097,"_s":"4bec834cbafe6012083b598bbc353fb3"} 72 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1434867138870,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":25}} 73 | {"k":"0000000080","o":"0000000374","v":"001"} 74 | {"_id":26,"_uid":26,"_dt":1434867141097,"_s":"74c60c697a5dba450c8bbe5b93a4071c"} 75 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1434867139746,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":26}} 76 | {"k":"0000000080","o":"0000000394","v":"001"} 77 | {"_id":27,"_uid":27,"_dt":1434867141098,"_s":"7f766e6e172d2062fd587381bc86e04d"} 78 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1434867139753,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":27}} 79 | {"k":"0000000080","o":"0000000379","v":"001"} 80 | {"_id":28,"_uid":28,"_dt":1434867141098,"_s":"5b9c3da297cade64950d9a20e3c8a7fc"} 81 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1434867139753,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":28}} 82 | {"k":"0000000080","o":"0000000374","v":"001"} 83 | {"_id":29,"_uid":29,"_dt":1438654564345,"_s":"6dc0c9c40f4ba0c152712f56682babc2"} 84 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1724)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1434864928593,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":29}} 85 | {"k":"0000000080","o":"0000000394","v":"001"} 86 | {"_id":30,"_uid":30,"_dt":1438654564348,"_s":"410ffb7e8a80953748f34e6c33ff7b30"} 87 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1724)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1434864928594,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":30}} 88 | {"k":"0000000080","o":"0000000379","v":"001"} 89 | {"_id":31,"_uid":31,"_dt":1438654564349,"_s":"a30edde722cf363ec5950b8aab5213a8"} 90 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1724)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1434864928594,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":31}} 91 | {"k":"0000000080","o":"0000000374","v":"001"} 92 | {"_id":32,"_uid":32,"_dt":1438654564349,"_s":"8322bf21d23e3ae271c59f6299fcdfd5"} 93 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1438654562839,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":32}} 94 | {"k":"0000000080","o":"0000000394","v":"001"} 95 | {"_id":33,"_uid":33,"_dt":1438654564349,"_s":"aeecf3222c91aea0de2f1b6dc76c4504"} 96 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1438654562840,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":33}} 97 | {"k":"0000000080","o":"0000000379","v":"001"} 98 | {"_id":34,"_uid":34,"_dt":1438654564349,"_s":"ec9a3ec6c5c645af7ae8ee99ac275005"} 99 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1438654562840,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":34}} 100 | {"k":"0000000080","o":"0000000374","v":"001"} 101 | {"_id":35,"_uid":35,"_dt":1438654588368,"_s":"a993ee5ea274fb2f1b0cac88d3e19557"} 102 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1438654587365,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":35}} 103 | {"k":"0000000080","o":"0000000394","v":"001"} 104 | {"_id":36,"_uid":36,"_dt":1438654588368,"_s":"6620563e3d830d84c990893d9db49cae"} 105 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1438654587375,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":36}} 106 | {"k":"0000000080","o":"0000000379","v":"001"} 107 | {"_id":37,"_uid":37,"_dt":1438654588369,"_s":"3fd1db53f08a076b50dd17435de19605"} 108 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1673)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1438654587376,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":37}} 109 | {"k":"0000000080","o":"0000000374","v":"001"} 110 | {"_id":38,"_uid":38,"_dt":1438654922723,"_s":"cee1e8cca47146def76ee5e6894854a5"} 111 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1438654921416,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":38}} 112 | {"k":"0000000080","o":"0000000394","v":"001"} 113 | {"_id":39,"_uid":39,"_dt":1438654922724,"_s":"2f6fa700a81470f5c36a13cab9bed6df"} 114 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1438654921416,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":39}} 115 | {"k":"0000000080","o":"0000000379","v":"001"} 116 | {"_id":40,"_uid":40,"_dt":1438654922725,"_s":"274e9399bedc582bef7d06a012d4332e"} 117 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1438654921416,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":40}} 118 | {"k":"0000000080","o":"0000000374","v":"001"} 119 | {"_id":41,"_uid":41,"_dt":1438654948165,"_s":"374015b34946e3befb292d99160802a9"} 120 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1438654943459,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":41}} 121 | {"k":"0000000080","o":"0000000394","v":"001"} 122 | {"_id":42,"_uid":42,"_dt":1438654948165,"_s":"ecc8203e20c3ad1da8aa7ad78c1e9a8f"} 123 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1438654943459,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":42}} 124 | {"k":"0000000080","o":"0000000379","v":"001"} 125 | {"_id":43,"_uid":43,"_dt":1438654948166,"_s":"0fe8758e218370372d3f6f27bbc90a84"} 126 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1438654943459,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":43}} 127 | {"k":"0000000080","o":"0000000374","v":"001"} 128 | {"_id":44,"_uid":44,"_dt":1438654948167,"_s":"398b02256c4ff1e32dc4453ec2791e54"} 129 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1438654947172,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":44}} 130 | {"k":"0000000080","o":"0000000394","v":"001"} 131 | {"_id":45,"_uid":45,"_dt":1438654948169,"_s":"cff50a7f3f141cd0df21a323e6afd33d"} 132 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1438654947173,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":45}} 133 | {"k":"0000000080","o":"0000000379","v":"001"} 134 | {"_id":46,"_uid":46,"_dt":1438654948170,"_s":"fad3419a2efc9060d35f5ae4f4785de4"} 135 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1438654947174,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":46}} 136 | {"k":"0000000080","o":"0000000374","v":"001"} 137 | {"_id":47,"_uid":47,"_dt":1438654993631,"_s":"4dcb8c7bddb366da6dc99821e83ed8aa"} 138 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1438654974922,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":47}} 139 | {"k":"0000000080","o":"0000000394","v":"001"} 140 | {"_id":48,"_uid":48,"_dt":1438654993632,"_s":"38780b79440db07697c1d0b191808f83"} 141 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1438654974923,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":48}} 142 | {"k":"0000000080","o":"0000000379","v":"001"} 143 | {"_id":49,"_uid":49,"_dt":1438654993632,"_s":"4163b4fdc8fad0c515a1c4edef0f773f"} 144 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1438654974923,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":49}} 145 | {"k":"0000000080","o":"0000000374","v":"001"} 146 | {"_id":50,"_uid":50,"_dt":1438654993632,"_s":"909e1b982a2f72636c2899202b957ead"} 147 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1438654976117,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":50}} 148 | {"k":"0000000080","o":"0000000394","v":"001"} 149 | {"_id":51,"_uid":51,"_dt":1438654993633,"_s":"cd2482ab4227fbe417657616df77f689"} 150 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1438654976117,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":51}} 151 | {"k":"0000000080","o":"0000000379","v":"001"} 152 | {"_id":52,"_uid":52,"_dt":1438654993633,"_s":"605a350e6344140ea3beb573ccafbf33"} 153 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1438654976118,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":52}} 154 | {"k":"0000000080","o":"0000000374","v":"001"} 155 | {"_id":53,"_uid":53,"_dt":1438654993633,"_s":"4b586e0842fb0b41372203ec5752b596"} 156 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1438654976627,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":53}} 157 | {"k":"0000000080","o":"0000000394","v":"001"} 158 | {"_id":54,"_uid":54,"_dt":1438654993634,"_s":"9138b42e6aef6753dd5210a2b78d57c2"} 159 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1438654976633,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":54}} 160 | {"k":"0000000080","o":"0000000379","v":"001"} 161 | {"_id":55,"_uid":55,"_dt":1438654993635,"_s":"3a604edd5672022233369f8c56b92e9d"} 162 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1438654976633,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":55}} 163 | {"k":"0000000080","o":"0000000374","v":"001"} 164 | {"_id":56,"_uid":56,"_dt":1438654993635,"_s":"50d4988028cb41db12f11dc2039c55d4"} 165 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1438654981215,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":56}} 166 | {"k":"0000000080","o":"0000000394","v":"001"} 167 | {"_id":57,"_uid":57,"_dt":1438654993636,"_s":"a6bdef55f43092e15e99cfac15e081b8"} 168 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1438654981216,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":57}} 169 | {"k":"0000000080","o":"0000000379","v":"001"} 170 | {"_id":58,"_uid":58,"_dt":1438654993637,"_s":"7eaf84cbeb50313eca9f0844b99f0136"} 171 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1438654981216,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":58}} 172 | {"k":"0000000080","o":"0000000374","v":"001"} 173 | {"_id":59,"_uid":59,"_dt":1438654993637,"_s":"bf83d2e050d9e34659750531ef80a02b"} 174 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1438654985786,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":59}} 175 | {"k":"0000000080","o":"0000000394","v":"001"} 176 | {"_id":60,"_uid":60,"_dt":1438654993637,"_s":"63659f103204f60db834352113e00dc1"} 177 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1438654985787,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":60}} 178 | {"k":"0000000080","o":"0000000379","v":"001"} 179 | {"_id":61,"_uid":61,"_dt":1438654993637,"_s":"674e350b73067b5159f7fd924d9a529a"} 180 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1438654985787,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":61}} 181 | {"k":"0000000080","o":"0000000374","v":"001"} 182 | {"_id":62,"_uid":62,"_dt":1438654993638,"_s":"0718dd9ab89be785d964a0f4d72ddf1d"} 183 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1438654992633,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":62}} 184 | {"k":"0000000080","o":"0000000394","v":"001"} 185 | {"_id":63,"_uid":63,"_dt":1438654993638,"_s":"ec03dbfce019d348d4ad4920621502b2"} 186 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1438654992633,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":63}} 187 | {"k":"0000000080","o":"0000000379","v":"001"} 188 | {"_id":64,"_uid":64,"_dt":1438654993638,"_s":"ffa804ecc15b9c43b376bff92eb71760"} 189 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1438654992633,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":64}} 190 | {"k":"0000000080","o":"0000000374","v":"001"} 191 | {"_id":65,"_uid":65,"_dt":1438655708327,"_s":"8819b0a7c575c2b537c727c6017def2b"} 192 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1438655707023,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":65}} 193 | {"k":"0000000080","o":"0000000394","v":"001"} 194 | {"_id":66,"_uid":66,"_dt":1438655708327,"_s":"f06ca2e6ce9e74f2472897e11bfd5b3a"} 195 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1438655707023,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":66}} 196 | {"k":"0000000080","o":"0000000379","v":"001"} 197 | {"_id":67,"_uid":67,"_dt":1438655708329,"_s":"a623b3f4a8e5ed55d3ea1fdf023a41e6"} 198 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1760)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1438655707023,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":67}} 199 | {"k":"0000000080","o":"0000000374","v":"001"} 200 | {"_id":68,"_uid":68,"_dt":1441878736342,"_s":"79ec879a971c1766770aaba2bc373eab"} 201 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html:11:13","time":1441878734995,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":68}} 202 | {"k":"0000000080","o":"0000000394","v":"001"} 203 | {"_id":69,"_uid":69,"_dt":1441878736343,"_s":"6214e96d57cb509086fd77b695b188e9"} 204 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html:12:13","time":1441878734996,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":69}} 205 | {"k":"0000000080","o":"0000000379","v":"001"} 206 | {"_id":70,"_uid":70,"_dt":1441878736344,"_s":"c7ea3a0cbf8c783611275af1bd410426"} 207 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html:13:13","time":1441878734996,"page":"localhost:63342/OpenLog/demo.html","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":70}} 208 | {"k":"0000000080","o":"0000000392","v":"001"} 209 | {"_id":71,"_uid":71,"_dt":1441878740159,"_s":"7d0f29660e7fcdf7dcfd753976899ba2"} 210 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?new-page:11:13","time":1441878739157,"page":"localhost:63342/OpenLog/demo.html?new-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":71}} 211 | {"k":"0000000080","o":"0000000412","v":"001"} 212 | {"_id":72,"_uid":72,"_dt":1441878740159,"_s":"0b30e0e636ce5bf94760e7cbf372b26c"} 213 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?new-page:12:13","time":1441878739157,"page":"localhost:63342/OpenLog/demo.html?new-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":72}} 214 | {"k":"0000000080","o":"0000000397","v":"001"} 215 | {"_id":73,"_uid":73,"_dt":1441878740159,"_s":"8e97f099831fbb01a6ec876cc4e6ed7d"} 216 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?new-page:13:13","time":1441878739157,"page":"localhost:63342/OpenLog/demo.html?new-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":73}} 217 | {"k":"0000000080","o":"0000000392","v":"001"} 218 | {"_id":74,"_uid":74,"_dt":1441878741449,"_s":"0ddfa3f1ca3df8fceeec195287f0b3fc"} 219 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?new-page:11:13","time":1441878740448,"page":"localhost:63342/OpenLog/demo.html?new-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":74}} 220 | {"k":"0000000080","o":"0000000412","v":"001"} 221 | {"_id":75,"_uid":75,"_dt":1441878741449,"_s":"5b4042f3c29a2c6ea5a52355a9eaba9a"} 222 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?new-page:12:13","time":1441878740448,"page":"localhost:63342/OpenLog/demo.html?new-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":75}} 223 | {"k":"0000000080","o":"0000000397","v":"001"} 224 | {"_id":76,"_uid":76,"_dt":1441878741449,"_s":"ae6ad8fcc2f5633ca5d3f7c56932abee"} 225 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?new-page:13:13","time":1441878740448,"page":"localhost:63342/OpenLog/demo.html?new-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":76}} 226 | {"k":"0000000080","o":"0000000400","v":"001"} 227 | {"_id":77,"_uid":77,"_dt":1441878747116,"_s":"30cfd1edac1c8c711e5387c48209152c"} 228 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:11:13","time":1441878743810,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":77}} 229 | {"k":"0000000080","o":"0000000420","v":"001"} 230 | {"_id":78,"_uid":78,"_dt":1441878747116,"_s":"ac8c6d019d732b90213b50557543d1bb"} 231 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:12:13","time":1441878743810,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":78}} 232 | {"k":"0000000080","o":"0000000405","v":"001"} 233 | {"_id":79,"_uid":79,"_dt":1441878747116,"_s":"95da8b678e40f9adad3e97f1090af267"} 234 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:13:13","time":1441878743810,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":79}} 235 | {"k":"0000000080","o":"0000000400","v":"001"} 236 | {"_id":80,"_uid":80,"_dt":1441878747116,"_s":"5dd81f0b1aed706b3a447516b8c78aec"} 237 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:11:13","time":1441878744426,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":80}} 238 | {"k":"0000000080","o":"0000000420","v":"001"} 239 | {"_id":81,"_uid":81,"_dt":1441878747117,"_s":"caf825e6e9b6e771f8bf03ace631301f"} 240 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:12:13","time":1441878744426,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":81}} 241 | {"k":"0000000080","o":"0000000405","v":"001"} 242 | {"_id":82,"_uid":82,"_dt":1441878747117,"_s":"72b4f75e3c1a53a316031e587cb24df4"} 243 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:13:13","time":1441878744426,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":82}} 244 | {"k":"0000000080","o":"0000000400","v":"001"} 245 | {"_id":83,"_uid":83,"_dt":1441878747117,"_s":"405d060af0d07ced76f2a72b42aa5525"} 246 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:11:13","time":1441878745005,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":83}} 247 | {"k":"0000000080","o":"0000000420","v":"001"} 248 | {"_id":84,"_uid":84,"_dt":1441878747118,"_s":"f7ff8ba7f73474175963ce571c5ebd46"} 249 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:12:13","time":1441878745006,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":84}} 250 | {"k":"0000000080","o":"0000000405","v":"001"} 251 | {"_id":85,"_uid":85,"_dt":1441878747118,"_s":"e8354ca6200503d2e771b163d4939679"} 252 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:13:13","time":1441878745006,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":85}} 253 | {"k":"0000000080","o":"0000000400","v":"001"} 254 | {"_id":86,"_uid":86,"_dt":1441878747119,"_s":"39322b93762e23450cb5a19deb5b86dd"} 255 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:11:13","time":1441878745572,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":86}} 256 | {"k":"0000000080","o":"0000000420","v":"001"} 257 | {"_id":87,"_uid":87,"_dt":1441878747119,"_s":"70a22934b91c1bb8a6a3d0f795c3ae5f"} 258 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:12:13","time":1441878745572,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":87}} 259 | {"k":"0000000080","o":"0000000405","v":"001"} 260 | {"_id":88,"_uid":88,"_dt":1441878747120,"_s":"81a4488571b6365641765716bc481d40"} 261 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:13:13","time":1441878745572,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":88}} 262 | {"k":"0000000080","o":"0000000400","v":"001"} 263 | {"_id":89,"_uid":89,"_dt":1441878747120,"_s":"89d17d7455a50662e4fc7fdff1a0910d"} 264 | {"type":"info","message":{"0":"This page was loaded"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as info] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:11:13","time":1441878746110,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":89}} 265 | {"k":"0000000080","o":"0000000420","v":"001"} 266 | {"_id":90,"_uid":90,"_dt":1441878747120,"_s":"baa4daf11028b01c9964b5df5ca07fa4"} 267 | {"type":"warn","message":{"0":"Was this page actually loaded correctly?"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as warn] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:12:13","time":1441878746111,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":90}} 268 | {"k":"0000000080","o":"0000000405","v":"001"} 269 | {"_id":91,"_uid":91,"_dt":1441878747120,"_s":"bd7785ff2055ecc2e6d293479dead81f"} 270 | {"type":"error","message":{"0":"Oh darn, it didn't load"},"trace":"Error\n at Error (native)\n at Console.console.(anonymous function) [as error] (http://localhost:63342/OpenLog/dist/capture.min.js:1:1736)\n at http://localhost:63342/OpenLog/demo.html?another-page:13:13","time":1441878746111,"page":"localhost:63342/OpenLog/demo.html?another-page","IP":"127.0.0.1","_id":{"$wrap":"$oid","v":91}} 271 | --------------------------------------------------------------------------------