tailog 0.3.7 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/ansi_up.js +8 -8
- data/app/assets/javascripts/jquery.highlight.js +152 -0
- data/app/assets/stylesheets/application.css +26 -0
- data/app/views/layout.erb +1 -0
- data/app/views/logs/index.erb +74 -8
- data/lib/tailog/eval.rb +36 -0
- data/lib/tailog/request_id.rb +24 -0
- data/lib/tailog/version.rb +1 -1
- data/lib/tailog/watch_methods.rb +69 -53
- data/lib/tailog.rb +3 -1
- data/tailog.gemspec +2 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e059546fe3ba51e4d77e16ecec8e8415849af454
|
4
|
+
data.tar.gz: b3ae7620423132949c16eb327e5f8e56a280fb89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0afce3b55d7d34d91819a52a356846e58db3eb6ddc4e72e31b3240c76371a4b2bd93207d983247a0ab5734da94ae4089bd68ac9f3cf10fce201944eab14106bb
|
7
|
+
data.tar.gz: 143514a5dba6dd0519d1633961d7d44f52e92e60ceecde7108ac82a7cee2aa1c0555e5f4b97326e707e6eef4e7c7f705f8001b2e334560b0c59464b5b49b885a
|
@@ -15,14 +15,14 @@
|
|
15
15
|
// Normal and then Bright
|
16
16
|
ANSI_COLORS = [
|
17
17
|
[
|
18
|
-
{ color: "
|
19
|
-
{ color: "
|
20
|
-
{ color: "
|
21
|
-
{ color: "
|
22
|
-
{ color: "
|
23
|
-
{ color: "
|
24
|
-
{ color: "
|
25
|
-
{ color: "
|
18
|
+
{ color: "27, 27, 27", 'class': "ansi-black" },
|
19
|
+
{ color: "182, 80, 47", 'class': "ansi-red" },
|
20
|
+
{ color: "141, 161, 88", 'class': "ansi-green" },
|
21
|
+
{ color: "220, 175, 95", 'class': "ansi-yellow" },
|
22
|
+
{ color: "126, 170, 199", 'class': "ansi-blue" },
|
23
|
+
{ color: "176, 101, 152", 'class': "ansi-magenta" },
|
24
|
+
{ color: "141, 220, 217", 'class': "ansi-cyan" },
|
25
|
+
{ color: "217, 217, 217", 'class': "ansi-white" }
|
26
26
|
], [
|
27
27
|
{ color: "27, 27, 27", 'class': "ansi-bright-black" },
|
28
28
|
{ color: "182, 80, 47", 'class': "ansi-bright-red" },
|
@@ -0,0 +1,152 @@
|
|
1
|
+
/*
|
2
|
+
* jQuery Highlight plugin
|
3
|
+
*
|
4
|
+
* Based on highlight v3 by Johann Burkard
|
5
|
+
* http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
|
6
|
+
*
|
7
|
+
* Code a little bit refactored and cleaned (in my humble opinion).
|
8
|
+
* Most important changes:
|
9
|
+
* - has an option to highlight only entire words (wordsOnly - false by default),
|
10
|
+
* - has an option to be case sensitive (caseSensitive - false by default)
|
11
|
+
* - highlight element tag and class names can be specified in options
|
12
|
+
*
|
13
|
+
* Usage:
|
14
|
+
* // wrap every occurrence of text 'lorem' in content
|
15
|
+
* // with <span class='highlight'> (default options)
|
16
|
+
* $('#content').highlight('lorem');
|
17
|
+
*
|
18
|
+
* // search for and highlight more terms at once
|
19
|
+
* // so you can save some time on traversing DOM
|
20
|
+
* $('#content').highlight(['lorem', 'ipsum']);
|
21
|
+
* $('#content').highlight('lorem ipsum');
|
22
|
+
*
|
23
|
+
* // search only for entire word 'lorem'
|
24
|
+
* $('#content').highlight('lorem', { wordsOnly: true });
|
25
|
+
*
|
26
|
+
* // search only for the entire word 'C#'
|
27
|
+
* // and make sure that the word boundary can also
|
28
|
+
* // be a 'non-word' character, as well as a regex latin1 only boundary:
|
29
|
+
* $('#content').highlight('C#', { wordsOnly: true , wordsBoundary: '[\\b\\W]' });
|
30
|
+
*
|
31
|
+
* // don't ignore case during search of term 'lorem'
|
32
|
+
* $('#content').highlight('lorem', { caseSensitive: true });
|
33
|
+
*
|
34
|
+
* // wrap every occurrence of term 'ipsum' in content
|
35
|
+
* // with <em class='important'>
|
36
|
+
* $('#content').highlight('ipsum', { element: 'em', className: 'important' });
|
37
|
+
*
|
38
|
+
* // remove default highlight
|
39
|
+
* $('#content').unhighlight();
|
40
|
+
*
|
41
|
+
* // remove custom highlight
|
42
|
+
* $('#content').unhighlight({ element: 'em', className: 'important' });
|
43
|
+
*
|
44
|
+
*
|
45
|
+
* Copyright (c) 2009 Bartek Szopka
|
46
|
+
*
|
47
|
+
* Licensed under MIT license.
|
48
|
+
*
|
49
|
+
*/
|
50
|
+
|
51
|
+
(function (factory) {
|
52
|
+
if (typeof define === 'function' && define.amd) {
|
53
|
+
// AMD. Register as an anonymous module.
|
54
|
+
define(['jquery'], factory);
|
55
|
+
} else if (typeof exports === 'object') {
|
56
|
+
// Node/CommonJS
|
57
|
+
factory(require('jquery'));
|
58
|
+
} else {
|
59
|
+
// Browser globals
|
60
|
+
factory(jQuery);
|
61
|
+
}
|
62
|
+
}(function (jQuery) {
|
63
|
+
jQuery.extend({
|
64
|
+
highlight: function (node, re, nodeName, className) {
|
65
|
+
if (node.nodeType === 3) {
|
66
|
+
var match = node.data.match(re);
|
67
|
+
if (match) {
|
68
|
+
// The new highlight Element Node
|
69
|
+
var highlight = document.createElement(nodeName || 'span');
|
70
|
+
highlight.className = className || 'highlight';
|
71
|
+
// Note that we use the captured value to find the real index
|
72
|
+
// of the match. This is because we do not want to include the matching word boundaries
|
73
|
+
var capturePos = node.data.indexOf( match[1] , match.index );
|
74
|
+
|
75
|
+
// Split the node and replace the matching wordnode
|
76
|
+
// with the highlighted node
|
77
|
+
var wordNode = node.splitText(capturePos);
|
78
|
+
wordNode.splitText(match[1].length);
|
79
|
+
|
80
|
+
var wordClone = wordNode.cloneNode(true);
|
81
|
+
highlight.appendChild(wordClone);
|
82
|
+
wordNode.parentNode.replaceChild(highlight, wordNode);
|
83
|
+
return 1; //skip added node in parent
|
84
|
+
}
|
85
|
+
} else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
|
86
|
+
!/(script|style)/i.test(node.tagName) && // ignore script and style nodes
|
87
|
+
!(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
|
88
|
+
for (var i = 0; i < node.childNodes.length; i++) {
|
89
|
+
i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
return 0;
|
93
|
+
}
|
94
|
+
});
|
95
|
+
|
96
|
+
jQuery.fn.unhighlight = function (options) {
|
97
|
+
var settings = {
|
98
|
+
className: 'highlight',
|
99
|
+
element: 'span'
|
100
|
+
};
|
101
|
+
|
102
|
+
jQuery.extend(settings, options);
|
103
|
+
|
104
|
+
return this.find(settings.element + '.' + settings.className).each(function () {
|
105
|
+
var parent = this.parentNode;
|
106
|
+
parent.replaceChild(this.firstChild, this);
|
107
|
+
parent.normalize();
|
108
|
+
}).end();
|
109
|
+
};
|
110
|
+
|
111
|
+
jQuery.fn.highlight = function (words, options) {
|
112
|
+
var settings = {
|
113
|
+
className: 'highlight',
|
114
|
+
element: 'span',
|
115
|
+
caseSensitive: false,
|
116
|
+
wordsOnly: false,
|
117
|
+
wordsBoundary: '\\b'
|
118
|
+
};
|
119
|
+
|
120
|
+
jQuery.extend(settings, options);
|
121
|
+
|
122
|
+
if (typeof words === 'string') {
|
123
|
+
words = [words];
|
124
|
+
}
|
125
|
+
words = jQuery.grep(words, function(word, i){
|
126
|
+
return word != '';
|
127
|
+
});
|
128
|
+
words = jQuery.map(words, function(word, i) {
|
129
|
+
return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
130
|
+
});
|
131
|
+
|
132
|
+
if (words.length === 0) {
|
133
|
+
return this;
|
134
|
+
};
|
135
|
+
|
136
|
+
var flag = settings.caseSensitive ? '' : 'i';
|
137
|
+
// The capture parenthesis will make sure we can match
|
138
|
+
// only the matching word
|
139
|
+
var pattern = '(' + words.join('|') + ')';
|
140
|
+
if (settings.wordsOnly) {
|
141
|
+
pattern =
|
142
|
+
(settings.wordsBoundaryStart || settings.wordsBoundary) +
|
143
|
+
pattern +
|
144
|
+
(settings.wordsBoundaryEnd || settings.wordsBoundary);
|
145
|
+
}
|
146
|
+
var re = new RegExp(pattern, flag);
|
147
|
+
|
148
|
+
return this.each(function () {
|
149
|
+
jQuery.highlight(this, re, settings.element, settings.className);
|
150
|
+
});
|
151
|
+
};
|
152
|
+
}));
|
@@ -9,6 +9,28 @@ p {
|
|
9
9
|
margin: 0;
|
10
10
|
}
|
11
11
|
|
12
|
+
.fixed-top-right {
|
13
|
+
position: fixed;
|
14
|
+
top: 25px;
|
15
|
+
right: 25px;
|
16
|
+
}
|
17
|
+
|
18
|
+
.settings-panel {
|
19
|
+
margin-top: 50px;
|
20
|
+
width: 320px;
|
21
|
+
box-shadow: 0 6px 12px rgba(0,0,0,.175);
|
22
|
+
}
|
23
|
+
|
24
|
+
.highlight-list {
|
25
|
+
margin-top: 5px;
|
26
|
+
}
|
27
|
+
|
28
|
+
.highlight-list span {
|
29
|
+
cursor: pointer;
|
30
|
+
margin-right: 5px;
|
31
|
+
font-size: 12px;
|
32
|
+
}
|
33
|
+
|
12
34
|
.content-hover p:hover {
|
13
35
|
background: #EEE;
|
14
36
|
}
|
@@ -37,3 +59,7 @@ p {
|
|
37
59
|
color: #a94442;
|
38
60
|
border-bottom: 3px dashed #d9534f;
|
39
61
|
}
|
62
|
+
|
63
|
+
.highlight {
|
64
|
+
background: #FFFF88;
|
65
|
+
}
|
data/app/views/layout.erb
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>
|
6
6
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/3.51/jquery.form.js"></script>
|
7
7
|
<script type="text/javascript" src="javascripts/ansi_up.js"></script>
|
8
|
+
<script type="text/javascript" src="javascripts/jquery.highlight.js"></script>
|
8
9
|
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css">
|
9
10
|
<link rel="stylesheet" type="text/css" href="stylesheets/application.css">
|
10
11
|
</head>
|
data/app/views/logs/index.erb
CHANGED
@@ -7,23 +7,83 @@
|
|
7
7
|
<h3 class="page-header"><%= file_path %></h3>
|
8
8
|
|
9
9
|
<% File.open file_path do |file| %>
|
10
|
-
<div id="content" class="content-hover"></div>
|
10
|
+
<div id="content" class="content content-hover"></div>
|
11
11
|
<% end %>
|
12
12
|
|
13
|
-
<a id="
|
13
|
+
<a id="settings-toggle" class="btn btn-primary fixed-top-right"><i class="glyphicon glyphicon-cog"></i></a>
|
14
|
+
|
15
|
+
<div id="settings-panel" class="panel panel-info fixed-top-right settings-panel hidden">
|
16
|
+
<div class="panel-heading">Settings</div>
|
17
|
+
<div class="panel-body">
|
18
|
+
<div class="form-group btn-group">
|
19
|
+
<a id="add-divider" class="btn btn-default">Add Divider</a>
|
20
|
+
<a id="clear-logs" class="btn btn-default">Clear Logs</a>
|
21
|
+
</div>
|
22
|
+
<div class="form-group">
|
23
|
+
<div class="input-group">
|
24
|
+
<input id="highlight" type="text" class="form-control" placeholder="Keyword">
|
25
|
+
<span class="input-group-btn">
|
26
|
+
<button id="add-highlight" class="btn btn-default" type="button">Highlight!</button>
|
27
|
+
</span>
|
28
|
+
</div>
|
29
|
+
<div id="highlight-list" class="highlight-list"></div>
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
</div>
|
14
33
|
|
15
34
|
<script type="text/javascript">
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
$content = $("#content");
|
35
|
+
var $settingsPanel = $("#settings-panel");
|
36
|
+
$("#settings-toggle").click(function() {
|
37
|
+
$settingsPanel.toggleClass("hidden");
|
38
|
+
});
|
21
39
|
|
22
40
|
var dividerId = 1;
|
23
|
-
$("#
|
41
|
+
$("#add-divider").click(function() {
|
24
42
|
$content.append('<span class="divider"> #' + dividerId++ + ' - ' + new Date() + '</span>');
|
25
43
|
});
|
26
44
|
|
45
|
+
$("#clear-logs").click(function() {
|
46
|
+
$content.html('');
|
47
|
+
});
|
48
|
+
|
49
|
+
var $highlight = $("#highlight"),
|
50
|
+
$highlightList = $("#highlight-list");
|
51
|
+
|
52
|
+
function rawHighlight(keyword) {
|
53
|
+
$content.highlight(keyword, { className: 'highlight highlight-' + keyword });
|
54
|
+
}
|
55
|
+
|
56
|
+
function rawUnhighlight(keyword) {
|
57
|
+
$content.unhighlight({ className: 'highlight-' + keyword });
|
58
|
+
}
|
59
|
+
|
60
|
+
function highlight(keyword) {
|
61
|
+
if ($highlightList.find('.highlight-' + keyword).length > 0) return;
|
62
|
+
rawHighlight(keyword);
|
63
|
+
$highlightList.append('<span class="label label-primary highlight-' + keyword + ' toggle-highlight">' + keyword + '</span>');
|
64
|
+
}
|
65
|
+
|
66
|
+
$highlight.keypress(function(event) {
|
67
|
+
if ((event.keyCode || event.which) === 13) {
|
68
|
+
highlight($highlight.val());
|
69
|
+
}
|
70
|
+
});
|
71
|
+
$("#add-highlight").click(function() {
|
72
|
+
highlight($highlight.val());
|
73
|
+
});
|
74
|
+
|
75
|
+
$("#highlight-list").on("click", ".toggle-highlight", function(event) {
|
76
|
+
var $this = $(this),
|
77
|
+
keyword = $this.text();
|
78
|
+
$this.data('hidden') ? rawHighlight(keyword) : rawUnhighlight(keyword);
|
79
|
+
$this.data('hidden', !$this.data('hidden'));
|
80
|
+
});
|
81
|
+
|
82
|
+
window.fileSize = {};
|
83
|
+
window.fileSizeDone = {};
|
84
|
+
var $window = $(window),
|
85
|
+
$document = $(document),
|
86
|
+
$content = $("#content");
|
27
87
|
function loadMore() {
|
28
88
|
$.post(window.location.href, { seek: window.fileSize }, function(json) {
|
29
89
|
try {
|
@@ -36,10 +96,16 @@
|
|
36
96
|
|
37
97
|
if (!data.content) return;
|
38
98
|
var shouldScrollToBottom = $window.scrollTop() + $window.height() == $document.height();
|
99
|
+
|
39
100
|
$content
|
40
101
|
.append('<span class="text-info">' + data.server_hostname + ' - ' + data.file_size + '</span>')
|
41
102
|
.append(ansi_up.ansi_to_html(data.content));
|
42
103
|
|
104
|
+
$highlightList.find("span").each(function(index, node) {
|
105
|
+
var $node = $(node);
|
106
|
+
$node.data('hidden') || rawHighlight($node.text());
|
107
|
+
});
|
108
|
+
|
43
109
|
if (shouldScrollToBottom) {
|
44
110
|
$window.scrollTop($document.height() - $window.height());
|
45
111
|
}
|
data/lib/tailog/eval.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Tailog
|
2
|
+
class Eval
|
3
|
+
class << self
|
4
|
+
attr_accessor :blacklist
|
5
|
+
end
|
6
|
+
|
7
|
+
self.blacklist = %w(/tailog)
|
8
|
+
|
9
|
+
def initialize app
|
10
|
+
@app = app
|
11
|
+
end
|
12
|
+
|
13
|
+
def call env
|
14
|
+
if skip_call? env
|
15
|
+
@app.call(env)
|
16
|
+
else
|
17
|
+
before = env["HTTP_TAILOG_EVAL_BEFORE"].presence
|
18
|
+
after = env["HTTP_TAILOG_EVAL_AFTER"].presence
|
19
|
+
|
20
|
+
eval before if before
|
21
|
+
response = @app.call(env)
|
22
|
+
eval after if after
|
23
|
+
|
24
|
+
response
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def skip_call? env
|
31
|
+
Tailog::Eval.blacklist.any? do |path|
|
32
|
+
env["PATH_INFO"].start_with? path
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Tailog
|
2
|
+
class RequestId
|
3
|
+
def initialize app
|
4
|
+
@app = app
|
5
|
+
end
|
6
|
+
|
7
|
+
def call env
|
8
|
+
Tailog.request_id = external_request_id(env) || internal_request_id
|
9
|
+
@app.call(env).tap do |_status, headers, _body|
|
10
|
+
headers["X-Request-Id"] = Tailog.request_id
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def external_request_id env
|
17
|
+
env["HTTP_X_REQUEST_ID"].presence
|
18
|
+
end
|
19
|
+
|
20
|
+
def internal_request_id
|
21
|
+
SecureRandom.uuid
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/tailog/version.rb
CHANGED
data/lib/tailog/watch_methods.rb
CHANGED
@@ -1,22 +1,17 @@
|
|
1
1
|
require 'active_support/core_ext/string'
|
2
|
-
require 'active_support/configurable'
|
3
2
|
require 'securerandom'
|
4
3
|
require 'logger'
|
5
4
|
|
6
5
|
module Tailog
|
7
6
|
module WatchMethods
|
8
|
-
include ActiveSupport::Configurable
|
9
|
-
|
10
7
|
class << self
|
11
|
-
attr_accessor :request_id
|
12
|
-
|
13
8
|
def logger
|
14
9
|
return @logger if @logger
|
15
10
|
@logger = Logger.new(File.join Tailog.log_path, "watch_methods.log")
|
16
11
|
@logger.formatter = proc do |severity, datetime, progname, message|
|
17
12
|
content = ""
|
18
13
|
content << "[#{datetime.strftime("%Y-%m-%d %H:%M:%S")}]"
|
19
|
-
content << "[#{Tailog
|
14
|
+
content << "[#{Tailog.request_id}]" if Tailog.request_id
|
20
15
|
content << " #{severity.rjust(5)}"
|
21
16
|
content << " (#{progname})" if progname
|
22
17
|
content << ": #{message.gsub(/\n\s*/, " ")}"
|
@@ -27,68 +22,63 @@ module Tailog
|
|
27
22
|
end
|
28
23
|
end
|
29
24
|
|
30
|
-
|
31
|
-
def initialize(app)
|
32
|
-
@app = app
|
33
|
-
end
|
34
|
-
|
35
|
-
def call(env)
|
36
|
-
Tailog::WatchMethods.request_id = external_request_id(env) || internal_request_id
|
37
|
-
@app.call(env).tap do |_status, headers, _body|
|
38
|
-
headers["X-Request-Id"] = Tailog::WatchMethods.request_id
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def external_request_id(env)
|
45
|
-
if request_id = env["HTTP_X_REQUEST_ID"].presence
|
46
|
-
request_id.gsub(/[^\w\-]/, "").first(255)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def internal_request_id
|
51
|
-
SecureRandom.uuid
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def inject_constants targets
|
25
|
+
def inject targets
|
56
26
|
targets.each do |target|
|
57
27
|
begin
|
58
|
-
target.
|
59
|
-
inject_instance_method
|
60
|
-
|
61
|
-
|
62
|
-
|
28
|
+
if target.include? "#"
|
29
|
+
inject_instance_method target
|
30
|
+
elsif target.include? "."
|
31
|
+
inject_class_method target
|
32
|
+
else
|
33
|
+
inject_constant target
|
63
34
|
end
|
64
35
|
rescue => error
|
65
|
-
WatchMethods.logger.error "Inject
|
36
|
+
WatchMethods.logger.error "Inject #{target} FAILED: #{error.class}: #{error.message}"
|
66
37
|
end
|
67
38
|
end
|
68
39
|
end
|
69
40
|
|
70
|
-
def
|
41
|
+
def cleanup targets
|
71
42
|
targets.each do |target|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
rescue => error
|
79
|
-
WatchMethods.logger.error "Inject method `#{target}' failed: #{error.class}: #{error.message}"
|
43
|
+
if target.include? "#"
|
44
|
+
cleanup_instance_method target
|
45
|
+
elsif target.include? "."
|
46
|
+
cleanup_class_method target
|
47
|
+
else
|
48
|
+
cleanup_constant target
|
80
49
|
end
|
81
50
|
end
|
82
51
|
end
|
83
52
|
|
84
53
|
private
|
85
54
|
|
55
|
+
RAW_METHOD_PREFIX = "watch_method_raw_"
|
56
|
+
|
57
|
+
def raw_method? method
|
58
|
+
method.to_s.start_with? RAW_METHOD_PREFIX
|
59
|
+
end
|
60
|
+
|
61
|
+
def inject_constant target
|
62
|
+
constant = target.constantize
|
63
|
+
constant.instance_methods(false).each do |method|
|
64
|
+
inject_instance_method "#{target}##{method}" unless raw_method? method
|
65
|
+
end
|
66
|
+
constant.methods(false).each do |method|
|
67
|
+
inject_class_method "#{target}.#{method}" unless raw_method? method
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def cleanup_constant target
|
72
|
+
target.constantize.instance_methods(false).each do |method|
|
73
|
+
cleanup_instance_method "#{target}##{method}" unless raw_method? method
|
74
|
+
end
|
75
|
+
target.constantize.methods(false).each do |method|
|
76
|
+
cleanup_class_method "#{target}.#{method}" unless raw_method? method
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
86
80
|
def inject_class_method target
|
87
|
-
klass, _, method =
|
88
|
-
target.rpartition(".")
|
89
|
-
else
|
90
|
-
target.rpartition("::")
|
91
|
-
end
|
81
|
+
klass, _, method = target.rpartition(".")
|
92
82
|
klass.constantize.class_eval <<-EOS, __FILE__, __LINE__
|
93
83
|
class << self
|
94
84
|
#{build_watch_method target, method}
|
@@ -96,6 +86,15 @@ module Tailog
|
|
96
86
|
EOS
|
97
87
|
end
|
98
88
|
|
89
|
+
def cleanup_class_method target
|
90
|
+
klass, _, method = target.rpartition(".")
|
91
|
+
klass.constantize.class_eval <<-EOS, __FILE__, __LINE__
|
92
|
+
class << self
|
93
|
+
#{build_cleanup_method target, method}
|
94
|
+
end
|
95
|
+
EOS
|
96
|
+
end
|
97
|
+
|
99
98
|
def inject_instance_method target
|
100
99
|
klass, _, method = target.rpartition("#")
|
101
100
|
klass.constantize.class_eval <<-EOS, __FILE__, __LINE__
|
@@ -103,8 +102,15 @@ module Tailog
|
|
103
102
|
EOS
|
104
103
|
end
|
105
104
|
|
105
|
+
def cleanup_instance_method target
|
106
|
+
klass, _, method = target.rpartition("#")
|
107
|
+
klass.constantize.class_eval <<-EOS, __FILE__, __LINE__
|
108
|
+
#{build_cleanup_method target, method}
|
109
|
+
EOS
|
110
|
+
end
|
111
|
+
|
106
112
|
def build_watch_method target, method
|
107
|
-
raw_method = "
|
113
|
+
raw_method = "#{RAW_METHOD_PREFIX}#{method}"
|
108
114
|
return <<-EOS
|
109
115
|
unless instance_methods.include?(:#{raw_method})
|
110
116
|
alias_method :#{raw_method}, :#{method}
|
@@ -124,5 +130,15 @@ module Tailog
|
|
124
130
|
end
|
125
131
|
EOS
|
126
132
|
end
|
133
|
+
|
134
|
+
def build_cleanup_method target, method
|
135
|
+
raw_method = "#{RAW_METHOD_PREFIX}#{method}"
|
136
|
+
return <<-EOS
|
137
|
+
if method_defined? :#{raw_method}
|
138
|
+
alias_method :#{method}, :#{raw_method}
|
139
|
+
remove_method :#{raw_method}
|
140
|
+
end
|
141
|
+
EOS
|
142
|
+
end
|
127
143
|
end
|
128
144
|
end
|
data/lib/tailog.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'tailog/version'
|
2
|
+
require 'tailog/eval'
|
3
|
+
require 'tailog/request_id'
|
2
4
|
require 'tailog/watch_methods'
|
3
5
|
require 'tailog/ext/file'
|
4
6
|
|
@@ -11,7 +13,7 @@ module Tailog
|
|
11
13
|
extend Tailog::WatchMethods
|
12
14
|
|
13
15
|
class << self
|
14
|
-
attr_accessor :log_path
|
16
|
+
attr_accessor :log_path, :request_id
|
15
17
|
|
16
18
|
def server_hostname
|
17
19
|
@server_hostname ||= Socket.gethostname
|
data/tailog.gemspec
CHANGED
@@ -27,6 +27,8 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
28
|
spec.require_paths = ["lib"]
|
29
29
|
|
30
|
+
spec.add_dependency "sinatra", "~> 1.4"
|
31
|
+
|
30
32
|
spec.add_development_dependency "bundler", "~> 1.11"
|
31
33
|
spec.add_development_dependency "rake", "~> 10.0"
|
32
34
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tailog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- bbtfr
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sinatra
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.4'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -51,6 +65,7 @@ files:
|
|
51
65
|
- README.md
|
52
66
|
- Rakefile
|
53
67
|
- app/assets/javascripts/ansi_up.js
|
68
|
+
- app/assets/javascripts/jquery.highlight.js
|
54
69
|
- app/assets/stylesheets/application.css
|
55
70
|
- app/views/env.erb
|
56
71
|
- app/views/error.erb
|
@@ -63,7 +78,9 @@ files:
|
|
63
78
|
- bin/console
|
64
79
|
- bin/setup
|
65
80
|
- lib/tailog.rb
|
81
|
+
- lib/tailog/eval.rb
|
66
82
|
- lib/tailog/ext/file.rb
|
83
|
+
- lib/tailog/request_id.rb
|
67
84
|
- lib/tailog/version.rb
|
68
85
|
- lib/tailog/watch_methods.rb
|
69
86
|
- tailog.gemspec
|