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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9d197122524ccb2e1140f5cce09773a107679bfe
4
- data.tar.gz: 463efa752c2bb2d56b33aa2886e792e9156f2ffd
3
+ metadata.gz: 22d313c4caa316badf7f3aa3a2dd286ca7409290
4
+ data.tar.gz: 79ed29b958c3b909f6ee30710d04029eb6349f70
5
5
  SHA512:
6
- metadata.gz: b036c9c0a24faedfbf0407cb51b6353e60413115cc191922aa76f6cfeb3edb36727fee3be628920fd2124f970baf307c3f3b0dc575d12a113a239e9c8f59ce82
7
- data.tar.gz: 96a35e620a984c902c18c317baca1890db96a6aa76bd53524aa8fbc7d3c44a590c016d42c27aa118974abed18033b5a783bc03fcb419ae673992d59c08edd473
6
+ metadata.gz: 86b21b72ed5bda63389081cf14a7bf185cc316ff85b564700c9df0d3470285726268f71e882ca0001994aa2da4dcc9dc513f5a6a7e5565a6307626429ae64852
7
+ data.tar.gz: c2a2ce42c84555784dbc00318e8a44a4da8082c4b85595e6b583ea5f845048f3a61c60c73b62a444348159e02b3f2a78a8450ccdb942ad746ea5e6c472c5e4ac
@@ -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 set_output_directory(dir)
5
- @output_directory = dir
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 put_stopped_profiles
27
- puts "Slowest targeted timers:"
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 output_directory
83
- @output_directory ||= "/tmp"
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
@@ -2,12 +2,7 @@ module Timmy
2
2
  class OptionParser
3
3
  class << self
4
4
  def parse
5
- options = {
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
- Run without a pipe (usually with --replay):
17
+ Replay previous session:
23
18
 
24
- \e[36mtimmy [OPTIONS]\e[0m
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("-r LOG", "--replay LOG", "Replay specific log file") do |replay|
32
- options[:replay] = replay
33
- end
34
-
35
- parser.on("-p", "--profile", "Profile targeted timers") do |profile|
36
- options[:profile] = profile
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
- options
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
- if value = options[:logger_output_directory]
10
- Logger.set_output_directory(value)
11
- end
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
- if replay = options[:replay]
18
- replay_log(replay)
19
- else
20
- consume_stdin
21
- end
20
+ def initialize(replay_speed:)
21
+ @replay_speed = replay_speed
22
+ @last_replay_time = 0
23
+ end
22
24
 
23
- if options[:profile]
24
- Logger.put_stopped_profiles
25
- end
26
- end
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
- def consume_stdin
29
- around_run_lines do
30
- STDIN.each_line do |line|
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
- def replay_log(log)
38
- around_run_lines do
39
- start_time = File.basename(log).match(/timmy-(?<time>\d+)\+\d+.log/)[:time].to_i
40
- MasterTimer.start(start_time)
41
-
42
- File.readlines(log).each do |line|
43
- if match = line.match(/^(?<m>\d+):(?<s>\d+(\.\d+)?) \| (?<content>.*)/)
44
- line_time = match[:m].to_i * 60 + match[:s].to_f
45
- MasterTimer.set(line_time)
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
- private
57
+ yield
57
58
 
58
- def around_run_lines
59
- MasterTimer.start
59
+ TargetedTimerManager.stop_all
60
+ Logger.finalize
61
+ end
60
62
 
61
- yield
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
- TargetedTimerManager.stop_all
64
- Logger.finalize
65
- end
67
+ duration = line_time - @last_replay_time
68
+ sleep duration / @replay_speed if @replay_speed
69
+ @last_replay_time = line_time
66
70
 
67
- def run_line(line)
68
- TargetedTimerManager.start_for_line(line)
69
- Logger.put_output(line)
70
- TargetedTimerManager.stop_for_line(line)
71
- end
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
@@ -1,3 +1,3 @@
1
1
  module Timmy
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/timmy.rb CHANGED
@@ -7,3 +7,11 @@ require "timmy/targeted_timer"
7
7
  require "timmy/targeted_timer_definition"
8
8
  require "timmy/targeted_timer_manager"
9
9
  require "timmy/version"
10
+
11
+ module Timmy
12
+ module_function
13
+
14
+ def configure
15
+ yield(ConfigLoader.new)
16
+ end
17
+ end
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.3.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: A simple command line tool that allows to measure how much time an arbitrary
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: