Class: Towel::Log

Inherits:
Object
  • Object
show all
Defined in:
lib/towel/log.rb

Constant Summary collapse

NAME_FORMAT =

Logs must be associated with an invocation.

/invocations\/[^\/]+\/logs\/[^\/]+/
FLUSH_INTERVAL_SECONDS =

How long to wait for more log entries before calling ‘AppendLog`. This tries to batch log lines together as opposed to making a call for each log line individually.

0.1
FLUSH_COUNT =

How many log lines to send at a time. If there are more than this, they will be broken up into several ‘AppendLog` calls.

100

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, stub) ⇒ Log

Returns a new instance of Log.

Raises:

  • (ArgumentError)


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/towel/log.rb', line 17

def initialize(name, stub)
  unless name =~ NAME_FORMAT
    raise ArgumentError, "Log name #{name} is invalid"
  end
  raise ArgumentError, "Stub must be provided" unless stub
  @name = name
  @stub = stub
  @entries = Queue.new
  @entry_id = Concurrent::AtomicFixnum.new(-1)
  @flush_mutex = Mutex.new
  @flush_timer_mutex = Mutex.new
  @flush_timer = nil

  # Create the log
  log = Towel::V1alpha::Log.new
  log.name = @name
  request = Towel::V1alpha::CreateLogRequest.new
  request.log = log
  @stub.create_log(request)
end

Instance Attribute Details

#nameObject (readonly)

Returns the value of attribute name.



15
16
17
# File 'lib/towel/log.rb', line 15

def name
  @name
end

Instance Method Details

#<<(line) ⇒ Object



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/towel/log.rb', line 46

def <<(line)
  entry = Towel::V1alpha::LogEntry.new
  entry.entry_id = @entry_id.increment
  entry.log_time = Time.now.utc
  entry.parent = context if context
  entry.contents = line

  @entries << entry

  # Set up a flush to happen momentarily, allowing other lines to possibly
  # be flushed together with this one.
  @flush_timer_mutex.synchronize do
    unless @flush_timer
      @flush_timer = Concurrent::ScheduledTask.execute(
        FLUSH_INTERVAL_SECONDS
      ) { flush }
    end
  end
end

#closeObject



66
67
68
69
# File 'lib/towel/log.rb', line 66

def close
  flush
  Thread.current["towel_context_#{object_id}"] = nil
end

#contextObject



38
39
40
# File 'lib/towel/log.rb', line 38

def context
  Thread.current["towel_context_#{object_id}"]
end

#context=(context) ⇒ Object



42
43
44
# File 'lib/towel/log.rb', line 42

def context=(context)
  Thread.current["towel_context_#{object_id}"] = context
end

#flushObject

Ensure that entries get written out to Towel.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/towel/log.rb', line 72

def flush
  @flush_mutex.synchronize do
    # Acknowledge the flush timer by unsetting it, if it exists.
    @flush_timer_mutex.synchronize do
      @flush_timer.cancel if @flush_timer
      @flush_timer = nil
    end

    until @entries.empty?
      request = Towel::V1alpha::AppendLogRequest.new
      request.name = @name
      i = 0
      while i < FLUSH_COUNT
        i += 1
        begin
          entry = @entries.pop(true)
        rescue ThreadError # Raised if the queue is empty
          break
        end
        request.entries << entry
      end
      @stub.append_log(request)
    end
  end
end