Module: Roby::Log

Extended by:
Logger::Forward, Logger::Hierarchy
Defined in:
lib/roby/log/hooks.rb,
lib/roby/log/logger.rb,
lib/roby/log/server.rb,
lib/roby/log/sqlite.rb,
lib/roby/log/console.rb,
lib/roby/log/timings.rb,
lib/roby/log/chronicle.rb,
lib/roby/log/data_stream.rb,
lib/roby/log/event_stream.rb,
lib/roby/log/notifications.rb,
lib/roby/log/relations.rb,
lib/roby/log/dot.rb

Defined Under Namespace

Modules: BasicObjectHooks, ControlHooks, DataDisplay, EventGeneratorHooks, PlanHooks, TaskDisplaySupport, TaskHooks, TransactionHooks Classes: ChronicleDisplay, Client, ConsoleLogger, DataDecoder, DataStream, EventMatcher, EventStream, Layout, Notifications, NotificationsDisplay, RelationsDisplay, RemoteStream, SQLiteLogger, Server, Timings

Constant Summary collapse

LOGGED_EVENTS_QUEUE_SIZE =
2000
EVENT_CIRCLE_RADIUS =
3
TASK_EVENT_SPACING =
5
DEFAULT_TASK_WIDTH =
20
DEFAULT_TASK_HEIGHT =
10
ARROW_COLOR =
Qt::Color.new('black')
ARROW_OPENING =
30
ARROW_SIZE =
10
PROPAG_SIGNAL =
1
PROPAG_FORWARD =
2
PROPAG_CALLING =
3
PROPAG_EMITTING =
4
EVENT_CONTINGENT =
0
EVENT_CONTROLABLE =
1
EVENT_CALLED =
2
EVENT_EMITTED =
4
EVENT_CALLED_AND_EMITTED =
EVENT_CALLED | EVENT_EMITTED
TASK_BRUSH_COLORS =
{
    :pending  => Qt::Color.new('#6DF3FF'),
    :started  => Qt::Color.new('#B0FFA6'),
    :success  => Qt::Color.new('#E2E2E2'),
    :finished => Qt::Color.new('#E2A8A8'),
    :finalized => Qt::Color.new('#555555')
}
TASK_PEN_COLORS =
{
    :pending  => Qt::Color.new('#6DF3FF'),
    :started  => Qt::Color.new('#B0FFA6'),
    :success  => Qt::Color.new('#E2E2E2'),
    :finished => Qt::Color.new('#E2A8A8'),
    :finalized => Qt::Color.new('#555555')
}
TASK_NAME_COLOR =
'black'
TASK_FONTSIZE =
10
PENDING_EVENT_COLOR =

default color for events

'black'
FIRED_EVENT_COLOR =
'red'
EVENT_FONTSIZE =
8
PLAN_LAYER =
0
TASK_LAYER =
PLAN_LAYER + 20
EVENT_LAYER =
PLAN_LAYER + 30
FIND_MARGIN =
10
@@logging_thread =
nil

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.flushed_loggerObject (readonly)

Returns the value of attribute flushed_logger.



76
77
78
# File 'lib/roby/log/logger.rb', line 76

def flushed_logger
  @flushed_logger
end

.flushed_logger_mutexObject (readonly)

Returns the value of attribute flushed_logger_mutex.



75
76
77
# File 'lib/roby/log/logger.rb', line 75

def flushed_logger_mutex
  @flushed_logger_mutex
end

.known_objectsObject (readonly)

Returns the value of attribute known_objects.



77
78
79
# File 'lib/roby/log/logger.rb', line 77

def known_objects
  @known_objects
end

.logged_eventsObject (readonly)

Returns the value of attribute logged_events.



74
75
76
# File 'lib/roby/log/logger.rb', line 74

def logged_events
  @logged_events
end

Class Method Details

.add_logger(logger) ⇒ Object

Add a logger object in the system



36
37
38
39
# File 'lib/roby/log/logger.rb', line 36

def add_logger(logger)
    start_logging
    @loggers << logger
end

.arrow_set(arrow, start_object, end_object) ⇒ Object



362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/roby/log/relations.rb', line 362

def self.arrow_set(arrow, start_object, end_object)
    start_br    = start_object.scene_bounding_rect
    end_br      = end_object.scene_bounding_rect
    start_point = start_br.center
    end_point   = end_br.center

    #from = intersect_rect(start_br.width, start_br.height, end_point, start_point)
    from = [start_point.x, start_point.y]
    to   = intersect_rect(end_br.width, end_br.height, from, [end_point.x, end_point.y])

    dy = to[1] - from[1]
    dx = to[0] - from[0]
    alpha  = Math.atan2(dy, dx)
    length = Math.sqrt(dx ** 2 + dy ** 2)

    #arrow.line.set_line from[0], from[1], to[0], to[1]
    arrow.resetMatrix
    arrow.line.set_line(-length, 0, 0, 0)
    arrow.translate to[0], to[1]
    arrow.rotate(alpha * 180 / Math::PI)
end

.clear_loggersObject

Remove all loggers



51
52
53
54
# File 'lib/roby/log/logger.rb', line 51

def clear_loggers
    stop_logging
    @loggers.clear
end

.correct_line(from, to, rect) ⇒ Object



358
359
360
# File 'lib/roby/log/relations.rb', line 358

def self.correct_line(from, to, rect)
    intersect_rect(rect.width, rect.height, from, to)
end

.each_hookObject



175
176
177
178
179
180
181
182
183
# File 'lib/roby/log/hooks.rb', line 175

def self.each_hook
	[TransactionHooks, BasicObjectHooks, TaskHooks,
 PlanHooks, EventGeneratorHooks, ControlHooks,
 ControlHooks::ClassExtension].each do |klass|
		klass::HOOKS.each do |m|
  yield(klass, m.to_sym)
		end
 end
end

.each_logger(m = nil) ⇒ Object

Iterates on all the logger objects. If m is given, yields only the loggers which respond to this method.



58
59
60
61
62
63
64
# File 'lib/roby/log/logger.rb', line 58

def each_logger(m = nil)
    for l in @loggers
	if !m || l.respond_to?(m)
	    yield(l) 
	end
    end
end

.flushObject

Waits for all the events queued in logged_events to be processed by the logging thread. Also sends the flush message to all loggers that respond to it



155
156
157
158
159
160
161
162
163
164
# File 'lib/roby/log/logger.rb', line 155

def flush
    flushed_logger_mutex.synchronize do
	if !logging?
	    raise "not logging"
	end

	logged_events.push [:flush, []]
	flushed_logger.wait(flushed_logger_mutex)
    end
end

.has_logger?(m) ⇒ Boolean

Returns true if there is at least one loggr for the m message

Returns:

  • (Boolean)


67
68
69
70
71
72
# File 'lib/roby/log/logger.rb', line 67

def has_logger?(m)
    for l in @loggers
	return true if l.respond_to?(m)
    end
    false
end

.incremental_dump?(object) ⇒ Boolean

Returns:

  • (Boolean)


79
# File 'lib/roby/log/logger.rb', line 79

def incremental_dump?(object); known_objects.include?(object) end

.intersect_rect(w, h, from, to) ⇒ Object



328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
# File 'lib/roby/log/relations.rb', line 328

def self.intersect_rect(w, h, from, to)
    to_x, to_y = *to
    from_x, from_y = *from

    # We only use half dimensions since 'to' is supposed to be be the
    # center of the rectangle we are intersecting
    w /= 2
    h /= 2

    dx    = (to_x - from_x)
    dy    = (to_y - from_y)
    delta_x = dx / dy * h
    if dy != 0 && delta_x.abs < w
	if dy > 0
	    [to_x - delta_x, to_y - h]
	else
	    [to_x + delta_x, to_y + h]
	end
    elsif dx != 0
	delta_y = dy / dx * w
	if dx > 0
	    [to_x - w, to_y - delta_y]
	else
	    [to_x + w, to_y + delta_y]
	end
    else
	[0, 0]
    end
end

.load_all_displaysObject

Requires all displays



167
168
169
170
# File 'lib/roby/log/logger.rb', line 167

def load_all_displays
    require 'roby/log/relations'
    require 'roby/log/execution-state'
end

.log(m, args = nil) ⇒ Object

call-seq:

Log.log(message) { args }

Logs message with argument args. The block is called only once if there is at least one logger which listens for message.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/roby/log/logger.rb', line 86

def log(m, args = nil)
    if m == :discovered_tasks || m == :discovered_events
	Roby::Control.synchronize do
	    args ||= yield
	    objects = args[1].to_value_set
	    # Do not give a 'peer' argument at Distributed.format, to
	    # make sure we do a full dump
	    args = Roby::Distributed.format(args) if has_logger?(m)
	    known_objects.merge(objects)
	end
    elsif m == :finalized_task || m == :finalized_event
	Roby::Control.synchronize do
	    args ||= yield
	    object = args[1]
	    args = Roby::Distributed.format(args, self) if has_logger?(m)
	    known_objects.delete(object)
	end
    end

    if has_logger?(m)
	if !args && block_given?
	    Roby::Control.synchronize do 
		args = Roby::Distributed.format(yield, self)
	    end
	end

	logged_events << [m, Time.now, args]
    end
end

.logger_loopObject

The main logging loop. We use a separate loop to avoid having logging have too much influence on the control thread. The Log.logged_events attribute is a sized queue (of size LOGGED_EVENTS_QUEUE_SIZE) in which all the events needing logging are saved



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/roby/log/logger.rb', line 120

def logger_loop
    Thread.current.priority = 2
    loop do
	m, time, args = logged_events.pop
	break unless m

	each_logger(m) do |logger|
	    if logger.splat?
		logger.send(m, time, *args)
	    else
		logger.send(m, time, args)
	    end
	end

	if m == :flush && logged_events.empty?
	    flushed_logger_mutex.synchronize do
		flushed_logger.broadcast
	    end
	end
    end

rescue Exception => e
    Roby.fatal "logger thread dies with #{e.full_message}" unless e.kind_of?(Interrupt)

ensure
    # Wake up any waiting thread
    flushed_logger_mutex.synchronize do
	@@logging_thread = nil
	flushed_logger.broadcast
    end
end

.logging?Boolean

Start the logging framework

Returns:

  • (Boolean)


13
14
15
# File 'lib/roby/log/logger.rb', line 13

def logging?
    @@logging_thread
end

.open(file) ⇒ Object



172
173
174
# File 'lib/roby/log/logger.rb', line 172

def open(file)
    Logfile.open(file)
end

.remove_logger(logger) ⇒ Object

Remove a logger from the list of loggers



42
43
44
45
46
47
48
# File 'lib/roby/log/logger.rb', line 42

def remove_logger(logger)
    flush if logging?
    if @loggers.size == 1
	stop_logging
    end
    @loggers.delete logger
end

.replay(file, &block) ⇒ Object



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/roby/log/logger.rb', line 176

def replay(file, &block)
    if file =~ /\.gz$/
	require 'zlib'
	require 'roby/log/file'
	Zlib::GzipReader.open(file) do |io|
	    FileLogger.replay(io, &block)
	end
    elsif file =~ /\.db$/
	require 'roby/log/sqlite'
	SQLiteLogger.replay(file, &block)
    else
	require 'roby/log/file'
	File.open(file) do |io|
	    FileLogger.replay(io, &block)
	end
    end
end

.start_loggingObject

Start the logging framework



18
19
20
21
22
# File 'lib/roby/log/logger.rb', line 18

def start_logging # :nodoc:
    return if logging?
    logged_events.clear
    @@logging_thread = Thread.new(&method(:logger_loop))
end

.stop_loggingObject

Stop the logging framework



25
26
27
28
29
30
31
32
33
# File 'lib/roby/log/logger.rb', line 25

def stop_logging # :nodoc:
    return unless logging?
    logged_events.push nil
    flushed_logger_mutex.synchronize do
	while @@logging_thread
	    flushed_logger.wait(flushed_logger_mutex)
	end
    end
end