rack-mini-profiler 2.2.0 → 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +5 -4
- data/lib/html/includes.js +209 -181
- data/lib/mini_profiler/asset_version.rb +1 -1
- data/lib/mini_profiler/config.rb +3 -1
- data/lib/mini_profiler/snapshots_transporter.rb +31 -6
- data/lib/mini_profiler/version.rb +1 -1
- data/rack-mini-profiler.gemspec +3 -3
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24c598b577f43c0c0e9b1a35cdd187383d99ac139eb345f2fa013f3aaf64b8b7
|
4
|
+
data.tar.gz: f825e2da4a72520d2b932b743f7a842d591c07ece8925db303c76851d04dcb3c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 627fe9b6795ea764316c04c0953d3bb686961ec7cca449aadb1a97901d41d3e40d79d9131f0291aec7921e51a447bb15b77e2c9dff92df14a8e1cbfde71d469d
|
7
|
+
data.tar.gz: 9e47290fb3bf24d312ef9d9d7e3d60a9db968f39b40229a48a81a354152822cce7d0bb072c09427f1a1d63b811aa6e48c398ff96a9dd20126f7e512bd2dbce15
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 2.2.1 - 2020-12-23
|
4
|
+
|
5
|
+
- [FIX] Turbolinks integration causing increasing number of GET requests
|
6
|
+
- [FEATURE] enahanced log transporter with compression and exponential backoff
|
7
|
+
- [FEATURE] sameSite=Lax added to MiniProfiler cookie
|
8
|
+
|
3
9
|
## 2.2.0 - 2020-10-19
|
4
10
|
|
5
11
|
- [UX] Enhancements to snapshots UI
|
data/README.md
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# rack-mini-profiler
|
2
2
|
|
3
|
-
[![Code Climate](https://codeclimate.com/github/MiniProfiler/rack-mini-profiler/badges/gpa.svg)](https://codeclimate.com/github/MiniProfiler/rack-mini-profiler) [![Build Status](https://travis-ci.org/MiniProfiler/rack-mini-profiler.svg)](https://travis-ci.org/MiniProfiler/rack-mini-profiler)
|
4
|
-
|
5
3
|
Middleware that displays speed badge for every html page. Designed to work both in production and in development.
|
6
4
|
|
7
5
|
#### Features
|
@@ -202,9 +200,11 @@ Mini Profiler will keep a maximum of 1000 snapshots by default, and you can chan
|
|
202
200
|
|
203
201
|
Mini Profiler can be configured so that it sends snapshots over HTTP using the snapshots transporter. The main use-case of the transporter is to allow the aggregation of snapshots from multiple applications/sources in a single place. To enable the snapshots transporter, you need to provide a destination URL to the `snapshots_transport_destination_url` config, and a secure key to the `snapshots_transport_auth_key` config (will be used for authorization). Both of these configs are required for the transporter to be enabled.
|
204
202
|
|
205
|
-
The transporter uses a buffer to temporarily hold snapshots in memory with a limit of 100 snapshots. Every
|
203
|
+
The transporter uses a buffer to temporarily hold snapshots in memory with a limit of 100 snapshots. Every 30 seconds, *if* the buffer is not empty, the transporter will make a `POST` request with the buffer content to the destination URL. Requests made by the transporter will have a `Mini-Profiler-Transport-Auth` header with the value of the `snapshots_transport_auth_key` config. The destination should only accept requests that include this header AND the header's value matches the key you set to the `snapshots_transport_auth_key` config.
|
204
|
+
|
205
|
+
If the specified destination responds with a non-200 status code, the transporter will increase the interval between requests by `2^n` seconds where `n` is the number of failed requests since the last successful request. The base interval between requests is 30 seconds. So if a request fails, the next request will be `30 + 2^1 = 32` seconds later. If the next request fails too, the next one will be `30 + 2^2 = 34` seconds later and so on until a request succeeds at which point the interval will return to 30 seconds. The interval will not go beyond 1 hour.
|
206
206
|
|
207
|
-
The body of the requests
|
207
|
+
Requests made by the transporter can be optionally gzip-compressed by setting the `snapshots_transport_gzip_requests` config to true. The body of the requests (after decompression, if you opt for compression) is a JSON string with a single top-level key called `snapshots` and it has an array of snapshots. The structure of a snapshot is too complex to be explained here, but it has the same structure that Mini Profiler client expects. So if your use-case is to simply be able to view snapshots from multiple sources in one place, you should simply store the snapshots as-is, and then serve them to Mini Profiler client to consume. If the destination application also has Mini Profiler, you can simply use the API of the storage backends to store the incoming snapshots and Mini Profiler will treat them the same as local snapshots (e.g. they'll be grouped and displayed in the same manner described in the previous section).
|
208
208
|
|
209
209
|
Mini Profiler offers an API to add extra fields (a.k.a custom fields) to snapshots. For example, you may want to add whether the request was made by a logged-in or anonymous user, the version of your application or any other things that are specific to your application. To add custom fields to a snapshot, call the `Rack::MiniProfiler.add_snapshot_custom_field(<key>, <value>)` method anywhere during the lifetime of a request, and the snapshot of that request will include the fields you added. If you have a Rails app, you can call that method in an `after_action` callback. Custom fields are cleared between requests.
|
210
210
|
|
@@ -398,6 +398,7 @@ snapshot_hidden_custom_fields|`[]`|Each snapshot custom field will have a dedica
|
|
398
398
|
snapshots_transport_destination_url|`nil`|Set this config to a valid URL to enable snapshots transporter which will `POST` snapshots to the given URL. The transporter requires `snapshots_transport_auth_key` config to be set as well.
|
399
399
|
snapshots_transport_auth_key|`nil`|`POST` requests made by the snapshots transporter to the destination URL will have a `Mini-Profiler-Transport-Auth` header with the value of this config. Make sure you use a secure and random key for this config.
|
400
400
|
snapshots_redact_sql_queries|`true`|When this is true, SQL queries will be redacted from sampling snapshots, but the backtrace and duration of each SQL query will be saved with the snapshot to keep debugging performance issues possible.
|
401
|
+
snapshots_transport_gzip_requests|`false`|Make the snapshots transporter gzip the requests it makes to `snapshots_transport_destination_url`.
|
401
402
|
|
402
403
|
### Using MiniProfiler with `Rack::Deflate` middleware
|
403
404
|
|
data/lib/html/includes.js
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
"use strict";
|
2
2
|
|
3
|
-
var
|
3
|
+
var _MiniProfiler = (function() {
|
4
4
|
var _arguments = arguments;
|
5
5
|
var options,
|
6
6
|
container,
|
7
7
|
controls,
|
8
|
-
fetchedIds = [],
|
9
|
-
fetchingIds =
|
8
|
+
fetchedIds = (window.MiniProfiler && window.MiniProfiler.fetchedIds) || [],
|
9
|
+
fetchingIds =
|
10
|
+
(window.MiniProfiler && window.MiniProfiler.fetchingIds) || [],
|
10
11
|
// so we never pull down a profiler twice
|
11
12
|
ajaxStartTime,
|
12
13
|
totalsControl,
|
@@ -634,6 +635,10 @@ var MiniProfiler = (function() {
|
|
634
635
|
}
|
635
636
|
};
|
636
637
|
|
638
|
+
var turbolinksSkipResultsFetch = function turbolinksSkipResultsFetch(event) {
|
639
|
+
event.data.xhr.__miniProfilerSkipResultsFetch = true;
|
640
|
+
};
|
641
|
+
|
637
642
|
var bindDocumentEvents = function bindDocumentEvents() {
|
638
643
|
document.addEventListener("click", onClickEvents);
|
639
644
|
document.addEventListener("keyup", onClickEvents);
|
@@ -642,6 +647,10 @@ var MiniProfiler = (function() {
|
|
642
647
|
if (typeof Turbolinks !== "undefined" && Turbolinks.supported) {
|
643
648
|
document.addEventListener("page:change", unbindDocumentEvents);
|
644
649
|
document.addEventListener("turbolinks:load", unbindDocumentEvents);
|
650
|
+
document.addEventListener(
|
651
|
+
"turbolinks:request-start",
|
652
|
+
turbolinksSkipResultsFetch
|
653
|
+
);
|
645
654
|
}
|
646
655
|
};
|
647
656
|
|
@@ -651,6 +660,10 @@ var MiniProfiler = (function() {
|
|
651
660
|
document.removeEventListener("keyup", toggleShortcutEvent);
|
652
661
|
document.removeEventListener("page:change", unbindDocumentEvents);
|
653
662
|
document.removeEventListener("turbolinks:load", unbindDocumentEvents);
|
663
|
+
document.removeEventListener(
|
664
|
+
"turbolinks:request-start",
|
665
|
+
turbolinksSkipResultsFetch
|
666
|
+
);
|
654
667
|
};
|
655
668
|
|
656
669
|
var initFullView = function initFullView() {
|
@@ -680,10 +693,12 @@ var MiniProfiler = (function() {
|
|
680
693
|
temp.innerHTML = MiniProfiler.templates.snapshotsGroupsList(data);
|
681
694
|
} else if (data.group_name) {
|
682
695
|
var allCustomFieldsNames = [];
|
683
|
-
data.list.forEach(function
|
684
|
-
Object.keys(snapshot.custom_fields).forEach(function
|
685
|
-
if (
|
686
|
-
|
696
|
+
data.list.forEach(function(snapshot) {
|
697
|
+
Object.keys(snapshot.custom_fields).forEach(function(k) {
|
698
|
+
if (
|
699
|
+
allCustomFieldsNames.indexOf(k) === -1 &&
|
700
|
+
options.hiddenCustomFields.indexOf(k.toLowerCase()) === -1
|
701
|
+
) {
|
687
702
|
allCustomFieldsNames.push(k);
|
688
703
|
}
|
689
704
|
});
|
@@ -694,7 +709,7 @@ var MiniProfiler = (function() {
|
|
694
709
|
allCustomFieldsNames: allCustomFieldsNames
|
695
710
|
});
|
696
711
|
}
|
697
|
-
Array.from(temp.children).forEach(function
|
712
|
+
Array.from(temp.children).forEach(function(child) {
|
698
713
|
document.body.appendChild(child);
|
699
714
|
});
|
700
715
|
};
|
@@ -767,213 +782,220 @@ var MiniProfiler = (function() {
|
|
767
782
|
fetchResults(options.ids);
|
768
783
|
}
|
769
784
|
|
770
|
-
|
771
|
-
|
772
|
-
XMLHttpRequest.prototype.send = function(data) {
|
773
|
-
ajaxStartTime = new Date();
|
774
|
-
this.addEventListener("load", function() {
|
775
|
-
// responseURL isn't available in IE11
|
776
|
-
if (
|
777
|
-
this.responseURL &&
|
778
|
-
this.responseURL.indexOf(window.location.origin) !== 0
|
779
|
-
) {
|
780
|
-
return;
|
781
|
-
}
|
782
|
-
// getAllResponseHeaders isn't available in Edge.
|
783
|
-
var allHeaders = this.getAllResponseHeaders
|
784
|
-
? this.getAllResponseHeaders()
|
785
|
-
: null;
|
786
|
-
if (
|
787
|
-
allHeaders &&
|
788
|
-
allHeaders.toLowerCase().indexOf("x-miniprofiler-ids") === -1
|
789
|
-
) {
|
790
|
-
return;
|
791
|
-
}
|
792
|
-
// should be a string of comma-separated ids
|
793
|
-
var stringIds = this.getResponseHeader("X-MiniProfiler-Ids");
|
794
|
-
|
795
|
-
if (stringIds) {
|
796
|
-
var ids = stringIds.split(",");
|
797
|
-
fetchResults(ids);
|
798
|
-
}
|
799
|
-
});
|
800
|
-
send.call(this, data);
|
801
|
-
}; // fetch results after ASP Ajax calls
|
802
|
-
|
803
|
-
if (
|
804
|
-
typeof Sys != "undefined" &&
|
805
|
-
typeof Sys.WebForms != "undefined" &&
|
806
|
-
typeof Sys.WebForms.PageRequestManager != "undefined"
|
807
|
-
) {
|
808
|
-
// Get the instance of PageRequestManager.
|
809
|
-
var PageRequestManager = Sys.WebForms.PageRequestManager.getInstance();
|
810
|
-
PageRequestManager.add_endRequest(function(sender, args) {
|
811
|
-
if (args) {
|
812
|
-
var response = args.get_response();
|
785
|
+
if (!window.MiniProfiler || !window.MiniProfiler.patchesApplied) {
|
786
|
+
var send = XMLHttpRequest.prototype.send;
|
813
787
|
|
788
|
+
XMLHttpRequest.prototype.send = function(data) {
|
789
|
+
ajaxStartTime = new Date();
|
790
|
+
this.addEventListener("load", function() {
|
791
|
+
// responseURL isn't available in IE11
|
814
792
|
if (
|
815
|
-
|
816
|
-
|
793
|
+
this.responseURL &&
|
794
|
+
this.responseURL.indexOf(window.location.origin) !== 0
|
817
795
|
) {
|
818
|
-
|
819
|
-
.get_response()
|
820
|
-
.getResponseHeader("X-MiniProfiler-Ids");
|
821
|
-
|
822
|
-
if (stringIds) {
|
823
|
-
var ids = stringIds.split(",");
|
824
|
-
fetchResults(ids);
|
825
|
-
}
|
796
|
+
return;
|
826
797
|
}
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
798
|
+
if (this.__miniProfilerSkipResultsFetch) {
|
799
|
+
return;
|
800
|
+
}
|
801
|
+
// getAllResponseHeaders isn't available in Edge.
|
802
|
+
var allHeaders = this.getAllResponseHeaders
|
803
|
+
? this.getAllResponseHeaders()
|
804
|
+
: null;
|
805
|
+
if (
|
806
|
+
allHeaders &&
|
807
|
+
allHeaders.toLowerCase().indexOf("x-miniprofiler-ids") === -1
|
808
|
+
) {
|
809
|
+
return;
|
810
|
+
}
|
811
|
+
// should be a string of comma-separated ids
|
812
|
+
var stringIds = this.getResponseHeader("X-MiniProfiler-Ids");
|
840
813
|
|
841
814
|
if (stringIds) {
|
842
815
|
var ids = stringIds.split(",");
|
843
816
|
fetchResults(ids);
|
844
817
|
}
|
845
|
-
};
|
846
|
-
|
847
|
-
|
818
|
+
});
|
819
|
+
send.call(this, data);
|
820
|
+
}; // fetch results after ASP Ajax calls
|
848
821
|
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
822
|
+
if (
|
823
|
+
typeof Sys != "undefined" &&
|
824
|
+
typeof Sys.WebForms != "undefined" &&
|
825
|
+
typeof Sys.WebForms.PageRequestManager != "undefined"
|
826
|
+
) {
|
827
|
+
// Get the instance of PageRequestManager.
|
828
|
+
var PageRequestManager = Sys.WebForms.PageRequestManager.getInstance();
|
829
|
+
PageRequestManager.add_endRequest(function(sender, args) {
|
830
|
+
if (args) {
|
831
|
+
var response = args.get_response();
|
832
|
+
|
833
|
+
if (
|
834
|
+
response.get_responseAvailable() &&
|
835
|
+
response._xmlHttpRequest !== null
|
836
|
+
) {
|
837
|
+
var stringIds = args
|
838
|
+
.get_response()
|
839
|
+
.getResponseHeader("X-MiniProfiler-Ids");
|
840
|
+
|
841
|
+
if (stringIds) {
|
842
|
+
var ids = stringIds.split(",");
|
843
|
+
fetchResults(ids);
|
844
|
+
}
|
845
|
+
}
|
846
|
+
}
|
847
|
+
});
|
848
|
+
} // more Asp.Net callbacks
|
849
|
+
|
850
|
+
if (typeof WebForm_ExecuteCallback == "function") {
|
851
|
+
WebForm_ExecuteCallback = (function(callbackObject) {
|
852
|
+
// Store original function
|
853
|
+
var original = WebForm_ExecuteCallback;
|
854
|
+
return function(callbackObject) {
|
855
|
+
original(callbackObject);
|
856
|
+
var stringIds = callbackObject.xmlRequest.getResponseHeader(
|
857
|
+
"X-MiniProfiler-Ids"
|
858
|
+
);
|
860
859
|
|
861
|
-
|
860
|
+
if (stringIds) {
|
861
|
+
var ids = stringIds.split(",");
|
862
|
+
fetchResults(ids);
|
863
|
+
}
|
864
|
+
};
|
865
|
+
})();
|
866
|
+
} // also fetch results after ExtJS requests, in case it is being used
|
862
867
|
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
868
|
+
if (
|
869
|
+
typeof Ext != "undefined" &&
|
870
|
+
typeof Ext.Ajax != "undefined" &&
|
871
|
+
typeof Ext.Ajax.on != "undefined"
|
872
|
+
) {
|
873
|
+
// Ext.Ajax is a singleton, so we just have to attach to its 'requestcomplete' event
|
874
|
+
Ext.Ajax.on("requestcomplete", function(e, xhr, settings) {
|
875
|
+
//iframed file uploads don't have headers
|
876
|
+
if (!xhr || !xhr.getResponseHeader) {
|
877
|
+
return;
|
878
|
+
}
|
869
879
|
|
870
|
-
|
871
|
-
Request.prototype.addEvents({
|
872
|
-
onComplete: function onComplete() {
|
873
|
-
var stringIds = this.xhr.getResponseHeader("X-MiniProfiler-Ids");
|
880
|
+
var stringIds = xhr.getResponseHeader("X-MiniProfiler-Ids");
|
874
881
|
|
875
882
|
if (stringIds) {
|
876
883
|
var ids = stringIds.split(",");
|
877
884
|
fetchResults(ids);
|
878
885
|
}
|
879
|
-
}
|
880
|
-
}
|
881
|
-
} // add support for AngularJS, which use the basic XMLHttpRequest object.
|
882
|
-
|
883
|
-
if (window.angular && typeof XMLHttpRequest != "undefined") {
|
884
|
-
var _send = XMLHttpRequest.prototype.send;
|
885
|
-
|
886
|
-
XMLHttpRequest.prototype.send = function sendReplacement(data) {
|
887
|
-
if (this.onreadystatechange) {
|
888
|
-
if (
|
889
|
-
typeof this.miniprofiler == "undefined" ||
|
890
|
-
typeof this.miniprofiler.prev_onreadystatechange == "undefined"
|
891
|
-
) {
|
892
|
-
this.miniprofiler = {
|
893
|
-
prev_onreadystatechange: this.onreadystatechange
|
894
|
-
};
|
886
|
+
});
|
887
|
+
}
|
895
888
|
|
896
|
-
|
897
|
-
|
898
|
-
|
889
|
+
if (typeof MooTools != "undefined" && typeof Request != "undefined") {
|
890
|
+
Request.prototype.addEvents({
|
891
|
+
onComplete: function onComplete() {
|
892
|
+
var stringIds = this.xhr.getResponseHeader("X-MiniProfiler-Ids");
|
899
893
|
|
900
|
-
|
901
|
-
|
902
|
-
|
894
|
+
if (stringIds) {
|
895
|
+
var ids = stringIds.split(",");
|
896
|
+
fetchResults(ids);
|
897
|
+
}
|
898
|
+
}
|
899
|
+
});
|
900
|
+
} // add support for AngularJS, which use the basic XMLHttpRequest object.
|
901
|
+
|
902
|
+
if (window.angular && typeof XMLHttpRequest != "undefined") {
|
903
|
+
var _send = XMLHttpRequest.prototype.send;
|
904
|
+
|
905
|
+
XMLHttpRequest.prototype.send = function sendReplacement(data) {
|
906
|
+
if (this.onreadystatechange) {
|
907
|
+
if (
|
908
|
+
typeof this.miniprofiler == "undefined" ||
|
909
|
+
typeof this.miniprofiler.prev_onreadystatechange == "undefined"
|
910
|
+
) {
|
911
|
+
this.miniprofiler = {
|
912
|
+
prev_onreadystatechange: this.onreadystatechange
|
913
|
+
};
|
914
|
+
|
915
|
+
this.onreadystatechange = function onReadyStateChangeReplacement() {
|
916
|
+
if (this.readyState == 4) {
|
917
|
+
var stringIds = this.getResponseHeader("X-MiniProfiler-Ids");
|
918
|
+
|
919
|
+
if (stringIds) {
|
920
|
+
var ids = stringIds.split(",");
|
921
|
+
fetchResults(ids);
|
922
|
+
}
|
903
923
|
}
|
904
|
-
}
|
905
924
|
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
925
|
+
if (this.miniprofiler.prev_onreadystatechange !== null)
|
926
|
+
return this.miniprofiler.prev_onreadystatechange.apply(
|
927
|
+
this,
|
928
|
+
arguments
|
929
|
+
);
|
930
|
+
};
|
931
|
+
}
|
912
932
|
}
|
913
|
-
}
|
914
|
-
|
915
|
-
return _send.apply(this, arguments);
|
916
|
-
};
|
917
|
-
} // https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
|
918
933
|
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
) {
|
923
|
-
var __originalFetch = window.fetch;
|
934
|
+
return _send.apply(this, arguments);
|
935
|
+
};
|
936
|
+
} // https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
|
924
937
|
|
925
|
-
window.fetch
|
926
|
-
var
|
938
|
+
if (typeof window.fetch === "function") {
|
939
|
+
var __originalFetch = window.fetch;
|
927
940
|
|
928
|
-
|
929
|
-
|
930
|
-
// look for x-mini-profile-ids
|
931
|
-
var entries = response.headers.entries();
|
932
|
-
var _iteratorNormalCompletion = true;
|
933
|
-
var _didIteratorError = false;
|
934
|
-
var _iteratorError = undefined;
|
941
|
+
window.fetch = function(input, init) {
|
942
|
+
var originalFetchRun = __originalFetch(input, init);
|
935
943
|
|
944
|
+
originalFetchRun.then(function(response) {
|
936
945
|
try {
|
937
|
-
for
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
if (pair[0] && pair[0].toLowerCase() == "x-miniprofiler-ids") {
|
945
|
-
var ids = pair[1].split(",");
|
946
|
-
fetchResults(ids);
|
947
|
-
}
|
948
|
-
}
|
949
|
-
} catch (err) {
|
950
|
-
_didIteratorError = true;
|
951
|
-
_iteratorError = err;
|
952
|
-
} finally {
|
946
|
+
// look for x-mini-profile-ids
|
947
|
+
var entries = response.headers.entries();
|
948
|
+
var _iteratorNormalCompletion = true;
|
949
|
+
var _didIteratorError = false;
|
950
|
+
var _iteratorError = undefined;
|
951
|
+
|
953
952
|
try {
|
954
|
-
|
955
|
-
_iterator.
|
953
|
+
for (
|
954
|
+
var _iterator = entries[Symbol.iterator](), _step;
|
955
|
+
!(_iteratorNormalCompletion = (_step = _iterator.next())
|
956
|
+
.done);
|
957
|
+
_iteratorNormalCompletion = true
|
958
|
+
) {
|
959
|
+
var pair = _step.value;
|
960
|
+
|
961
|
+
if (
|
962
|
+
pair[0] &&
|
963
|
+
pair[0].toLowerCase() == "x-miniprofiler-ids"
|
964
|
+
) {
|
965
|
+
var ids = pair[1].split(",");
|
966
|
+
fetchResults(ids);
|
967
|
+
}
|
956
968
|
}
|
969
|
+
} catch (err) {
|
970
|
+
_didIteratorError = true;
|
971
|
+
_iteratorError = err;
|
957
972
|
} finally {
|
958
|
-
|
959
|
-
|
973
|
+
try {
|
974
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
975
|
+
_iterator.return();
|
976
|
+
}
|
977
|
+
} finally {
|
978
|
+
if (_didIteratorError) {
|
979
|
+
throw _iteratorError;
|
980
|
+
}
|
960
981
|
}
|
961
982
|
}
|
983
|
+
} catch (e) {
|
984
|
+
console.error(e);
|
962
985
|
}
|
963
|
-
}
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
window.fetch.__patchedByMiniProfiler = true;
|
971
|
-
} // some elements want to be hidden on certain doc events
|
986
|
+
});
|
987
|
+
return originalFetchRun;
|
988
|
+
};
|
989
|
+
}
|
990
|
+
window.MiniProfiler.patchesApplied = true;
|
991
|
+
}
|
972
992
|
|
973
993
|
bindDocumentEvents();
|
974
994
|
};
|
975
995
|
|
976
996
|
return {
|
997
|
+
fetchedIds: fetchedIds,
|
998
|
+
fetchingIds: fetchingIds,
|
977
999
|
init: function init() {
|
978
1000
|
var script = document.getElementById("mini-profiler");
|
979
1001
|
if (!script || !script.getAttribute) return;
|
@@ -1007,7 +1029,10 @@ var MiniProfiler = (function() {
|
|
1007
1029
|
sessionStorage["rack-mini-profiler-start-hidden"] === "true";
|
1008
1030
|
var htmlContainer = script.getAttribute("data-html-container");
|
1009
1031
|
var cssUrl = script.getAttribute("data-css-url");
|
1010
|
-
var hiddenCustomFields = script
|
1032
|
+
var hiddenCustomFields = script
|
1033
|
+
.getAttribute("data-hidden-custom-fields")
|
1034
|
+
.toLowerCase()
|
1035
|
+
.split(",");
|
1011
1036
|
return {
|
1012
1037
|
ids: ids,
|
1013
1038
|
path: path,
|
@@ -1432,7 +1457,7 @@ var MiniProfiler = (function() {
|
|
1432
1457
|
return options.showTotalSqlCount;
|
1433
1458
|
},
|
1434
1459
|
timestampToRelative: function timestampToRelative(timestamp) {
|
1435
|
-
var now = Math.round(
|
1460
|
+
var now = Math.round(new Date().getTime() / 1000);
|
1436
1461
|
timestamp = Math.round(timestamp / 1000);
|
1437
1462
|
var diff = now - timestamp;
|
1438
1463
|
if (diff < 60) {
|
@@ -1444,7 +1469,7 @@ var MiniProfiler = (function() {
|
|
1444
1469
|
res += "s";
|
1445
1470
|
}
|
1446
1471
|
return res;
|
1447
|
-
}
|
1472
|
+
};
|
1448
1473
|
diff = Math.round(diff / 60);
|
1449
1474
|
if (diff <= 60) {
|
1450
1475
|
return buildDisplayTime(diff, "minute");
|
@@ -1459,5 +1484,8 @@ var MiniProfiler = (function() {
|
|
1459
1484
|
};
|
1460
1485
|
})();
|
1461
1486
|
|
1462
|
-
window.MiniProfiler
|
1463
|
-
MiniProfiler.
|
1487
|
+
if (window.MiniProfiler) {
|
1488
|
+
_MiniProfiler.patchesApplied = window.MiniProfiler.patchesApplied;
|
1489
|
+
}
|
1490
|
+
window.MiniProfiler = _MiniProfiler;
|
1491
|
+
_MiniProfiler.init();
|
data/lib/mini_profiler/config.rb
CHANGED
@@ -56,6 +56,7 @@ module Rack
|
|
56
56
|
@snapshots_transport_destination_url = nil
|
57
57
|
@snapshots_transport_auth_key = nil
|
58
58
|
@snapshots_redact_sql_queries = true
|
59
|
+
@snapshots_transport_gzip_requests = false
|
59
60
|
|
60
61
|
self
|
61
62
|
}
|
@@ -77,7 +78,8 @@ module Rack
|
|
77
78
|
# snapshot related config
|
78
79
|
attr_accessor :snapshot_every_n_requests, :snapshots_limit,
|
79
80
|
:snapshot_hidden_custom_fields, :snapshots_transport_destination_url,
|
80
|
-
:snapshots_transport_auth_key, :snapshots_redact_sql_queries
|
81
|
+
:snapshots_transport_auth_key, :snapshots_redact_sql_queries,
|
82
|
+
:snapshots_transport_gzip_requests
|
81
83
|
|
82
84
|
# Deprecated options
|
83
85
|
attr_accessor :use_existing_jquery
|
@@ -23,16 +23,18 @@ class ::Rack::MiniProfiler::SnapshotsTransporter
|
|
23
23
|
end
|
24
24
|
|
25
25
|
attr_reader :buffer
|
26
|
-
attr_accessor :max_buffer_size
|
26
|
+
attr_accessor :max_buffer_size, :gzip_requests
|
27
27
|
|
28
28
|
def initialize(config)
|
29
29
|
@uri = URI(config.snapshots_transport_destination_url)
|
30
30
|
@auth_key = config.snapshots_transport_auth_key
|
31
|
+
@gzip_requests = config.snapshots_transport_gzip_requests
|
31
32
|
@thread = nil
|
32
33
|
@thread_mutex = Mutex.new
|
33
34
|
@buffer = []
|
34
35
|
@buffer_mutex = Mutex.new
|
35
36
|
@max_buffer_size = 100
|
37
|
+
@consecutive_failures_count = 0
|
36
38
|
@testing = false
|
37
39
|
end
|
38
40
|
|
@@ -49,12 +51,24 @@ class ::Rack::MiniProfiler::SnapshotsTransporter
|
|
49
51
|
@buffer.dup if @buffer.size > 0
|
50
52
|
end
|
51
53
|
if buffer_content
|
52
|
-
|
53
|
-
@uri,
|
54
|
+
headers = {
|
54
55
|
'Content-Type' => 'application/json',
|
55
56
|
'Mini-Profiler-Transport-Auth' => @auth_key
|
56
|
-
|
57
|
-
|
57
|
+
}
|
58
|
+
json = { snapshots: buffer_content }.to_json
|
59
|
+
body = if @gzip_requests
|
60
|
+
require 'zlib'
|
61
|
+
io = StringIO.new
|
62
|
+
gzip_writer = Zlib::GzipWriter.new(io)
|
63
|
+
gzip_writer.write(json)
|
64
|
+
gzip_writer.close
|
65
|
+
headers['Content-Encoding'] = 'gzip'
|
66
|
+
io.string
|
67
|
+
else
|
68
|
+
json
|
69
|
+
end
|
70
|
+
request = Net::HTTP::Post.new(@uri, headers)
|
71
|
+
request.body = body
|
58
72
|
http = Net::HTTP.new(@uri.hostname, @uri.port)
|
59
73
|
http.use_ssl = @uri.scheme == 'https'
|
60
74
|
res = http.request(request)
|
@@ -64,19 +78,30 @@ class ::Rack::MiniProfiler::SnapshotsTransporter
|
|
64
78
|
@buffer_mutex.synchronize do
|
65
79
|
@buffer -= buffer_content
|
66
80
|
end
|
81
|
+
@consecutive_failures_count = 0
|
67
82
|
else
|
68
83
|
@@failed_http_requests_count += 1
|
84
|
+
@consecutive_failures_count += 1
|
69
85
|
end
|
70
86
|
end
|
71
87
|
end
|
72
88
|
|
89
|
+
def requests_interval
|
90
|
+
[30 + backoff_delay, 60 * 60].min
|
91
|
+
end
|
92
|
+
|
73
93
|
private
|
74
94
|
|
95
|
+
def backoff_delay
|
96
|
+
return 0 if @consecutive_failures_count == 0
|
97
|
+
2**@consecutive_failures_count
|
98
|
+
end
|
99
|
+
|
75
100
|
def start_thread
|
76
101
|
return if @thread&.alive? || @testing
|
77
102
|
@thread = Thread.new do
|
78
103
|
while true
|
79
|
-
sleep
|
104
|
+
sleep requests_interval
|
80
105
|
flush_buffer
|
81
106
|
end
|
82
107
|
end
|
data/rack-mini-profiler.gemspec
CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
|
|
28
28
|
'changelog_uri' => 'https://github.com/MiniProfiler/rack-mini-profiler/blob/master/CHANGELOG.md'
|
29
29
|
}
|
30
30
|
|
31
|
-
s.add_development_dependency 'rake'
|
31
|
+
s.add_development_dependency 'rake'
|
32
32
|
s.add_development_dependency 'rack-test'
|
33
33
|
s.add_development_dependency 'dalli'
|
34
34
|
s.add_development_dependency 'rspec', '~> 3.6.0'
|
@@ -40,8 +40,8 @@ Gem::Specification.new do |s|
|
|
40
40
|
s.add_development_dependency 'nokogiri'
|
41
41
|
s.add_development_dependency 'rubocop-discourse'
|
42
42
|
s.add_development_dependency 'listen'
|
43
|
-
s.add_development_dependency 'webpacker'
|
44
|
-
s.add_development_dependency 'rails', '~>
|
43
|
+
s.add_development_dependency 'webpacker'
|
44
|
+
s.add_development_dependency 'rails', '~> 6.0'
|
45
45
|
s.add_development_dependency 'webmock', '3.9.1'
|
46
46
|
|
47
47
|
s.require_paths = ["lib"]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-mini-profiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Saffron
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2020-
|
13
|
+
date: 2020-12-23 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rack
|
@@ -30,16 +30,16 @@ dependencies:
|
|
30
30
|
name: rake
|
31
31
|
requirement: !ruby/object:Gem::Requirement
|
32
32
|
requirements:
|
33
|
-
- - "
|
33
|
+
- - ">="
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version: '
|
35
|
+
version: '0'
|
36
36
|
type: :development
|
37
37
|
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
|
-
- - "
|
40
|
+
- - ">="
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: '
|
42
|
+
version: '0'
|
43
43
|
- !ruby/object:Gem::Dependency
|
44
44
|
name: rack-test
|
45
45
|
requirement: !ruby/object:Gem::Requirement
|
@@ -198,30 +198,30 @@ dependencies:
|
|
198
198
|
name: webpacker
|
199
199
|
requirement: !ruby/object:Gem::Requirement
|
200
200
|
requirements:
|
201
|
-
- - "
|
201
|
+
- - ">="
|
202
202
|
- !ruby/object:Gem::Version
|
203
|
-
version: '
|
203
|
+
version: '0'
|
204
204
|
type: :development
|
205
205
|
prerelease: false
|
206
206
|
version_requirements: !ruby/object:Gem::Requirement
|
207
207
|
requirements:
|
208
|
-
- - "
|
208
|
+
- - ">="
|
209
209
|
- !ruby/object:Gem::Version
|
210
|
-
version: '
|
210
|
+
version: '0'
|
211
211
|
- !ruby/object:Gem::Dependency
|
212
212
|
name: rails
|
213
213
|
requirement: !ruby/object:Gem::Requirement
|
214
214
|
requirements:
|
215
215
|
- - "~>"
|
216
216
|
- !ruby/object:Gem::Version
|
217
|
-
version: '
|
217
|
+
version: '6.0'
|
218
218
|
type: :development
|
219
219
|
prerelease: false
|
220
220
|
version_requirements: !ruby/object:Gem::Requirement
|
221
221
|
requirements:
|
222
222
|
- - "~>"
|
223
223
|
- !ruby/object:Gem::Version
|
224
|
-
version: '
|
224
|
+
version: '6.0'
|
225
225
|
- !ruby/object:Gem::Dependency
|
226
226
|
name: webmock
|
227
227
|
requirement: !ruby/object:Gem::Requirement
|
@@ -322,7 +322,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
322
322
|
- !ruby/object:Gem::Version
|
323
323
|
version: '0'
|
324
324
|
requirements: []
|
325
|
-
rubygems_version: 3.
|
325
|
+
rubygems_version: 3.2.2
|
326
326
|
signing_key:
|
327
327
|
specification_version: 4
|
328
328
|
summary: Profiles loading speed for rack applications.
|