logster 2.4.0 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e0b7d537afb560db43baeed0d1de845c84df83b499fe6fd84f8a803133b9219d
4
- data.tar.gz: 36d7b21799023ce9af8005a115d60809ea606d5170ee4a908ad3764ed9a49a59
3
+ metadata.gz: 32d46ec6061a8b58d50146ab27c3185f3964680207f0a6ad783ad3122aa44d2a
4
+ data.tar.gz: abf94ecdefb382f60606e0d94cffa9dae77a64eda8f124f7a1c6c9295be688bd
5
5
  SHA512:
6
- metadata.gz: 865760766f7429c9610e66042f6d463bf3423a7f73f07c78eec36ee815fa20883870f1300a234be886731b5da6716a7ef50d6ceecc14b190b01e2385ae32e71f
7
- data.tar.gz: 3f2ef09d8b21224b1d90af7a1775f8fbcbb7205e7b6315bba25e605d706c777c604361ec011b60a1814a8347eab7166c95e8f1324953564d27d8121303d60691
6
+ metadata.gz: b0a40b769c195f36fa14bc856efe6490653113b57f65b0b07875a648d1ffaa98f26343cbed2f6d688402ef83c63b2ad142e8d81624f25f043f4d0f84be0d8f30
7
+ data.tar.gz: 428f7b1e3577f16c65752ddeca5f8004858f204e97fdba496816df532308201fdd415e8edf2b081bcb3090dd3bc0f2cd59f6778561af3b5a16f6f4d6163320d1
@@ -1,5 +1,13 @@
1
1
  # CHANGELOG
2
2
 
3
+ - 2019-10-17: 2.4.1
4
+
5
+ - PERF: Debounce search field so it doesn't fire a search query at every keystroke.
6
+ - PERF: Disallow search terms that are fewer than 2 characters long.
7
+ - PERF: Bypass refresh cycle if previous cycle hasn't finished.
8
+ - PERF: Defer sending message envs to client until the user requests them.
9
+ - PERF: Cap message size to 60,000 bytes by default.
10
+
3
11
  - 2019-10-10: 2.4.0
4
12
 
5
13
  - FEATURE: Allow having retroactive affect when adding suppression patterns
data/README.md CHANGED
@@ -43,6 +43,8 @@ Logster can be configured using `Logster.config`:
43
43
  - `Logster.config.enable_js_error_reporting` : enable js error reporting from clients
44
44
  - `Logster.config.rate_limit_error_reporting` : controls automatic 1 minute rate limiting for JS error reporting.
45
45
  - `Logster.config.web_title` : `<title>` tag for logster error page.
46
+ - `Logster.config.enable_custom_patterns_via_ui` : enables a setting page that allows adding suppression patterns via the UI.
47
+ - `Logster.config.maximum_message_size_bytes` : specifiy a size in bytes that a message cannot exceed. Note this isn't 100% accurate, meaning a message may still grow above the limit, but it shouldn't grow by more tha, say, 2000 bytes.
46
48
 
47
49
  ### Tracking Error Rate
48
50
  Logster allows you to register a callback when the rate of errors has exceeded
@@ -1,8 +1,8 @@
1
1
  "use strict"
2
2
  define("client-app/app",["exports","client-app/resolver","ember-load-initializers","client-app/config/environment"],function(e,t,n,a){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
3
3
  var s=Ember.Application.extend({modulePrefix:a.default.modulePrefix,podModulePrefix:a.default.podModulePrefix,Resolver:t.default});(0,n.default)(s,a.default.modulePrefix)
4
- var r=s
5
- e.default=r}),define("client-app/components/actions-menu",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
4
+ var i=s
5
+ e.default=i}),define("client-app/components/actions-menu",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
6
6
  var t=Ember.Component.extend({showMenu:!1,tagName:"span",init:function(){this._super.apply(this,arguments),this.bindingFunction=this.bindingFunction.bind(this)},bindingFunction:function(e){var t=this.$()[0]
7
7
  Em.$.contains(t,e.target)||t===e.target||this.set("showMenu",!1)},bindDocument:Ember.observer("showMenu",function(){var e=Em.$(document)
8
8
  this.get("showMenu")?e.on("click",this.get("bindingFunction")):e.off("click",this.get("bindingFunction"))}),willDestroyElement:function(){this._super.apply(this,arguments),Em.$(document).off("click",this.get("bindingFunction"))},actions:{expandMenu:function(){this.toggleProperty("showMenu")},share:function(){this.share()}}})
@@ -15,20 +15,20 @@ this.set("current",this.get("current")+t)},bigJump:function(e){var t="back"===e?
15
15
  this.set("current",t)}}})
16
16
  e.default=a}),define("client-app/components/message-info",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
17
17
  var t=Ember.Component.extend({buttons:Ember.computed("currentMessage.{canSolve,protected}",function(){var e=this.get("currentMessage.canSolve"),t=this.get("currentMessage.protected"),n=[]
18
- return!t&&e&&n.push({klass:"solve",action:"solve",icon:"check-square-o",label:"Solve",danger:!0}),t?n.push({klass:"unprotect",action:"unprotect",icon:"unlock",label:"Unprotect"}):n.push({klass:"remove",action:"remove",icon:"trash-o",label:"Remove",danger:!0},{klass:"protect",action:"protect",icon:"lock",label:"Protect"}),n}),actions:{protect:function(){this.get("currentMessage").protect()},unprotect:function(){this.get("currentMessage").unprotect()},remove:function(){this.removeMessage(this.get("currentMessage"))},solve:function(){this.solveMessage(this.get("currentMessage"))},share:function(){window.location.pathname=this.get("currentMessage.shareUrl")}}})
18
+ return!t&&e&&n.push({klass:"solve",action:"solve",icon:"check-square-o",label:"Solve",danger:!0}),t?n.push({klass:"unprotect",action:"unprotect",icon:"unlock",label:"Unprotect"}):n.push({klass:"remove",action:"remove",icon:"trash-o",label:"Remove",danger:!0},{klass:"protect",action:"protect",icon:"lock",label:"Protect"}),n}),actions:{tabChanged:function(e){this.onTabChange&&this.onTabChange(e)},protect:function(){this.get("currentMessage").protect()},unprotect:function(){this.get("currentMessage").unprotect()},remove:function(){this.removeMessage(this.get("currentMessage"))},solve:function(){this.solveMessage(this.get("currentMessage"))},share:function(){window.location.pathname=this.get("currentMessage.shareUrl")}}})
19
19
  e.default=t}),define("client-app/components/message-row",["exports"],function(e){var t,n
20
20
  Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
21
- var a=Ember.Component.extend({tagName:"div",classNameBindings:["model.rowClass",":message-row","model.selected:selected"],click:function(){this.selectedMessage(this.get("model"))},willInsertElement:function(){if(!t){var e=Em.$("#top-panel"),a=e.scrollTop(),s=e.height(),r=e[0].scrollHeight
22
- n=r-20<s+a,t=!0}},didInsertElement:function(){var e=Em.$("#top-panel")
21
+ var a=Ember.Component.extend({tagName:"div",classNameBindings:["model.rowClass",":message-row","model.selected:selected"],click:function(){this.selectedMessage(this.get("model"))},willInsertElement:function(){if(!t){var e=Em.$("#top-panel"),a=e.scrollTop(),s=e.height(),i=e[0].scrollHeight
22
+ n=i-20<s+a,t=!0}},didInsertElement:function(){var e=Em.$("#top-panel")
23
23
  Em.run.next(function(){t=!1,n&&(n=!1,e.scrollTop(e[0].scrollHeight-e.height()))})}})
24
24
  e.default=a}),define("client-app/components/panel-resizer",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
25
25
  var t=["touchmove","mousemove"],n=["touchend","mouseup"],a=["touchstart","mousedown"],s=Ember.Component.extend({classNames:["divider"],divideView:function(e,t){var n=t||Em.$(window),a=n.height(),s=n.height()-e
26
26
  e<100||e+170>a||(this.divider.css("bottom",s-5),this.events.trigger("panelResized",s))},didInsertElement:function(){var e=this
27
27
  this.divider=Em.$(".divider")
28
- var s=Em.$(window),r=!1,i=function(t){r&&e.divideView(t.clientY||t.touches&&t.touches[0]&&t.touches[0].clientY,s)},o=function a(){Em.$("#overlay").remove(),r=!1,localStorage&&(localStorage.logster_divider_bottom=parseInt(e.divider.css("bottom"),10))
28
+ var s=Em.$(window),i=!1,r=function(t){i&&e.divideView(t.clientY||t.touches&&t.touches[0]&&t.touches[0].clientY,s)},o=function a(){Em.$("#overlay").remove(),i=!1,localStorage&&(localStorage.logster_divider_bottom=parseInt(e.divider.css("bottom"),10))
29
29
  var s=Em.$(document)
30
- t.forEach(function(e){return s.unbind(e,i)}),n.forEach(function(e){return s.unbind(e,a)})}
31
- this.divider.on(a.join(" "),function(e){e.preventDefault(),Em.$("<div id='overlay'></div>").appendTo(Em.$("body")),r=!0,Em.$(document).on(t.join(" "),_.throttle(i,25)).on(n.join(" "),o)}),Em.run.next(function(){var t=localStorage&&localStorage.logster_divider_bottom||300,n=s.height()-parseInt(t,10)
30
+ t.forEach(function(e){return s.unbind(e,r)}),n.forEach(function(e){return s.unbind(e,a)})}
31
+ this.divider.on(a.join(" "),function(e){e.preventDefault(),Em.$("<div id='overlay'></div>").appendTo(Em.$("body")),i=!0,Em.$(document).on(t.join(" "),_.throttle(r,25)).on(n.join(" "),o)}),Em.run.next(function(){var t=localStorage&&localStorage.logster_divider_bottom||300,n=s.height()-parseInt(t,10)
32
32
  e.divideView(n,s)})},willDestroyElement:function(){Em.$(".divider").off(a.join(" "))}})
33
33
  e.default=s}),define("client-app/components/patterns-list",["exports","@babel/runtime/helpers/esm/toConsumableArray","client-app/models/pattern-item","client-app/lib/utilities"],function(e,t,n,a){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
34
34
  var s=Ember.Component.extend({immutable:Ember.computed.not("mutable"),init:function(){this._super.apply(this,arguments),this.get("patterns.length")<1&&this.get("mutable")&&this.send("create")},allPatterns:Ember.computed("patterns.[]","newPatterns.[]",function(){var e=this.get("patterns"),n=this.get("newPatterns")||[]
@@ -43,25 +43,27 @@ t&&t[e](this)},didInsertElement:function(){this.invokeParent("addTab"),this.get(
43
43
  e.default=t}),define("client-app/components/tabbed-section",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
44
44
  var t=Ember.Component.extend({tabs:Em.A(),selectTab:function(e){if(e.get("isLink"))this.triggerAction(e.get("action"))
45
45
  else{var t=this.get("selected")
46
- t&&t.set("active",!1),this.set("selected",e),e.set("active",!0)}},addTab:function(e){this.get("tabs").addObject(e),this.get("selected")||e.get("isLink")||this.selectTab(e)},removeTab:function(e){this.get("selected")===e&&this.set("selected",null),this.get("tabs").removeObject(e)}})
46
+ t&&t.set("active",!1),this.set("selected",e),e.set("active",!0),this.onTabChange(e.name)}},addTab:function(e){this.get("tabs").addObject(e),this.get("selected")||e.get("isLink")||this.selectTab(e)},removeTab:function(e){this.get("selected")===e&&this.set("selected",null),this.get("tabs").removeObject(e)}})
47
47
  e.default=t}),define("client-app/components/time-formatter",["exports","client-app/lib/utilities"],function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
48
48
  var n=Ember.Component.extend({tagName:"span",classNames:"auto-update-time",attributeBindings:["dataTimestamp:data-timestamp","title"],title:Ember.computed(function(){return this.get("moment").format()}),dataTimestamp:Ember.computed(function(){return this.get("timestamp")}),moment:Ember.computed(function(){return moment(this.get("timestamp"))}),time:Ember.computed("timestamp",function(){return(0,t.formatTime)(this.get("timestamp"))})})
49
49
  e.default=n}),define("client-app/components/update-time",["exports","client-app/lib/utilities"],function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
50
50
  var n=Ember.Component.extend({didInsertElement:function(){Em.run.later(function e(){Em.$(".auto-update-time").each(function(){var e=parseInt(this.getAttribute("data-timestamp"),10),n=(0,t.formatTime)(e)
51
51
  n!==this.innerText&&(this.innerText=n)}),Em.run.later(e,6e4)},6e4)}})
52
52
  e.default=n}),define("client-app/controllers/index",["exports","client-app/lib/utilities","client-app/lib/preload"],function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
53
- var a=Ember.Controller.extend({showDebug:!0,showInfo:!0,showWarn:!0,showErr:!0,showFatal:!0,search:"",currentMessage:Em.computed.alias("model.currentMessage"),showSettings:Ember.computed(function(){return n.default.get("patterns_enabled")}),resizePanels:function(e){Em.$("#bottom-panel").css("height",e-13),Em.$("#top-panel").css("bottom",e+12)},actionsInMenu:Ember.computed(function(){return this.site.isMobile}),actions:{expandMessage:function(e){e.expand()},selectMessage:function(e){var t=this.get("currentMessage")
54
- t&&t.set("selected",!1),e.set("selected",!0),this.set("currentMessage",e)},showMoreBefore:function(){this.get("model").showMoreBefore()},loadMore:function(){return this.get("model").loadMore()},clear:function(){var e=this
53
+ var a=Ember.Controller.extend({showDebug:!0,showInfo:!0,showWarn:!0,showErr:!0,showFatal:!0,search:"",currentMessage:Em.computed.alias("model.currentMessage"),currentTab:null,showSettings:Ember.computed(function(){return n.default.get("patterns_enabled")}),resizePanels:function(e){Em.$("#bottom-panel").css("height",e-13),Em.$("#top-panel").css("bottom",e+12)},actionsInMenu:Ember.computed(function(){return this.site.isMobile}),fetchEnv:function(){var e=this,n=this.get("currentMessage")
54
+ if(n)return this.set("loadingEnv",!0),(0,t.ajax)("/fetch-env/".concat(n.key,".json")).then(function(e){return n.set("env",e)}).always(function(){return e.set("loadingEnv",!1)})},actions:{expandMessage:function(e){e.expand()},selectMessage:function(e){var t=this.get("currentMessage")
55
+ t&&t.set("selected",!1),e.set("selected",!0),this.setProperties({currentMessage:e,loadingEnv:!1}),e.env||"env"!==this.currentTab||this.fetchEnv()},tabChanged:function(e){this.setProperties({currentTab:e,loadingEnv:!1}),"env"!==e||this.get("currentMessage.env")||this.fetchEnv()},showMoreBefore:function(){this.get("model").showMoreBefore()},loadMore:function(){return this.get("model").loadMore()},clear:function(){var e=this
55
56
  confirm("Clear the logs?\n\nCancel = No, OK = Clear")&&(0,t.ajax)("/clear",{type:"POST"}).then(function(){e.get("model").reload()})},removeMessage:function(e){this.get("model").destroy(e)},solveMessage:function(e){this.get("model").solve(e)}},updateSelectedMessage:function(){var e=this.get("currentMessage.key"),t=this.get("model.messages")
56
57
  if(e&&t){var n=t.find(function(t){return t.key===e})
57
58
  n?n.set("selected",!0):this.set("currentMessage",null)}},filter:Ember.computed("showDebug","showInfo","showWarn","showErr","showFatal",function(){var e=this,t=[]
58
59
  return["Debug","Info","Warn","Err","Fatal"].forEach(function(n,a){e.get("show".concat(n))&&t.push(a)}),t.push(5),t}),filterChanged:Ember.observer("filter.length",function(){var e=this,t=this.get("filter"),n=this.get("model")
59
- n.set("filter",t),t&&this.get("initialized")&&n.reload().then(function(){return e.updateSelectedMessage()})}),searchChanged:Ember.observer("search",function(){var e=this,t=this.get("search"),n=this.get("model")
60
- n.set("search",t),this.get("initialized")&&n.reload().then(function(){return e.updateSelectedMessage()})})})
60
+ n.set("filter",t),t&&this.get("initialized")&&n.reload().then(function(){return e.updateSelectedMessage()})}),doSearch:function(e){var t=this,n=this.get("model")
61
+ n.set("search",e),this.get("initialized")&&n.reload().then(function(){return t.updateSelectedMessage()})},searchChanged:Ember.observer("search",function(){var e=this.search,t=e&&e.length
62
+ t&&1===t||Ember.run.debounce(this,this.doSearch,e,250)})})
61
63
  e.default=a}),define("client-app/controllers/show",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
62
64
  var t=Ember.Controller.extend({actions:{protect:function(){this.get("model").protect()},unprotect:function(){this.get("model").unprotect()}}})
63
- e.default=t}),define("client-app/helpers/app-version",["exports","client-app/config/environment","ember-cli-app-version/utils/regexp"],function(e,t,n){function a(e){var a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},s=t.default.APP.version,r=a.versionOnly||a.hideSha,i=a.shaOnly||a.hideVersion,o=null
64
- return r&&(a.showExtended&&(o=s.match(n.versionExtendedRegExp)),o||(o=s.match(n.versionRegExp))),i&&(o=s.match(n.shaRegExp)),o?o[0]:s}Object.defineProperty(e,"__esModule",{value:!0}),e.appVersion=a,e.default=void 0
65
+ e.default=t}),define("client-app/helpers/app-version",["exports","client-app/config/environment","ember-cli-app-version/utils/regexp"],function(e,t,n){function a(e){var a=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},s=t.default.APP.version,i=a.versionOnly||a.hideSha,r=a.shaOnly||a.hideVersion,o=null
66
+ return i&&(a.showExtended&&(o=s.match(n.versionExtendedRegExp)),o||(o=s.match(n.versionRegExp))),r&&(o=s.match(n.shaRegExp)),o?o[0]:s}Object.defineProperty(e,"__esModule",{value:!0}),e.appVersion=a,e.default=void 0
65
67
  var s=Ember.Helper.helper(a)
66
68
  e.default=s}),define("client-app/helpers/logster-url",["exports","client-app/lib/preload"],function(e,t){function n(e){var n=e[0]
67
69
  return"/"!==n[0]&&(n="/".concat(n)),t.default.get("rootPath")+n}Object.defineProperty(e,"__esModule",{value:!0}),e.logsterUrl=n,e.default=void 0
@@ -77,12 +79,12 @@ var n=["component","route"]
77
79
  function a(e){var a,s
78
80
  moment.updateLocale("en",{relativeTime:{future:"in %s",past:"%s ago",s:"secs",m:"a min",mm:"%d mins",h:"an hr",hh:"%d hrs",d:"a day",dd:"%d days",M:"a mth",MM:"%d mths",y:"a yr",yy:"%d yrs"}}),["","webkit","ms","moz","ms"].forEach(function(e){var t=e+(""===e?"hidden":"Hidden")
79
81
  void 0===document[t]||a||(a=t,s=e+"visibilitychange")}),(0,t.updateHiddenProperty)(a),document.addEventListener(s,function(){(0,t.resetTitleCount)()},!1),e.register("events:main",Ember.Object.extend(Ember.Evented).create(),{instantiate:!1}),n.forEach(function(t){return e.inject(t,"events","events:main")})
80
- var r=/mobile/i.test(navigator.userAgent)&&!/iPad/.test(navigator.userAgent)
81
- r&&Em.$("body").addClass("mobile"),e.register("site:main",{isMobile:r},{instantiate:!1}),e.inject("controller","site","site:main")}var s={initialize:a}
82
+ var i=/mobile/i.test(navigator.userAgent)&&!/iPad/.test(navigator.userAgent)
83
+ i&&Em.$("body").addClass("mobile"),e.register("site:main",{isMobile:i},{instantiate:!1}),e.inject("controller","site","site:main")}var s={initialize:a}
82
84
  e.default=s}),define("client-app/initializers/app-version",["exports","ember-cli-app-version/initializer-factory","client-app/config/environment"],function(e,t,n){var a,s
83
85
  Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,n.default.APP&&(a=n.default.APP.name,s=n.default.APP.version)
84
- var r={name:"App Version",initialize:(0,t.default)(a,s)}
85
- e.default=r}),define("client-app/initializers/container-debug-adapter",["exports","ember-resolver/resolvers/classic/container-debug-adapter"],function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
86
+ var i={name:"App Version",initialize:(0,t.default)(a,s)}
87
+ e.default=i}),define("client-app/initializers/container-debug-adapter",["exports","ember-resolver/resolvers/classic/container-debug-adapter"],function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
86
88
  var n={name:"container-debug-adapter",initialize:function(){var e=arguments[1]||arguments[0]
87
89
  e.register("container-debug-adapter:main",t.default),e.inject("container-debug-adapter:main","namespace","application:main")}}
88
90
  e.default=n}),define("client-app/initializers/ember-data",["exports","ember-data/setup-container","ember-data"],function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
@@ -104,22 +106,22 @@ function a(){var e=document.getElementById("preloaded-data").dataset
104
106
  t=Em.$.extend(JSON.parse(e.preloaded),{rootPath:e.rootPath}),n=!0}var s={get:function(e){return n||a(),Em.get(t,e)}}
105
107
  e.default=s}),define("client-app/lib/utilities",["exports","@babel/runtime/helpers/esm/typeof","client-app/lib/preload"],function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.escapeHtml=o,e.ajax=l,e.preloadOrAjax=function(e,t){var a=n.default.get(e.replace(".json",""))
106
108
  return a?Em.RSVP.resolve(a):l(e,t)},e.updateHiddenProperty=function(e){a=e},e.isHidden=c,e.increaseTitleCount=function(e){if(!c())return
107
- s=s||document.title,r=r||0,r+=e,document.title="".concat(s," (").concat(r,")")},e.resetTitleCount=function(){r=0,document.title=s||document.title},e.formatTime=u,e.buildArrayString=d,e.buildHashString=function e(a,s){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[]
109
+ s=s||document.title,i=i||0,i+=e,document.title="".concat(s," (").concat(i,")")},e.resetTitleCount=function(){i=0,document.title=s||document.title},e.formatTime=u,e.buildArrayString=d,e.buildHashString=function e(a,s){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[]
108
110
  if(!a)return""
109
- var i=[]
111
+ var r=[]
110
112
  var l=[]
111
113
  var c=n.default.get("env_expandable_keys")||[]
112
- _.each(a,function(e,n){if(null===e)i.push("null")
114
+ _.each(a,function(e,n){if(null===e)r.push("null")
113
115
  else if("[object Array]"===Object.prototype.toString.call(e)){var a=""
114
- a=-1!==c.indexOf(n)&&!s&&-1===r.indexOf(n)&&e.length>3?"".concat(o(e[0]),', <a class="expand-list" data-key=').concat(n,">").concat(e.length-1," more</a>"):d(e),i.push("<tr><td>"+o(n)+"</td><td>"+a+"</td></tr>")}else if("object"===(0,t.default)(e))l.push(n)
116
+ a=-1!==c.indexOf(n)&&!s&&-1===i.indexOf(n)&&e.length>3?"".concat(o(e[0]),', <a class="expand-list" data-key=').concat(n,">").concat(e.length-1," more</a>"):d(e),r.push("<tr><td>"+o(n)+"</td><td>"+a+"</td></tr>")}else if("object"===(0,t.default)(e))l.push(n)
115
117
  else if("time"===n&&"number"==typeof e){var p=moment(e).format(),f=u(e)
116
- i.push('<tr title="'.concat(p,'"><td>').concat(n,"</td><td>").concat(f,"</td></tr>"))}else i.push("<tr><td>".concat(o(n),"</td><td>").concat(o(e),"</td></tr>"))})
118
+ r.push('<tr title="'.concat(p,'"><td>').concat(n,"</td><td>").concat(f,"</td></tr>"))}else r.push("<tr><td>".concat(o(n),"</td><td>").concat(o(e),"</td></tr>"))})
117
119
  _.size(l)>0&&_.each(l,function(t){var n=a[t]
118
- i.push("<tr><td></td><td><table>"),i.push("<td>"+o(t)+"</td><td>"+e(n,!0)+"</td>"),i.push("</table></td></tr>")})
120
+ r.push("<tr><td></td><td><table>"),r.push("<td>"+o(t)+"</td><td>"+e(n,!0)+"</td>"),r.push("</table></td></tr>")})
119
121
  var p=s?"":"env-table"
120
- return"<table class='"+p+"'>"+i.join("\n")+"</table>"}
121
- var a,s,r,i={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;"}
122
- function o(e){return String(e).replace(/[&<>"'\/]/g,function(e){return i[e]})}function l(e,t){return(t=t||{}).headers=t.headers||{},t.headers["X-SILENCE-LOGGER"]=!0,Em.$.ajax(n.default.get("rootPath")+e,t)}function c(){return void 0!==a?document[a]:!document.hasFocus}function u(e){var t=moment(e),n=moment()
122
+ return"<table class='"+p+"'>"+r.join("\n")+"</table>"}
123
+ var a,s,i,r={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;"}
124
+ function o(e){return String(e).replace(/[&<>"'\/]/g,function(e){return r[e]})}function l(e,t){return(t=t||{}).headers=t.headers||{},t.headers["X-SILENCE-LOGGER"]=!0,Em.$.ajax(n.default.get("rootPath")+e,t)}function c(){return void 0!==a?document[a]:!document.hasFocus}function u(e){var t=moment(e),n=moment()
123
125
  return t.diff(n.startOf("day"))>0?t.format("h:mm a"):t.diff(n.startOf("week"))>0?t.format("dd h:mm a"):t.diff(n.startOf("year"))>0?t.format("D MMM h:mm a"):t.format("D MMM YY")}function d(e){var t=[]
124
126
  return e.forEach(function(e){null===e?t.push("null"):"[object Array]"===Object.prototype.toString.call(e)?t.push(d(e)):t.push(o(e.toString()))}),"["+t.join(", ")+"]"}}),define("client-app/models/message-collection",["exports","client-app/lib/utilities","client-app/models/message"],function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
125
127
  var a=Em.Object.extend({messages:Em.A(),currentMessage:null,total:0,solve:function(e){var t=this
@@ -128,8 +130,8 @@ e.destroy(),e.set("selected",!1),this.set("total",this.get("total")-1),this.get(
128
130
  e=e||{}
129
131
  var a={filter:this.get("filter").join("_")},s=this.get("search")
130
132
  _.isEmpty(s)||(a.search=s,this.get("regexSearch")&&(a.regex_search="true"))
131
- return e.before&&(a.before=e.before),e.after&&(a.after=e.after),(0,t.ajax)("/messages.json",{data:a}).then(function(a){if(0==Ember.compare(a.filter,n.get("filter"))&&0==Ember.compare(a.search,n.get("search"))){if(a.messages.length>0){var s=n.toMessages(a.messages),r=n.get("messages")
132
- e.before?r.unshiftObjects(s):(s.forEach(function(e){r.forEach(function(t){t.key==e.key&&(r.removeObject(t),n.get("currentMessage")===t&&(n.set("currentMessage",e),e.set("selected",t.get("selected"))))})}),r.addObjects(s),s.length>0&&(0,t.increaseTitleCount)(s.length))}return n.set("total",a.total),a}})},reload:function(){var e=this
133
+ return e.before&&(a.before=e.before),e.after&&(a.after=e.after),this.set("loading",!0),(0,t.ajax)("/messages.json",{data:a}).then(function(a){if(0==Ember.compare(a.filter,n.get("filter"))&&0==Ember.compare(a.search,n.get("search"))){if(a.messages.length>0){var s=n.toMessages(a.messages),i=n.get("messages")
134
+ e.before?i.unshiftObjects(s):(s.forEach(function(e){i.forEach(function(t){t.key==e.key&&(i.removeObject(t),n.get("currentMessage")===t&&(n.set("currentMessage",e),e.set("selected",t.get("selected"))))})}),i.addObjects(s),s.length>0&&(0,t.increaseTitleCount)(s.length))}return n.set("total",a.total),a}}).always(function(){return n.set("loading",!1)})},reload:function(){var e=this
133
135
  return this.set("total",0),this.get("messages").clear(),this.load().then(function(t){return e.updateCanLoadMore(t)})},updateCanLoadMore:function(e){e&&(e.messages.length<50?this.set("canLoadMore",!1):this.set("canLoadMore",!0))},loadMore:function(){var e=this.get("messages")
134
136
  if(0!==e.length){var t=e[e.length-1].get("key")
135
137
  this.load({after:t})}else this.load({})},hideCountInLoadMore:Ember.computed("search","filter",function(){var e=this.get("search"),t=this.get("filter")
@@ -161,13 +163,13 @@ var a=n
161
163
  e.default=a}),define("client-app/routes/index",["exports","client-app/models/message-collection","client-app/lib/utilities"],function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
162
164
  var a=Ember.Route.extend({model:function(){return t.default.create()},setupController:function(e,t){this._super(e,t),t.setProperties(e.getProperties("filter","search")),t.reload(),e.set("initialized",!0)
163
165
  var a=0,s=1
164
- this.refreshInterval=setInterval(function(){a+=1
165
- var e=(0,n.isHidden)(),r=!e
166
- e&&a%s==0&&(r=!0,s<20&&s++),r&&(t.loadMore(),e||(s=1))},3e3),this.events.on("panelResized",function(t){e.resizePanels(t)})},deactivate:function(){clearInterval(this.refreshInterval)}})
166
+ this.refreshInterval=setInterval(function(){if(!t.loading){a+=1
167
+ var e=(0,n.isHidden)(),i=!e
168
+ e&&a%s==0&&(i=!0,s<20&&s++),i&&(t.loadMore(),e||(s=1))}},3e3),this.events.on("panelResized",function(t){e.resizePanels(t)})},deactivate:function(){clearInterval(this.refreshInterval)}})
167
169
  e.default=a}),define("client-app/routes/settings",["exports","client-app/lib/utilities","client-app/models/pattern-item"],function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
168
170
  var a=Ember.Route.extend({model:function(){return(0,t.ajax)("/settings.json")},setupController:function(e,t){this._super.apply(this,arguments)
169
- var a=t.suppression,s=a.filter(function(e){return e.hard}).map(function(e){return n.default.create(e)}),r=a.reject(function(e){return e.hard}).map(function(e){return n.default.create(e)}),i=s.length>0
170
- e.setProperties({showCodedSuppression:i,codedSuppression:s,customSuppression:r})}})
171
+ var a=t.suppression,s=a.filter(function(e){return e.hard}).map(function(e){return n.default.create(e)}),i=a.reject(function(e){return e.hard}).map(function(e){return n.default.create(e)}),r=s.length>0
172
+ e.setProperties({showCodedSuppression:r,codedSuppression:s,customSuppression:i})}})
171
173
  e.default=a}),define("client-app/routes/show",["exports","client-app/models/message","client-app/lib/utilities"],function(e,t,n){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
172
174
  var a=Ember.Route.extend({model:function(e){return(0,n.preloadOrAjax)("/show/"+e.id+".json")},setupController:function(e,n){this._super.apply(this,arguments),e.set("model",t.default.create(n))}})
173
175
  e.default=a}),define("client-app/services/ajax",["exports","ember-ajax/services/ajax"],function(e,t){Object.defineProperty(e,"__esModule",{value:!0}),Object.defineProperty(e,"default",{enumerable:!0,get:function(){return t.default}})}),define("client-app/templates/application",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
@@ -177,7 +179,7 @@ var t=Ember.HTMLBars.template({id:"iO5WYaED",block:'{"symbols":["&default"],"sta
177
179
  e.default=t}),define("client-app/templates/components/env-tab",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
178
180
  var t=Ember.HTMLBars.template({id:"X1VwEK8H",block:'{"symbols":[],"statements":[[4,"if",[[23,["isEnvArray"]]],null,{"statements":[[0," "],[7,"div"],[11,"class","nav-controls"],[9],[0,"\\n "],[7,"button"],[12,"disabled",[21,"disableBackButtons"]],[11,"class","btn nav-btn no-text"],[9],[7,"i"],[11,"class","fa fa-fast-backward"],[9],[10],[3,"action",[[22,0,[]],"bigJump","back"]],[10],[0,"\\n "],[7,"button"],[12,"disabled",[21,"disableBackButtons"]],[11,"class","btn nav-btn no-text"],[9],[7,"i"],[11,"class","fa fa-backward"],[9],[10],[3,"action",[[22,0,[]],"takeStep","back"]],[10],[0,"\\n "],[7,"span"],[11,"class","env-number"],[9],[1,[21,"current"],false],[0,"/"],[1,[23,["message","env","length"]],false],[10],[0,"\\n "],[7,"button"],[12,"disabled",[21,"disableForwardButtons"]],[11,"class","btn nav-btn no-text"],[9],[7,"i"],[11,"class","fa fa-forward"],[9],[10],[3,"action",[[22,0,[]],"takeStep","front"]],[10],[0,"\\n "],[7,"button"],[12,"disabled",[21,"disableForwardButtons"]],[11,"class","btn nav-btn no-text"],[9],[7,"i"],[11,"class","fa fa-fast-forward"],[9],[10],[3,"action",[[22,0,[]],"bigJump","front"]],[10],[0,"\\n "],[10],[0,"\\n"]],"parameters":[]},null],[1,[21,"html"],true],[0,"\\n"]],"hasEval":false}',meta:{moduleName:"client-app/templates/components/env-tab.hbs"}})
179
181
  e.default=t}),define("client-app/templates/components/message-info",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
180
- var t=Ember.HTMLBars.template({id:"Jwt+/aHp",block:'{"symbols":["btn"],"statements":[[7,"div"],[11,"class","message-info"],[9],[0,"\\n"],[4,"tabbed-section",null,null,{"statements":[[4,"tab-contents",null,[["name","hint","currentMessage"],["info","show info",[23,["currentMessage"]]]],{"statements":[[4,"if",[[23,["showTitle"]]],null,{"statements":[[0," "],[7,"h3"],[9],[0,"Message\\n"],[4,"if",[[23,["currentMessage","showCount"]]],null,{"statements":[[0," ("],[1,[23,["currentMessage","count"]],false],[0," copies reported)\\n"]],"parameters":[]},null],[0," "],[10],[0,"\\n"]],"parameters":[]},null],[0," "],[7,"pre"],[9],[1,[23,["currentMessage","message"]],false],[10],[0,""]],"parameters":[]},null],[4,"tab-contents",null,[["name","defaultTab","hint","currentMessage"],["backtrace","true","show backtrace",[23,["currentMessage"]]]],{"statements":[[4,"if",[[23,["showTitle"]]],null,{"statements":[[0," "],[7,"h3"],[9],[0,"Backtrace"],[10],[0,"\\n"]],"parameters":[]},null],[0," "],[7,"pre"],[9],[1,[23,["currentMessage","backtrace"]],false],[10],[0,""]],"parameters":[]},null],[4,"if",[[23,["currentMessage","env"]]],null,{"statements":[[4,"tab-contents",null,[["className","name","hint","currentMessage"],["env","env","show environment",[23,["currentMessage"]]]],{"statements":[[4,"if",[[23,["showTitle"]]],null,{"statements":[[0," "],[7,"h3"],[9],[0,"Env"],[10],[0,"\\n"]],"parameters":[]},null],[0," "],[1,[27,"env-tab",null,[["message"],[[23,["currentMessage"]]]]],false],[0,"\\n"]],"parameters":[]},null]],"parameters":[]},null]],"parameters":[]},null],[0,"\\n"],[4,"if",[[23,["currentMessage"]]],null,{"statements":[[0," "],[7,"div"],[11,"class","message-actions"],[9],[0,"\\n"],[4,"actions-menu",null,[["actionsInMenu","share"],[[23,["actionsInMenu"]],[27,"action",[[22,0,[]],"share"],null]]],{"statements":[[4,"each",[[23,["buttons"]]],null,{"statements":[[0," "],[7,"button"],[12,"class",[28,[[22,1,["klass"]]," btn ",[27,"if",[[22,1,["danger"]],"danger",""],null]]]],[9],[0,"\\n "],[7,"i"],[12,"class",[28,["fa fa-",[22,1,["icon"]]]]],[9],[10],[0,"\\n "],[7,"span"],[9],[1,[22,1,["label"]],false],[10],[0,"\\n "],[3,"action",[[22,0,[]],[22,1,["action"]]]],[10],[0,"\\n"]],"parameters":[1]},null]],"parameters":[]},null],[0," "],[10],[0,"\\n"]],"parameters":[]},null],[10],[0,"\\n"]],"hasEval":false}',meta:{moduleName:"client-app/templates/components/message-info.hbs"}})
182
+ var t=Ember.HTMLBars.template({id:"gPjmElUI",block:'{"symbols":["btn"],"statements":[[7,"div"],[11,"class","message-info"],[9],[0,"\\n"],[4,"tabbed-section",null,[["onTabChange"],[[27,"action",[[22,0,[]],"tabChanged"],null]]],{"statements":[[4,"tab-contents",null,[["name","hint","currentMessage"],["info","show info",[23,["currentMessage"]]]],{"statements":[[4,"if",[[23,["showTitle"]]],null,{"statements":[[0," "],[7,"h3"],[9],[0,"Message\\n"],[4,"if",[[23,["currentMessage","showCount"]]],null,{"statements":[[0," ("],[1,[23,["currentMessage","count"]],false],[0," copies reported)\\n"]],"parameters":[]},null],[0," "],[10],[0,"\\n"]],"parameters":[]},null],[0," "],[7,"pre"],[9],[1,[23,["currentMessage","message"]],false],[10],[0,""]],"parameters":[]},null],[4,"tab-contents",null,[["name","defaultTab","hint","currentMessage"],["backtrace","true","show backtrace",[23,["currentMessage"]]]],{"statements":[[4,"if",[[23,["showTitle"]]],null,{"statements":[[0," "],[7,"h3"],[9],[0,"Backtrace"],[10],[0,"\\n"]],"parameters":[]},null],[0," "],[7,"pre"],[9],[1,[23,["currentMessage","backtrace"]],false],[10],[0,""]],"parameters":[]},null],[4,"tab-contents",null,[["className","name","hint","currentMessage"],["env","env","show environment",[23,["currentMessage"]]]],{"statements":[[4,"if",[[23,["currentMessage","env"]]],null,{"statements":[[4,"if",[[23,["showTitle"]]],null,{"statements":[[0," "],[7,"h3"],[9],[0,"Env"],[10],[0,"\\n"]],"parameters":[]},null],[0," "],[1,[27,"env-tab",null,[["message"],[[23,["currentMessage"]]]]],false],[0,"\\n"]],"parameters":[]},{"statements":[[4,"if",[[23,["loadingEnv"]]],null,{"statements":[[0," Loading env...\\n"]],"parameters":[]},{"statements":[[0," No env for this message.\\n "]],"parameters":[]}]],"parameters":[]}]],"parameters":[]},null]],"parameters":[]},null],[0,"\\n"],[4,"if",[[23,["currentMessage"]]],null,{"statements":[[0," "],[7,"div"],[11,"class","message-actions"],[9],[0,"\\n"],[4,"actions-menu",null,[["actionsInMenu","share"],[[23,["actionsInMenu"]],[27,"action",[[22,0,[]],"share"],null]]],{"statements":[[4,"each",[[23,["buttons"]]],null,{"statements":[[0," "],[7,"button"],[12,"class",[28,[[22,1,["klass"]]," btn ",[27,"if",[[22,1,["danger"]],"danger",""],null]]]],[9],[0,"\\n "],[7,"i"],[12,"class",[28,["fa fa-",[22,1,["icon"]]]]],[9],[10],[0,"\\n "],[7,"span"],[9],[1,[22,1,["label"]],false],[10],[0,"\\n "],[3,"action",[[22,0,[]],[22,1,["action"]]]],[10],[0,"\\n"]],"parameters":[1]},null]],"parameters":[]},null],[0," "],[10],[0,"\\n"]],"parameters":[]},null],[10],[0,"\\n"]],"hasEval":false}',meta:{moduleName:"client-app/templates/components/message-info.hbs"}})
181
183
  e.default=t}),define("client-app/templates/components/message-row",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
182
184
  var t=Ember.HTMLBars.template({id:"pF0hQ9a+",block:'{"symbols":[],"statements":[[7,"div"],[11,"class","count"],[9],[0,"\\n"],[4,"if",[[23,["model","showCount"]]],null,{"statements":[[0," "],[1,[23,["model","count"]],false],[0,"\\n"]],"parameters":[]},null],[10],[0,"\\n"],[7,"div"],[11,"class","severity"],[9],[1,[23,["model","glyph"]],true],[10],[0,"\\n"],[7,"div"],[11,"class","message-body"],[9],[0,"\\n "],[1,[23,["model","displayMessage"]],false],[0,"\\n"],[10],[0,"\\n"],[7,"div"],[11,"class","protected"],[9],[0,"\\n"],[4,"if",[[23,["model","protected"]]],null,{"statements":[[0," "],[7,"i"],[11,"title","message is protected, clearing will not remove it"],[11,"class","fa fa-lock"],[9],[10],[0,"\\n"]],"parameters":[]},null],[10],[0,"\\n"],[7,"div"],[11,"class","time"],[9],[1,[27,"time-formatter",null,[["timestamp"],[[23,["model","timestamp"]]]]],false],[10],[0,"\\n"]],"hasEval":false}',meta:{moduleName:"client-app/templates/components/message-row.hbs"}})
183
185
  e.default=t}),define("client-app/templates/components/panel-resizer",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
@@ -189,10 +191,10 @@ var t=Ember.HTMLBars.template({id:"zCP0V00P",block:'{"symbols":["tab","&default"
189
191
  e.default=t}),define("client-app/templates/components/time-formatter",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
190
192
  var t=Ember.HTMLBars.template({id:"sp53cTcH",block:'{"symbols":[],"statements":[[1,[21,"time"],false],[0,"\\n"]],"hasEval":false}',meta:{moduleName:"client-app/templates/components/time-formatter.hbs"}})
191
193
  e.default=t}),define("client-app/templates/index",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
192
- var t=Ember.HTMLBars.template({id:"i9LWBRFJ",block:'{"symbols":["message"],"statements":[[7,"div"],[11,"id","top-panel"],[9],[0,"\\n "],[7,"div"],[11,"id","log-table"],[9],[0,"\\n"],[4,"if",[[23,["model","moreBefore"]]],null,{"statements":[[0," "],[7,"div"],[11,"class","show-more"],[9],[0,"\\n"],[4,"if",[[23,["model","hideCountInLoadMore"]]],null,{"statements":[[0," Load more\\n"]],"parameters":[]},{"statements":[[0," Select to see "],[1,[23,["model","totalBefore"]],false],[0," more\\n"]],"parameters":[]}],[0," "],[3,"action",[[22,0,[]],"showMoreBefore"]],[10],[0,"\\n"]],"parameters":[]},null],[4,"each",[[23,["model","messages"]]],null,{"statements":[[0," "],[1,[27,"message-row",null,[["model","selectedMessage"],[[22,1,[]],[27,"action",[[22,0,[]],"selectMessage"],null]]]],false],[0,"\\n"]],"parameters":[1]},null],[0," "],[10],[0,"\\n"],[10],[0,"\\n"],[7,"div"],[11,"id","bottom-panel"],[9],[0,"\\n "],[1,[27,"message-info",null,[["currentMessage","removeMessage","solveMessage","actionsInMenu"],[[23,["currentMessage"]],[27,"action",[[22,0,[]],"removeMessage"],null],[27,"action",[[22,0,[]],"solveMessage"],null],[23,["actionsInMenu"]]]]],false],[0,"\\n\\n "],[7,"div"],[11,"class","action-panel"],[9],[0,"\\n "],[7,"div"],[11,"class","severity-filters"],[9],[0,"\\n "],[7,"div"],[11,"class","more-wrapping"],[9],[0,"\\n "],[7,"label"],[11,"class","debug"],[9],[0,"\\n "],[1,[27,"input",null,[["type","checked"],["checkbox",[23,["showDebug"]]]]],false],[0,"\\n "],[7,"span"],[9],[0,"Debug"],[10],[0,"\\n "],[10],[0,"\\n "],[7,"label"],[11,"class","info"],[9],[0,"\\n "],[1,[27,"input",null,[["type","checked"],["checkbox",[23,["showInfo"]]]]],false],[0,"\\n "],[7,"span"],[9],[0,"Info"],[10],[0,"\\n "],[10],[0,"\\n "],[7,"label"],[11,"class","warn"],[9],[0,"\\n "],[1,[27,"input",null,[["type","checked"],["checkbox",[23,["showWarn"]]]]],false],[0,"\\n "],[7,"i"],[11,"class","fa fa-exclamation-circle warning"],[9],[10],[0,"\\n "],[7,"span"],[9],[0,"Warning"],[10],[0,"\\n "],[10],[0,"\\n "],[7,"label"],[11,"class","error"],[9],[0,"\\n "],[1,[27,"input",null,[["type","checked"],["checkbox",[23,["showErr"]]]]],false],[0,"\\n "],[7,"i"],[11,"class","fa fa-times-circle error"],[9],[10],[0,"\\n "],[7,"span"],[9],[0,"Error"],[10],[0,"\\n "],[10],[0,"\\n "],[7,"label"],[11,"class","fatal"],[9],[0,"\\n "],[1,[27,"input",null,[["type","checked"],["checkbox",[23,["showFatal"]]]]],false],[0,"\\n "],[7,"i"],[11,"class","fa fa-times-circle fatal"],[9],[10],[0,"\\n "],[7,"span"],[9],[0,"Fatal"],[10],[0,"\\n "],[10],[0,"\\n "],[10],[0,"\\n "],[10],[0,"\\n "],[7,"div"],[11,"class","search-clear-all"],[9],[0,"\\n "],[1,[27,"input",null,[["type","class","placeholder","value"],["textfield","search","Search",[23,["search"]]]]],false],[0,"\\n "],[7,"div"],[11,"class","footer-btns"],[9],[0,"\\n"],[4,"if",[[23,["showSettings"]]],null,{"statements":[[4,"link-to",["settings"],[["class"],["settings btn no-text"]],{"statements":[[0," "],[7,"i"],[11,"class","fa fa-cog"],[9],[10],[0,"\\n"]],"parameters":[]},null]],"parameters":[]},null],[0," "],[7,"button"],[11,"class","clear btn danger"],[9],[7,"i"],[11,"class","fa fa-trash-o"],[9],[10],[7,"span"],[9],[0,"Clear logs"],[10],[3,"action",[[22,0,[]],"clear"]],[10],[0,"\\n "],[10],[0,"\\n "],[10],[0,"\\n "],[10],[0,"\\n"],[10],[0,"\\n"],[1,[21,"panel-resizer"],false],[0,"\\n"]],"hasEval":false}',meta:{moduleName:"client-app/templates/index.hbs"}})
194
+ var t=Ember.HTMLBars.template({id:"2nOvOGVv",block:'{"symbols":["message"],"statements":[[7,"div"],[11,"id","top-panel"],[9],[0,"\\n "],[7,"div"],[11,"id","log-table"],[9],[0,"\\n"],[4,"if",[[23,["model","moreBefore"]]],null,{"statements":[[0," "],[7,"div"],[11,"class","show-more"],[9],[0,"\\n"],[4,"if",[[23,["model","hideCountInLoadMore"]]],null,{"statements":[[0," Load more\\n"]],"parameters":[]},{"statements":[[0," Select to see "],[1,[23,["model","totalBefore"]],false],[0," more\\n"]],"parameters":[]}],[0," "],[3,"action",[[22,0,[]],"showMoreBefore"]],[10],[0,"\\n"]],"parameters":[]},null],[4,"each",[[23,["model","messages"]]],null,{"statements":[[0," "],[1,[27,"message-row",null,[["model","selectedMessage"],[[22,1,[]],[27,"action",[[22,0,[]],"selectMessage"],null]]]],false],[0,"\\n"]],"parameters":[1]},null],[0," "],[10],[0,"\\n"],[10],[0,"\\n"],[7,"div"],[11,"id","bottom-panel"],[9],[0,"\\n "],[1,[27,"message-info",null,[["currentMessage","loadingEnv","removeMessage","solveMessage","onTabChange","actionsInMenu"],[[23,["currentMessage"]],[23,["loadingEnv"]],[27,"action",[[22,0,[]],"removeMessage"],null],[27,"action",[[22,0,[]],"solveMessage"],null],[27,"action",[[22,0,[]],"tabChanged"],null],[23,["actionsInMenu"]]]]],false],[0,"\\n\\n "],[7,"div"],[11,"class","action-panel"],[9],[0,"\\n "],[7,"div"],[11,"class","severity-filters"],[9],[0,"\\n "],[7,"div"],[11,"class","more-wrapping"],[9],[0,"\\n "],[7,"label"],[11,"class","debug"],[9],[0,"\\n "],[1,[27,"input",null,[["type","checked"],["checkbox",[23,["showDebug"]]]]],false],[0,"\\n "],[7,"span"],[9],[0,"Debug"],[10],[0,"\\n "],[10],[0,"\\n "],[7,"label"],[11,"class","info"],[9],[0,"\\n "],[1,[27,"input",null,[["type","checked"],["checkbox",[23,["showInfo"]]]]],false],[0,"\\n "],[7,"span"],[9],[0,"Info"],[10],[0,"\\n "],[10],[0,"\\n "],[7,"label"],[11,"class","warn"],[9],[0,"\\n "],[1,[27,"input",null,[["type","checked"],["checkbox",[23,["showWarn"]]]]],false],[0,"\\n "],[7,"i"],[11,"class","fa fa-exclamation-circle warning"],[9],[10],[0,"\\n "],[7,"span"],[9],[0,"Warning"],[10],[0,"\\n "],[10],[0,"\\n "],[7,"label"],[11,"class","error"],[9],[0,"\\n "],[1,[27,"input",null,[["type","checked"],["checkbox",[23,["showErr"]]]]],false],[0,"\\n "],[7,"i"],[11,"class","fa fa-times-circle error"],[9],[10],[0,"\\n "],[7,"span"],[9],[0,"Error"],[10],[0,"\\n "],[10],[0,"\\n "],[7,"label"],[11,"class","fatal"],[9],[0,"\\n "],[1,[27,"input",null,[["type","checked"],["checkbox",[23,["showFatal"]]]]],false],[0,"\\n "],[7,"i"],[11,"class","fa fa-times-circle fatal"],[9],[10],[0,"\\n "],[7,"span"],[9],[0,"Fatal"],[10],[0,"\\n "],[10],[0,"\\n "],[10],[0,"\\n "],[10],[0,"\\n "],[7,"div"],[11,"class","search-clear-all"],[9],[0,"\\n "],[1,[27,"input",null,[["type","class","placeholder","value"],["textfield","search","Search",[23,["search"]]]]],false],[0,"\\n "],[7,"div"],[11,"class","footer-btns"],[9],[0,"\\n"],[4,"if",[[23,["showSettings"]]],null,{"statements":[[4,"link-to",["settings"],[["class"],["settings btn no-text"]],{"statements":[[0," "],[7,"i"],[11,"class","fa fa-cog"],[9],[10],[0,"\\n"]],"parameters":[]},null]],"parameters":[]},null],[0," "],[7,"button"],[11,"class","clear btn danger"],[9],[7,"i"],[11,"class","fa fa-trash-o"],[9],[10],[7,"span"],[9],[0,"Clear logs"],[10],[3,"action",[[22,0,[]],"clear"]],[10],[0,"\\n "],[10],[0,"\\n "],[10],[0,"\\n "],[10],[0,"\\n"],[10],[0,"\\n"],[1,[21,"panel-resizer"],false],[0,"\\n"]],"hasEval":false}',meta:{moduleName:"client-app/templates/index.hbs"}})
193
195
  e.default=t}),define("client-app/templates/settings",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
194
196
  var t=Ember.HTMLBars.template({id:"ZVQ4fCm0",block:'{"symbols":[],"statements":[[7,"div"],[11,"class","settings-page"],[9],[0,"\\n "],[4,"link-to",["index"],null,{"statements":[[0,"Home"]],"parameters":[]},null],[0,"\\n "],[7,"div"],[11,"class","settings-header"],[9],[0,"\\n "],[7,"h1"],[11,"class","header-title"],[9],[0,"Settings"],[10],[0,"\\n "],[7,"img"],[11,"class","header-logo"],[12,"src",[27,"logster-url",["images/icon_144x144.png"],null]],[9],[10],[0,"\\n "],[10],[0,"\\n\\n "],[7,"div"],[11,"class","settings-section suppression-patterns"],[9],[0,"\\n "],[7,"h2"],[11,"class","section-title"],[9],[0,"Suppression Patterns"],[10],[0,"\\n "],[7,"div"],[9],[0,"New messages that match these Regular Expression patterns will be suppressed."],[10],[0,"\\n\\n"],[4,"if",[[23,["showCodedSuppression"]]],null,{"statements":[[0," "],[7,"h3"],[11,"class","subsection-title"],[9],[0,"Hard-coded patterns:"],[10],[0,"\\n "],[7,"div"],[11,"class","tip"],[9],[0,"These patterns can\'t be removed via the UI because they are commited to the source code of your app."],[10],[0,"\\n "],[1,[27,"patterns-list",null,[["patterns","mutable"],[[23,["codedSuppression"]],false]]],false],[0,"\\n"]],"parameters":[]},null],[0,"\\n "],[7,"h3"],[11,"class","subsection-title"],[9],[0,"Custom patterns:"],[10],[0,"\\n "],[1,[27,"patterns-list",null,[["patterns","key","applyRetroactivelyCheckbox","mutable"],[[23,["customSuppression"]],"suppression",true,true]]],false],[0,"\\n "],[10],[0,"\\n"],[10],[0,"\\n"]],"hasEval":false}',meta:{moduleName:"client-app/templates/settings.hbs"}})
195
197
  e.default=t}),define("client-app/templates/show",["exports"],function(e){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
196
198
  var t=Ember.HTMLBars.template({id:"V916vpg9",block:'{"symbols":[],"statements":[[4,"link-to",["index"],null,{"statements":[[0,"Recent"]],"parameters":[]},null],[0,"\\n"],[7,"div"],[11,"id","bottom-panel"],[11,"class","full"],[9],[0,"\\n "],[1,[27,"message-info",null,[["currentMessage","showTitle","actionsInMenu"],[[23,["model"]],"true",false]]],false],[0,"\\n"],[10],[0,"\\n"]],"hasEval":false}',meta:{moduleName:"client-app/templates/show.hbs"}})
197
199
  e.default=t}),define("client-app/config/environment",[],function(){try{var e="client-app/config/environment",t=document.querySelector('meta[name="'+e+'"]').getAttribute("content"),n={default:JSON.parse(decodeURIComponent(t))}
198
- return Object.defineProperty(n,"__esModule",{value:!0}),n}catch(a){throw new Error('Could not read config from meta tag with name "'+e+'".')}}),runningTests||require("client-app/app").default.create({name:"client-app",version:"0.0.0+ce647650"})
200
+ return Object.defineProperty(n,"__esModule",{value:!0}),n}catch(a){throw new Error('Could not read config from meta tag with name "'+e+'".')}}),runningTests||require("client-app/app").default.create({name:"client-app",version:"0.0.0+9798c0bc"})
@@ -46,6 +46,12 @@ export default Component.extend({
46
46
  }),
47
47
 
48
48
  actions: {
49
+ tabChanged(newTab) {
50
+ if (this.onTabChange) {
51
+ this.onTabChange(newTab);
52
+ }
53
+ },
54
+
49
55
  protect() {
50
56
  this.get("currentMessage").protect();
51
57
  },
@@ -14,6 +14,7 @@ export default Component.extend({
14
14
  }
15
15
  this.set("selected", view);
16
16
  view.set("active", true);
17
+ this.onTabChange(view.name);
17
18
  },
18
19
 
19
20
  addTab(tab) {
@@ -2,6 +2,7 @@ import Controller from "@ember/controller";
2
2
  import { ajax } from "client-app/lib/utilities";
3
3
  import { observer, computed } from "@ember/object";
4
4
  import Preload from "client-app/lib/preload";
5
+ import { debounce } from "@ember/runloop";
5
6
 
6
7
  export default Controller.extend({
7
8
  showDebug: true,
@@ -11,6 +12,7 @@ export default Controller.extend({
11
12
  showFatal: true,
12
13
  search: "",
13
14
  currentMessage: Em.computed.alias("model.currentMessage"),
15
+ currentTab: null,
14
16
 
15
17
  showSettings: computed(function() {
16
18
  return Preload.get("patterns_enabled");
@@ -25,6 +27,16 @@ export default Controller.extend({
25
27
  return this.site.isMobile;
26
28
  }),
27
29
 
30
+ fetchEnv() {
31
+ const message = this.get("currentMessage");
32
+ if (message) {
33
+ this.set("loadingEnv", true);
34
+ return ajax(`/fetch-env/${message.key}.json`)
35
+ .then(env => message.set("env", env))
36
+ .always(() => this.set("loadingEnv", false));
37
+ }
38
+ },
39
+
28
40
  actions: {
29
41
  expandMessage(message) {
30
42
  message.expand();
@@ -37,7 +49,23 @@ export default Controller.extend({
37
49
  }
38
50
 
39
51
  message.set("selected", true);
40
- this.set("currentMessage", message);
52
+ this.setProperties({
53
+ currentMessage: message,
54
+ loadingEnv: false
55
+ });
56
+ if (!message.env && this.currentTab === "env") {
57
+ this.fetchEnv();
58
+ }
59
+ },
60
+
61
+ tabChanged(newTab) {
62
+ this.setProperties({
63
+ currentTab: newTab,
64
+ loadingEnv: false
65
+ });
66
+ if (newTab === "env" && !this.get("currentMessage.env")) {
67
+ this.fetchEnv();
68
+ }
41
69
  },
42
70
 
43
71
  showMoreBefore() {
@@ -109,13 +137,21 @@ export default Controller.extend({
109
137
  }
110
138
  }),
111
139
 
112
- searchChanged: observer("search", function() {
113
- const search = this.get("search");
140
+ doSearch(term) {
114
141
  const model = this.get("model");
115
- model.set("search", search);
142
+ model.set("search", term);
116
143
 
117
144
  if (this.get("initialized")) {
118
145
  model.reload().then(() => this.updateSelectedMessage());
119
146
  }
147
+ },
148
+
149
+ searchChanged: observer("search", function() {
150
+ const term = this.search;
151
+ const termSize = term && term.length;
152
+ if (termSize && termSize === 1) {
153
+ return;
154
+ }
155
+ debounce(this, this.doSearch, term, 250);
120
156
  })
121
157
  });
@@ -63,45 +63,48 @@ export default Em.Object.extend({
63
63
  data.after = opts.after;
64
64
  }
65
65
 
66
+ this.set("loading", true);
66
67
  return ajax("/messages.json", {
67
68
  data: data
68
- }).then(data => {
69
- // guard against race: ensure the results we're trying to apply
70
- // match the current search terms
71
- if (compare(data.filter, this.get("filter")) != 0) {
72
- return;
73
- }
74
- if (compare(data.search, this.get("search")) != 0) {
75
- return;
76
- }
69
+ })
70
+ .then(data => {
71
+ // guard against race: ensure the results we're trying to apply
72
+ // match the current search terms
73
+ if (compare(data.filter, this.get("filter")) != 0) {
74
+ return;
75
+ }
76
+ if (compare(data.search, this.get("search")) != 0) {
77
+ return;
78
+ }
77
79
 
78
- if (data.messages.length > 0) {
79
- const newRows = this.toMessages(data.messages);
80
- const messages = this.get("messages");
81
- if (opts.before) {
82
- messages.unshiftObjects(newRows);
83
- } else {
84
- newRows.forEach(nmsg => {
85
- messages.forEach(emsg => {
86
- if (emsg.key == nmsg.key) {
87
- messages.removeObject(emsg);
88
- if (this.get("currentMessage") === emsg) {
89
- // TODO would updateFromJson() work here?
90
- this.set("currentMessage", nmsg);
91
- nmsg.set("selected", emsg.get("selected"));
80
+ if (data.messages.length > 0) {
81
+ const newRows = this.toMessages(data.messages);
82
+ const messages = this.get("messages");
83
+ if (opts.before) {
84
+ messages.unshiftObjects(newRows);
85
+ } else {
86
+ newRows.forEach(nmsg => {
87
+ messages.forEach(emsg => {
88
+ if (emsg.key == nmsg.key) {
89
+ messages.removeObject(emsg);
90
+ if (this.get("currentMessage") === emsg) {
91
+ // TODO would updateFromJson() work here?
92
+ this.set("currentMessage", nmsg);
93
+ nmsg.set("selected", emsg.get("selected"));
94
+ }
92
95
  }
93
- }
96
+ });
94
97
  });
95
- });
96
- messages.addObjects(newRows);
97
- if (newRows.length > 0) {
98
- increaseTitleCount(newRows.length);
98
+ messages.addObjects(newRows);
99
+ if (newRows.length > 0) {
100
+ increaseTitleCount(newRows.length);
101
+ }
99
102
  }
100
103
  }
101
- }
102
- this.set("total", data.total);
103
- return data;
104
- });
104
+ this.set("total", data.total);
105
+ return data;
106
+ })
107
+ .always(() => this.set("loading", false));
105
108
  },
106
109
 
107
110
  reload() {
@@ -18,6 +18,9 @@ export default Route.extend({
18
18
  let backoff = 1;
19
19
 
20
20
  this.refreshInterval = setInterval(() => {
21
+ if (model.loading) {
22
+ return;
23
+ }
21
24
  times += 1;
22
25
  const hidden = isHidden();
23
26
  let load = !hidden;
@@ -1,5 +1,5 @@
1
1
  <div class="message-info">
2
- {{#tabbed-section}}
2
+ {{#tabbed-section onTabChange=(action "tabChanged")}}
3
3
  {{#tab-contents name="info" hint="show info" currentMessage=currentMessage}}
4
4
  {{#if showTitle}}
5
5
  <h3>Message
@@ -16,14 +16,18 @@
16
16
  {{/if}}
17
17
  <pre>{{currentMessage.backtrace}}</pre>
18
18
  {{/tab-contents}}
19
- {{#if currentMessage.env}}
20
- {{#tab-contents className="env" name="env" hint="show environment" currentMessage=currentMessage}}
19
+ {{#tab-contents className="env" name="env" hint="show environment" currentMessage=currentMessage }}
20
+ {{#if currentMessage.env}}
21
21
  {{#if showTitle}}
22
22
  <h3>Env</h3>
23
23
  {{/if}}
24
24
  {{env-tab message=currentMessage}}
25
- {{/tab-contents}}
26
- {{/if}}
25
+ {{else if loadingEnv}}
26
+ Loading env...
27
+ {{else}}
28
+ No env for this message.
29
+ {{/if}}
30
+ {{/tab-contents}}
27
31
  {{/tabbed-section}}
28
32
 
29
33
  {{#if currentMessage}}
@@ -17,8 +17,10 @@
17
17
  <div id="bottom-panel">
18
18
  {{message-info
19
19
  currentMessage=currentMessage
20
+ loadingEnv=loadingEnv
20
21
  removeMessage=(action "removeMessage")
21
22
  solveMessage=(action "solveMessage")
23
+ onTabChange=(action "tabChanged")
22
24
  actionsInMenu=actionsInMenu}}
23
25
 
24
26
  <div class="action-panel">
@@ -183,13 +183,12 @@ module Logster
183
183
  end
184
184
 
185
185
  if similar
186
- has_env = !similar.env.nil? && !similar.env.empty?
187
- if similar.count < Logster::MAX_GROUPING_LENGTH && !has_env
186
+ if similar.count < Logster::MAX_GROUPING_LENGTH
188
187
  similar.env = get_env(similar.key) || {}
189
188
  end
190
189
  save_env = similar.merge_similar_message(message)
191
190
 
192
- replace_and_bump(similar, save_env: save_env || has_env)
191
+ replace_and_bump(similar, save_env: save_env)
193
192
  similar
194
193
  else
195
194
  save message
@@ -11,7 +11,8 @@ module Logster
11
11
  :enable_js_error_reporting,
12
12
  :environments,
13
13
  :rate_limit_error_reporting,
14
- :web_title
14
+ :web_title,
15
+ :maximum_message_size_bytes
15
16
  )
16
17
 
17
18
  attr_writer :subdirectory
@@ -25,6 +26,7 @@ module Logster
25
26
  @enable_custom_patterns_via_ui = false
26
27
  @rate_limit_error_reporting = true
27
28
  @enable_js_error_reporting = true
29
+ @maximum_message_size_bytes = 60_000
28
30
 
29
31
  @allow_grouping = false
30
32
 
@@ -4,6 +4,7 @@ require 'securerandom'
4
4
  module Logster
5
5
 
6
6
  MAX_GROUPING_LENGTH = 50
7
+ MAX_MESSAGE_LENGTH = 600
7
8
 
8
9
  class Message
9
10
  LOGSTER_ENV = "_logster_env".freeze
@@ -21,13 +22,14 @@ module Logster
21
22
  application_version
22
23
  }
23
24
 
24
- attr_accessor :timestamp, :severity, :progname, :message, :key, :backtrace, :count, :env, :protected, :first_timestamp
25
+ attr_accessor :timestamp, :severity, :progname, :key, :backtrace, :count, :protected, :first_timestamp
26
+ attr_reader :message, :env
25
27
 
26
28
  def initialize(severity, progname, message, timestamp = nil, key = nil, count: 1)
27
29
  @timestamp = timestamp || get_timestamp
28
30
  @severity = severity
29
31
  @progname = progname
30
- @message = message
32
+ @message = truncate_message(message)
31
33
  @key = key || SecureRandom.hex
32
34
  @backtrace = nil
33
35
  @count = count || 1
@@ -53,6 +55,10 @@ module Logster
53
55
  h
54
56
  end
55
57
 
58
+ def message=(m)
59
+ @message = truncate_message(m)
60
+ end
61
+
56
62
  def to_json(opts = nil)
57
63
  exclude_env = Hash === opts && opts.delete(:exclude_env)
58
64
  JSON.fast_generate(to_h(exclude_env: exclude_env), opts)
@@ -74,6 +80,7 @@ module Logster
74
80
  end
75
81
 
76
82
  def env=(env)
83
+ @env_json = nil
77
84
  @env = self.class.scrub_params(env)
78
85
  end
79
86
 
@@ -90,6 +97,7 @@ module Logster
90
97
  else
91
98
  env = self.class.default_env.merge(env)
92
99
  end
100
+ @env_json = nil
93
101
  @env = Message.populate_from_env(env)
94
102
  end
95
103
 
@@ -140,6 +148,10 @@ module Logster
140
148
  self.count += other.count || 1
141
149
  return false if self.count > Logster::MAX_GROUPING_LENGTH
142
150
 
151
+ size = self.to_json(exclude_env: true).bytesize + self.env_json.bytesize
152
+ extra_env_size = other.env_json.bytesize
153
+ return false if size + extra_env_size > Logster.config.maximum_message_size_bytes
154
+
143
155
  other_env = JSON.load JSON.fast_generate other.env
144
156
  if Hash === other_env && !other_env.key?("time")
145
157
  other_env["time"] = other.timestamp
@@ -153,6 +165,7 @@ module Logster
153
165
  else
154
166
  Array === other_env ? self.env = [self.env, *other_env] : self.env = [self.env, other_env]
155
167
  end
168
+ @env_json = nil
156
169
  true
157
170
  end
158
171
 
@@ -214,6 +227,10 @@ module Logster
214
227
  end
215
228
  end
216
229
 
230
+ def env_json
231
+ @env_json ||= (self.env || {}).to_json
232
+ end
233
+
217
234
  def self.scrub_params(params)
218
235
  if Array === params
219
236
  params.map! { |p| scrub_params(p) }
@@ -233,6 +250,11 @@ module Logster
233
250
 
234
251
  protected
235
252
 
253
+ def truncate_message(msg)
254
+ return msg unless msg
255
+ msg.size <= MAX_MESSAGE_LENGTH ? msg : msg[0...MAX_MESSAGE_LENGTH] + "..."
256
+ end
257
+
236
258
  def get_timestamp
237
259
  (Time.new.to_f * 1000).to_i
238
260
  end
@@ -156,6 +156,14 @@ module Logster
156
156
  [200, {}, ["OK"]]
157
157
  elsif resource == "/"
158
158
  [200, { "Content-Type" => "text/html; charset=utf-8" }, [body(preload_json)]]
159
+ elsif resource =~ /\/fetch-env\/([0-9a-f]+)\.json$/
160
+ key = $1
161
+ env = Logster.store.get_env(key)
162
+ if env
163
+ [200, { "Content-Type" => "application/json; charset=utf-8" }, [JSON.generate(env)]]
164
+ else
165
+ not_found
166
+ end
159
167
  else
160
168
  not_found
161
169
  end
@@ -190,6 +198,8 @@ module Logster
190
198
  search = (parse_regex(search) || search) if params["regex_search"] == "true"
191
199
  opts[:search] = search
192
200
  end
201
+ search = opts[:search]
202
+ opts[:with_env] = (String === search && search.size > 0) || Regexp === search
193
203
 
194
204
  payload = {
195
205
  messages: @store.latest(opts),
@@ -24,6 +24,7 @@ module Logster
24
24
  return true if @redis.hget(solved_key, solved)
25
25
  end
26
26
  end
27
+ apply_max_size_limit(message)
27
28
 
28
29
  @redis.multi do
29
30
  @redis.hset(grouping_key, message.grouping_key, message.key)
@@ -64,7 +65,7 @@ module Logster
64
65
 
65
66
  @redis.multi do
66
67
  @redis.hset(hash_key, message.key, message.to_json(exclude_env: true))
67
- @redis.hset(env_key, message.key, (message.env || {}).to_json) if save_env
68
+ @redis.hset(env_key, message.key, message.env_json) if save_env
68
69
  @redis.lrem(list_key, -1, message.key)
69
70
  @redis.rpush(list_key, message.key)
70
71
  end
@@ -98,6 +99,7 @@ module Logster
98
99
  before = opts[:before]
99
100
  after = opts[:after]
100
101
  search = opts[:search]
102
+ with_env = opts.key?(:with_env) ? opts[:with_env] : true
101
103
 
102
104
  start, finish = find_location(before, after, limit)
103
105
 
@@ -110,7 +112,7 @@ module Logster
110
112
  begin
111
113
  keys = @redis.lrange(list_key, start, finish) || []
112
114
  break unless keys && (keys.count > 0)
113
- rows = bulk_get(keys)
115
+ rows = bulk_get(keys, with_env: with_env)
114
116
 
115
117
  temp = []
116
118
 
@@ -204,14 +206,16 @@ module Logster
204
206
  bulk_get(@redis.lrange(list_key, 0, -1))
205
207
  end
206
208
 
207
- def bulk_get(message_keys)
208
- envs = @redis.hmget(env_key, message_keys)
209
- @redis.hmget(hash_key, message_keys).map!.with_index do |json, ind|
209
+ def bulk_get(message_keys, with_env: true)
210
+ envs = @redis.mapped_hmget(env_key, *message_keys) if with_env
211
+ @redis.hmget(hash_key, message_keys).map! do |json|
210
212
  message = Message.from_json(json)
211
- env = envs[ind]
212
- if !message.env || message.env.size == 0
213
- env = env && env.size > 0 ? ::JSON.parse(env) : {}
214
- message.env = env
213
+ if with_env
214
+ env = envs[message.key]
215
+ if !message.env || message.env.size == 0
216
+ env = env && env.size > 0 ? ::JSON.parse(env) : {}
217
+ message.env = env
218
+ end
215
219
  end
216
220
  message
217
221
  end
@@ -337,7 +341,7 @@ module Logster
337
341
 
338
342
  def update_message(message)
339
343
  @redis.hset(hash_key, message.key, message.to_json(exclude_env: true))
340
- @redis.hset(env_key, message.key, (message.env || {}).to_json)
344
+ @redis.hset(env_key, message.key, message.env_json)
341
345
  if message.protected
342
346
  @redis.sadd(protected_key, message.key)
343
347
  else
@@ -513,6 +517,22 @@ module Logster
513
517
 
514
518
  private
515
519
 
520
+ def apply_max_size_limit(message)
521
+ size = message.to_json(exclude_env: true).bytesize
522
+ env_size = message.env_json.bytesize
523
+ max_size = Logster.config.maximum_message_size_bytes
524
+ if size + env_size > max_size
525
+ # env is most likely the reason for the large size
526
+ # truncate it so the overall size is < the limit
527
+ if Array === message.env
528
+ # the - 1 at the end ensures the size goes a little bit below the limit
529
+ truncate_at = (message.env.size.to_f * max_size.to_f / (env_size + size)).to_i - 1
530
+ truncate_at = 1 if truncate_at < 1
531
+ message.env = message.env[0...truncate_at]
532
+ end
533
+ end
534
+ end
535
+
516
536
  def register_rate_limit(severities, limit, duration, callback)
517
537
  severities = [severities] unless severities.is_a?(Array)
518
538
  redis = (@redis_raw_connection && @redis_prefix) ? @redis_raw_connection : @redis
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Logster
4
- VERSION = "2.4.0"
4
+ VERSION = "2.4.1"
5
5
  end
@@ -328,4 +328,44 @@ class TestViewer < Minitest::Test
328
328
  assert_equal(404, response.status, "#{path} should have 404'ed")
329
329
  end
330
330
  end
331
+
332
+ def test_messages_endpoint_doesnt_include_envs_when_search_term_absent
333
+ Logster.store.clear_all
334
+ env = { "b" => 1, "c" => 2 }
335
+ msg = Logster.store.report(Logger::INFO, "test", "something hello", env: env)
336
+ response = request.get("/logsie/messages.json")
337
+ assert_equal(200, response.status)
338
+ messages = JSON.parse(response.body)["messages"]
339
+ assert_equal(1, messages.size)
340
+ msg = messages.first
341
+ assert_equal("something hello", msg["message"])
342
+ assert_nil(msg["env"])
343
+ end
344
+
345
+ def test_messages_endpoint_includes_env_when_there_is_search_term
346
+ Logster.store.clear_all
347
+ env = { "b" => 1, "c" => 2 }
348
+ msg = Logster.store.report(Logger::INFO, "test", "something hello", env: env)
349
+ response = request.get("/logsie/messages.json?search=something")
350
+ assert_equal(200, response.status)
351
+ messages = JSON.parse(response.body)["messages"]
352
+ assert_equal(1, messages.size)
353
+ msg = messages.first
354
+ assert_equal("something hello", msg["message"])
355
+ assert_includes(msg["env"].values, 1, 2)
356
+ end
357
+
358
+ def test_fetch_env_returns_env_associated_with_message
359
+ env = { "b" => 1, "c" => 2 }
360
+ msg = Logster.store.report(Logger::INFO, "test", "something whatever store", env: env)
361
+ response = request.get("/logsie/fetch-env/#{msg.key}.json")
362
+ assert_equal(200, response.status)
363
+ res = JSON.parse(response.body)
364
+ assert_includes(res.values, 1, 2)
365
+ end
366
+
367
+ def test_fetch_env_returns_404_when_invalid_key
368
+ response = request.get("/logsie/fetch-env/123456abc.json")
369
+ assert_equal(404, response.status)
370
+ end
331
371
  end
@@ -148,4 +148,28 @@ class TestMessage < MiniTest::Test
148
148
  assert_includes(msg.to_json, test_hash.to_json)
149
149
  refute_includes(msg.to_json(exclude_env: true), test_hash.to_json)
150
150
  end
151
+
152
+ def test_title_is_truncated_when_too_large
153
+ msg = Logster::Message.new(0, "", "a" * 1000)
154
+ # 3 is the ... at the end to indicate truncated message
155
+ assert_equal(600 + 3, msg.message.size)
156
+ end
157
+
158
+ def test_env_is_not_merged_into_similar_message_if_size_will_be_too_large
159
+ default = Logster.config.maximum_message_size_bytes
160
+ Logster.config.maximum_message_size_bytes = 1000
161
+ message = Logster::Message.new(Logger::INFO, "test", "message", count: 13)
162
+ env = [{ key1: "this is my first key", key2: "this is my second key" }] * 13
163
+ message.env = env
164
+
165
+ message2 = Logster::Message.new(Logger::INFO, "test", "message")
166
+ message2.env = env.first
167
+ message.merge_similar_message(message2)
168
+
169
+ # env isn't merged, but count is incremented
170
+ assert_equal(13, message.env.size)
171
+ assert_equal(14, message.count)
172
+ ensure
173
+ Logster.config.maximum_message_size_bytes = default
174
+ end
151
175
  end
@@ -705,6 +705,21 @@ class TestRedisStore < Minitest::Test
705
705
  end
706
706
  end
707
707
 
708
+ def test_store_trims_too_big_envs
709
+ default = Logster.config.maximum_message_size_bytes
710
+ Logster.config.maximum_message_size_bytes = 1000
711
+ message = Logster::Message.new(Logger::INFO, "test", "message")
712
+ env = [{ key1: "this is my first key", key2: "this is my second key" }] * 40
713
+ message.env = env
714
+ @store.save(message)
715
+ trimmed_message = @store.latest.first
716
+ assert_equal(13, trimmed_message.env.size)
717
+ size = message.to_json(exclude_env: true).bytesize + message.env_json.bytesize
718
+ assert_operator(1000, :>, size)
719
+ ensure
720
+ Logster.config.maximum_message_size_bytes = default
721
+ end
722
+
708
723
  private
709
724
 
710
725
  def reset_redis
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logster
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.0
4
+ version: 2.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - UI for viewing logs in Rack
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-10 00:00:00.000000000 Z
11
+ date: 2019-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler