Class: BBLib::TaskTimer

Inherits:
Object
  • Object
show all
Includes:
Effortless, Prototype
Defined in:
lib/bblib/core/classes/task_timer.rb

Overview

Simple timer that can track tasks based on time. Also provides aggregated metrics

and history for each task run. Generally useful for benchmarking or logging.

Author:

  • Brandon Black

Constant Summary collapse

TIMER_TYPES =
{
  current: [],
  count:   [:total],
  first:   [:initial],
  last:    [:latest],
  min:     [:minimum, :smallest],
  max:     [:maximum, :largest],
  avg:     [:average, :av],
  sum:     [],
  all:     [:times]
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Prototype

included

Methods included from Effortless

#_attrs, included

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(*args, **named) ⇒ Object



92
93
94
95
96
97
98
99
# File 'lib/bblib/core/classes/task_timer.rb', line 92

def method_missing(*args, **named)
  temp   = args.first.to_sym
  type   = TIMER_TYPES.keys.find { |k| k == temp || TIMER_TYPES[k].include?(temp) }
  return super unless type
  t = time(args[1] || :default, type)
  return t if type == :count || !named[:pretty]
  t.is_a?(Array) ? t.map(&:to_duration) : t.to_duration
end

Instance Attribute Details

#retentionInteger

The number of runs to collect per task before truncation.

Returns:

  • (Integer)

    the current value of retention



8
9
10
# File 'lib/bblib/core/classes/task_timer.rb', line 8

def retention
  @retention
end

#tasksHash

The information on all running tasks and history of all tasks up to the retention.

Returns:

  • (Hash)

    the current value of tasks



8
9
10
# File 'lib/bblib/core/classes/task_timer.rb', line 8

def tasks
  @tasks
end

Instance Method Details

#active?(task = :default) ⇒ Boolean

Returns:

  • (Boolean)


79
80
81
82
# File 'lib/bblib/core/classes/task_timer.rb', line 79

def active?(task = :default)
  return false unless tasks.keys.include?(task)
  !tasks[task][:current].nil?
end

#clear(task = :default) ⇒ NilClass

Removes all history for a given task

Parameters:

  • task (Symbol) (defaults to: :default)

    The name of the task to clear history from.

Returns:

  • (NilClass)

    Returns nil



45
46
47
48
49
# File 'lib/bblib/core/classes/task_timer.rb', line 45

def clear(task = :default)
  return nil unless tasks.keys.include?(task)
  stop task
  tasks[task][:history].clear
end

#respond_to_missing?(method, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


101
102
103
# File 'lib/bblib/core/classes/task_timer.rb', line 101

def respond_to_missing?(method, include_private = false)
  TIMER_TYPES.keys.find { |k| k == method || TIMER_TYPES[k].include?(method) } || super
end

#restart(task = :default) ⇒ Object



75
76
77
# File 'lib/bblib/core/classes/task_timer.rb', line 75

def restart(task = :default)
  start(task) unless stop(task).nil?
end

#start(task = :default) ⇒ Integer

Start a new timer for the referenced task. If a timer is already running for that task it will be stopped first.

Parameters:

  • task (Symbol) (defaults to: :default)

    The name of the task to start.

Returns:



55
56
57
58
59
60
# File 'lib/bblib/core/classes/task_timer.rb', line 55

def start(task = :default)
  tasks[task] = { history: [], current: nil } unless tasks.keys.include?(task)
  stop task if tasks[task][:current]
  tasks[task][:current] = Time.now.to_f
  0
end

#stats(task = :default, pretty: false) ⇒ Object



84
85
86
87
88
89
90
# File 'lib/bblib/core/classes/task_timer.rb', line 84

def stats(task = :default, pretty: false)
  return nil unless tasks.include?(task)
  TIMER_TYPES.map do |k, _v|
    next if STATS_IGNORE.include?(k)
    [k, send(k, task, pretty: pretty)]
  end.compact.to_h
end

#stop(task = :default) ⇒ Float, NilClass

Stop the referenced timer.

Parameters:

  • task (Symbol) (defaults to: :default)

    The name of the task to stop.

Returns:

  • (Float, NilClass)

    The amount of time the task had been running or nil if no matching task was found.



66
67
68
69
70
71
72
73
# File 'lib/bblib/core/classes/task_timer.rb', line 66

def stop(task = :default)
  return nil unless tasks.keys.include?(task) && active?(task)
  time_taken = Time.now.to_f - tasks[task][:current].to_f
  tasks[task][:history] << { start: tasks[task][:current], stop: Time.now.to_f, time: time_taken }
  tasks[task][:current] = nil
  if retention && tasks[task][:history].size > retention then tasks[task][:history].shift end
  time_taken
end

#time(task = :default, type = :current) ⇒ Float, ...

Returns an aggregated metric for a given type.

Parameters:

  • task (Symbol) (defaults to: :default)

    The key value of the task to retrieve

  • type (Symbol) (defaults to: :current)

    The metric to return. Options are :avg, :min, :max, :first, :last, :sum, :all and :count.

Returns:

  • (Float, Integer, Array)

    Returns either the aggregation (Numeric) or an Array in the case of :all.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/bblib/core/classes/task_timer.rb', line 21

def time(task = :default, type = :current)
  return nil unless tasks.keys.include?(task)
  numbers = tasks[task][:history].map { |v| v[:time] }
  case type
  when :current
    return nil unless tasks[task][:current]
    Time.now.to_f - tasks[task][:current]
  when :min, :max, :first, :last
    numbers.send(type)
  when :avg
    numbers.size.zero? ? nil : numbers.inject { |sum, n| sum + n }.to_f / numbers.size
  when :sum
    numbers.inject { |sum, n| sum + n }
  when :all
    numbers
  when :count
    numbers.size
  end
end