timmy 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/timmy/config_loader.rb +24 -0
- data/lib/timmy/logger.rb +36 -18
- data/lib/timmy/option_parser.rb +11 -25
- data/lib/timmy/runner.rb +56 -48
- data/lib/timmy/version.rb +1 -1
- data/lib/timmy.rb +8 -0
- metadata +2 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 22d313c4caa316badf7f3aa3a2dd286ca7409290
|
4
|
+
data.tar.gz: 79ed29b958c3b909f6ee30710d04029eb6349f70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86b21b72ed5bda63389081cf14a7bf185cc316ff85b564700c9df0d3470285726268f71e882ca0001994aa2da4dcc9dc513f5a6a7e5565a6307626429ae64852
|
7
|
+
data.tar.gz: c2a2ce42c84555784dbc00318e8a44a4da8082c4b85595e6b583ea5f845048f3a61c60c73b62a444348159e02b3f2a78a8450ccdb942ad746ea5e6c472c5e4ac
|
data/lib/timmy/config_loader.rb
CHANGED
@@ -10,5 +10,29 @@ module Timmy
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
13
|
+
|
14
|
+
def add_timer(id, start_regex:, stop_regex: nil)
|
15
|
+
TargetedTimerDefinition.add(id, start_regex: start_regex, stop_regex: stop_regex)
|
16
|
+
end
|
17
|
+
|
18
|
+
def delete_timer(id)
|
19
|
+
TargetedTimerDefinition.delete(id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_precision(precision)
|
23
|
+
Logger.set_precision(precision)
|
24
|
+
end
|
25
|
+
|
26
|
+
def set_logger_output_dir(dir)
|
27
|
+
Logger.set_output_dir(dir)
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_profile(profile)
|
31
|
+
Logger.set_profile(profile)
|
32
|
+
end
|
33
|
+
|
34
|
+
def set_replay_speed(speed)
|
35
|
+
Runner.set_replay_speed(speed)
|
36
|
+
end
|
13
37
|
end
|
14
38
|
end
|
data/lib/timmy/logger.rb
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
module Timmy
|
2
2
|
class Logger
|
3
3
|
class << self
|
4
|
-
def
|
5
|
-
@
|
4
|
+
def set_output_dir(dir)
|
5
|
+
@output_dir = File.expand_path(dir)
|
6
6
|
end
|
7
7
|
|
8
8
|
def set_precision(precision)
|
9
9
|
@precision = precision
|
10
10
|
end
|
11
11
|
|
12
|
+
def set_profile(profile)
|
13
|
+
@profile = profile
|
14
|
+
end
|
15
|
+
|
12
16
|
def put_output(output)
|
13
17
|
duration = MasterTimer.get
|
14
18
|
formatted_duration = format_duration(duration)
|
@@ -19,18 +23,39 @@ module Timmy
|
|
19
23
|
@output += sprintf("%.9f %s\n", duration, output)
|
20
24
|
end
|
21
25
|
|
26
|
+
def put_eof
|
27
|
+
put_output(feint("EOF"))
|
28
|
+
end
|
29
|
+
|
22
30
|
def put_timer(timer)
|
23
31
|
puts format_timer(timer)
|
24
32
|
end
|
25
33
|
|
26
|
-
def
|
27
|
-
|
34
|
+
def finalize
|
35
|
+
suffix = "#{MasterTimer.start.to_i}+#{MasterTimer.get.to_i}"
|
36
|
+
filename = File.join(output_dir, "timmy-#{suffix}.log")
|
37
|
+
header = sprintf("TIMMY-SESSION:v1:%.9f\n", MasterTimer.start)
|
38
|
+
|
39
|
+
File.write(filename, header + @output)
|
40
|
+
|
41
|
+
puts feint("Log written to #{filename}")
|
42
|
+
puts
|
43
|
+
|
44
|
+
put_profile if profile?
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
28
48
|
|
49
|
+
def put_profile
|
29
50
|
slowest_timers = TargetedTimerManager
|
30
51
|
.stopped
|
31
52
|
.sort_by { |timer| -timer.duration }
|
32
53
|
.slice(0, 10)
|
33
54
|
|
55
|
+
return unless slowest_timers.any?
|
56
|
+
|
57
|
+
puts "Slowest targeted timers:"
|
58
|
+
|
34
59
|
slowest_timers.each do |timer|
|
35
60
|
put_timer(timer)
|
36
61
|
end
|
@@ -38,18 +63,6 @@ module Timmy
|
|
38
63
|
puts
|
39
64
|
end
|
40
65
|
|
41
|
-
def finalize
|
42
|
-
suffix = "#{MasterTimer.start.to_i}+#{MasterTimer.get.to_i}"
|
43
|
-
filename = File.join(output_directory, "timmy-#{suffix}.log")
|
44
|
-
|
45
|
-
File.write(filename, @output)
|
46
|
-
|
47
|
-
puts feint("Log written to #{filename}")
|
48
|
-
puts
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
66
|
def format_timer(timer)
|
54
67
|
string = "#{bold(format_duration(timer.duration))} #{format_id(timer.definition.id)}"
|
55
68
|
string += " (#{timer.group})" if timer.group
|
@@ -79,13 +92,18 @@ module Timmy
|
|
79
92
|
"\e[0m\e[2m#{string}\e[0m"
|
80
93
|
end
|
81
94
|
|
82
|
-
def
|
83
|
-
@
|
95
|
+
def output_dir
|
96
|
+
@output_dir ||= "/tmp"
|
84
97
|
end
|
85
98
|
|
86
99
|
def precision
|
87
100
|
@precision ||= 0
|
88
101
|
end
|
102
|
+
|
103
|
+
def profile?
|
104
|
+
@profile = false if @profile == nil
|
105
|
+
@profile
|
106
|
+
end
|
89
107
|
end
|
90
108
|
end
|
91
109
|
end
|
data/lib/timmy/option_parser.rb
CHANGED
@@ -2,12 +2,7 @@ module Timmy
|
|
2
2
|
class OptionParser
|
3
3
|
class << self
|
4
4
|
def parse
|
5
|
-
|
6
|
-
replay: nil,
|
7
|
-
profile: false,
|
8
|
-
logger_output_directory: nil,
|
9
|
-
logger_precision: nil
|
10
|
-
}
|
5
|
+
opts = {}
|
11
6
|
|
12
7
|
::OptionParser.new do |parser|
|
13
8
|
parser.banner = <<-EOS
|
@@ -19,35 +14,26 @@ Pipe output from arbitrary command:
|
|
19
14
|
|
20
15
|
\e[36m[COMMAND] | timmy [OPTIONS]\e[0m
|
21
16
|
|
22
|
-
|
17
|
+
Replay previous session:
|
23
18
|
|
24
|
-
\e[
|
19
|
+
\e[36mcat [LOGFILE] | timmy [OPTIONS]\e[0m
|
25
20
|
EOS
|
26
21
|
|
27
22
|
parser.separator ""
|
28
23
|
parser.separator "\e[33mOptions:\e[0m"
|
29
24
|
parser.separator ""
|
30
25
|
|
31
|
-
parser.on("-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
parser.on("-
|
36
|
-
|
37
|
-
end
|
38
|
-
|
39
|
-
parser.on("--logger-output-dir DIR", "Save logs to different directory (default: \"/tmp\")") do |logger_output_directory|
|
40
|
-
options[:logger_output_directory] = logger_output_directory
|
41
|
-
end
|
42
|
-
|
43
|
-
parser.on("--logger-precision NUM", Integer, "Set precision used when printing time (default: 0)") do |logger_precision|
|
44
|
-
options[:logger_precision] = logger_precision
|
45
|
-
end
|
26
|
+
parser.on("-p", "--precision NUM", Integer,
|
27
|
+
"Set precision used when printing time (default: 0)")
|
28
|
+
parser.on("-r", "--[no-]profile",
|
29
|
+
"Profile slowest targeted timers (default: false)")
|
30
|
+
parser.on("-x", "--replay-speed NUM", Float,
|
31
|
+
"Replay with given speed (default: instant)")
|
46
32
|
|
47
33
|
parser.separator ""
|
48
|
-
end.parse!
|
34
|
+
end.parse!(into: opts)
|
49
35
|
|
50
|
-
|
36
|
+
opts.map { |key, value| [key.to_s.gsub('-', '_').to_sym, value] }.to_h
|
51
37
|
end
|
52
38
|
end
|
53
39
|
end
|
data/lib/timmy/runner.rb
CHANGED
@@ -1,74 +1,82 @@
|
|
1
1
|
module Timmy
|
2
2
|
class Runner
|
3
3
|
class << self
|
4
|
+
def set_replay_speed(speed)
|
5
|
+
@replay_speed = speed
|
6
|
+
end
|
7
|
+
|
4
8
|
def run
|
5
9
|
ConfigLoader.load
|
6
10
|
|
7
11
|
options = OptionParser.parse
|
12
|
+
replay_speed = options[:replay_speed] || @replay_speed
|
13
|
+
Logger.set_precision(options[:precision]) if options.key?(:precision)
|
14
|
+
Logger.set_profile(options[:profile]) if options.key?(:profile)
|
8
15
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
if value = options[:logger_precision]
|
14
|
-
Logger.set_precision(value)
|
15
|
-
end
|
16
|
+
self.new(replay_speed: replay_speed).consume_stdin
|
17
|
+
end
|
18
|
+
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
20
|
+
def initialize(replay_speed:)
|
21
|
+
@replay_speed = replay_speed
|
22
|
+
@last_replay_time = 0
|
23
|
+
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
def consume_stdin
|
26
|
+
around_run_lines do
|
27
|
+
STDIN.each_line do |line|
|
28
|
+
next if init_replay_mode(line)
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
-
|
30
|
+
if @replay_mode
|
31
|
+
replay_line(line)
|
32
|
+
else
|
31
33
|
run_line(line.rstrip)
|
32
34
|
end
|
33
|
-
Logger.put_output("EOF")
|
34
35
|
end
|
36
|
+
|
37
|
+
Logger.put_eof unless @replay_mode
|
35
38
|
end
|
39
|
+
end
|
36
40
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
run_line(match[:content])
|
47
|
-
elsif match = line.match(/^(?<s>\d+(\.\d+)?) (?<content>.*)/)
|
48
|
-
line_time = match[:s].to_f
|
49
|
-
MasterTimer.set(line_time)
|
50
|
-
run_line(match[:content])
|
51
|
-
end
|
52
|
-
end
|
41
|
+
private
|
42
|
+
|
43
|
+
def init_replay_mode(line)
|
44
|
+
if @replay_mode == nil
|
45
|
+
if (match = line.match(/^TIMMY-SESSION:v1:(?<s>\d+\.\d{9})$/))
|
46
|
+
MasterTimer.start(match[:s].to_f)
|
47
|
+
@replay_mode = true
|
48
|
+
else
|
49
|
+
@replay_mode = false
|
53
50
|
end
|
54
51
|
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def around_run_lines
|
55
|
+
MasterTimer.start
|
55
56
|
|
56
|
-
|
57
|
+
yield
|
57
58
|
|
58
|
-
|
59
|
-
|
59
|
+
TargetedTimerManager.stop_all
|
60
|
+
Logger.finalize
|
61
|
+
end
|
60
62
|
|
61
|
-
|
63
|
+
def replay_line(line)
|
64
|
+
line_match = line.match(/^(?<s>\d+(\.\d+)?) (?<content>.*)/)
|
65
|
+
line_time = line_match[:s].to_f
|
62
66
|
|
63
|
-
|
64
|
-
|
65
|
-
|
67
|
+
duration = line_time - @last_replay_time
|
68
|
+
sleep duration / @replay_speed if @replay_speed
|
69
|
+
@last_replay_time = line_time
|
66
70
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
71
|
+
MasterTimer.set(line_time)
|
72
|
+
|
73
|
+
run_line(line_match[:content])
|
74
|
+
end
|
75
|
+
|
76
|
+
def run_line(line)
|
77
|
+
TargetedTimerManager.start_for_line(line)
|
78
|
+
Logger.put_output(line)
|
79
|
+
TargetedTimerManager.stop_for_line(line)
|
72
80
|
end
|
73
81
|
end
|
74
82
|
end
|
data/lib/timmy/version.rb
CHANGED
data/lib/timmy.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timmy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Karol Słuszniak
|
@@ -52,9 +52,7 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.0'
|
55
|
-
description:
|
56
|
-
command spends on each stage of execution by annotating the command output with
|
57
|
-
timestamps as well as running command-specific targeted timers.
|
55
|
+
description:
|
58
56
|
email:
|
59
57
|
- ksluszniak@gmail.com
|
60
58
|
executables:
|