Module: Syskit::NetworkGeneration::LoggerConfigurationSupport

Extended by:
Logger::Hierarchy
Includes:
Logger::Hierarchy
Defined in:
lib/syskit/network_generation/logger.rb

Overview

Extension to the logger's task model for logging configuration

It is automatically included in Engine#configure_logging

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#logged_portsObject (readonly)

Returns the value of attribute logged_ports



10
11
12
# File 'lib/syskit/network_generation/logger.rb', line 10

def logged_ports
  @logged_ports
end

Class Method Details

.add_logging_to_network(engine, work_plan) ⇒ Object

Configures each running deployment's logger, based on the information in port_dynamics

The “configuration” means that we create the necessary connections between each component's port and the logger



117
118
119
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/syskit/network_generation/logger.rb', line 117

def self.add_logging_to_network(engine, work_plan)
    return if !engine.dataflow_dynamics

    return unless (logger_model = find_logger_model)
    setup_logger_model(logger_model)

    fallback_policy = Hash[
        type: :buffer,
        size: Syskit.conf.logs.default_logging_buffer_size
    ]

    seen_loggers = Set.new
    engine.deployment_tasks.each do |deployment|
        next if !deployment.plan

        required_logging_ports = Array.new
        required_connections   = Array.new
        deployment.each_executed_task do |t|
            if t.finishing? || t.finished?
                next
            elsif t.kind_of?(logger_model)
                next
            elsif !engine.deployed_tasks.include?(t)
                next
            end

            connections = Hash.new
            t.each_output_port do |p|
                next if !deployment.log_port?(p)

                log_port_name = "#{t.orocos_name}.#{p.name}"
                connections[[p.name, log_port_name]] = Hash[fallback_policy: fallback_policy]
                required_logging_ports << [log_port_name, t, p]
            end
            required_connections << [t, connections]
        end

        if !(logger_task = deployment.logger_task)
            warn "deployment #{deployment.process_name} has no logger (default logger name would be #{deployment.process_name}_Logger))"
            next
        end
        logger_task = work_plan[deployment.logger_task]

        # Disconnect current log connections, we're going to
        # reestablish the ones we want later on. We leave other
        # connections as-is
        unless seen_loggers.include?(logger_task)
            dataflow = work_plan.task_relation_graph_for(Flows::DataFlow)
            deployment.each_executed_task do |t|
                if engine.deployed_tasks.include?(t)
                    dataflow.remove_relation(t, logger_task)
                end
            end
        end

        next if required_logging_ports.empty?

        # Make sure that the tasks are started after the logger was
        # started
        deployment.each_executed_task do |t|
            if t.pending? && t != logger_task
                t.should_start_after logger_task.start_event
            end
        end

        if logger_task.setup?
            # The logger task is already configured. Add the ports
            # manually
            #
            # Otherwise, Logger#configure will take care of it for
            # us
            required_logging_ports.each do |port_name, logged_task, logged_port|
                logger_task.create_logging_port(port_name, logged_task, logged_port)
            end
        end
        required_connections.each do |task, connections|
            connections = connections.map_value do |(port_name, log_port_name), policy|
                out_port = task.model.find_output_port(port_name)

                if !logger_task.model.find_input_port(log_port_name)
                    logger_task.instanciate_dynamic_input_port(log_port_name, out_port.type, logger_dynamic_port)
                end
                engine.dataflow_dynamics.policy_for(task, port_name, log_port_name, logger_task, policy)
            end

            task.connect_ports(logger_task, connections)
        end
    end

    # Finally, select 'default' as configuration for all
    # remaining tasks that do not have a 'conf' argument set
    work_plan.find_local_tasks(logger_model).
        each do |task|
            if !task.arguments[:conf]
                task.arguments[:conf] = ['default']
            end
        end

    # Mark as permanent any currently running logger
    work_plan.find_tasks(logger_model).
        not_finished.
        to_a.each do |t|
            work_plan.add_permanent_task(t)
        end
end

.find_logger_modelObject



96
97
98
# File 'lib/syskit/network_generation/logger.rb', line 96

def self.find_logger_model
    TaskContext.find_model_from_orogen_name 'logger::Logger'
end

.logger_dynamic_portObject



82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/syskit/network_generation/logger.rb', line 82

def self.logger_dynamic_port
    if @logger_dynamic_port
        return @logger_dynamic_port
    end

    ports = find_logger_model.orogen_model.dynamic_ports.find_all { |p| !p.type && p.kind_of?(Orocos::Spec::InputPort) }
    if ports.size > 1
        raise InternalError, "oroGen's logger::Logger task should have only one catch-all dynamic input port"
    elsif ports.empty?
        raise InternalError, "oroGen's logger::Logger task should have one catch-all dynamic input port, and has none"
    end
    @logger_dynamic_port = ports.first
end

.setup_logger_model(logger_model) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
# File 'lib/syskit/network_generation/logger.rb', line 100

def self.setup_logger_model(logger_model)
    if !(logger_model <= LoggerConfigurationSupport)
        logger_model.include LoggerConfigurationSupport
        logger_model.stub do
            def createLoggingPort(port_name, port_type, )
                create_input_port(port_name, port_type)
                true
            end
        end
    end
end

Instance Method Details

#configureObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/syskit/network_generation/logger.rb', line 63

def configure
    super

    if default_logger?
        deployment = execution_agent
        process = deployment.orocos_process
        process.setup_default_logger(
            self,
            log_file_name: process.default_log_file_name(orocos_task.basename),
            log_dir: deployment.log_dir,
            remote: !deployment.on_localhost?)
    end

    each_input_connection do |source_task, source_port_name, sink_port_name, policy|
        source_port = source_task.find_output_port(source_port_name)
        create_logging_port(sink_port_name, source_task, source_port)
    end
end

#create_logging_port(sink_port_name, logged_task, logged_port) ⇒ Object

Wrapper on top of the createLoggingPort operation

Parameters:

  • sink_port_name (String)

    the desired port name on the logger

  • the (TaskContext)

    task context that is being logged

  • the (OutputPort)

    port that is being logged



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/syskit/network_generation/logger.rb', line 32

def create_logging_port(sink_port_name, logged_task, logged_port)
    logged_port_type = logged_port.model.orocos_type_name
    return if logged_ports.include?([sink_port_name, logged_port_type])

     = Hash[
        'rock_task_model' => logged_task.concrete_model.orogen_model.name,
        'rock_task_name' => logged_task.orocos_name,
        'rock_task_object_name' => logged_port.name,
        'rock_stream_type' => 'port']
     = .map do |k, v|
        Hash['key' => k, 'value' => v]
    end

    @create_port ||= operation('createLoggingPort')
    if !@create_port.callop(sink_port_name, logged_port_type, )
        # Look whether a port with that name and type already
        # exists. If it is the case, it means somebody else already
        # created it and we're fine- Otherwise, raise an error
        begin
            port = orocos_task.port(sink_port_name)
            logger_port_type_m = Orocos.default_loader.intermediate_type_for(logged_port_type)
            if port.orocos_type_name != logged_port_type && port.orocos_type_name != logger_port_type_m.name
                raise ArgumentError, "cannot create a logger port of name #{sink_port_name} and type #{logged_port_type}: a port of same name but of type #{port.model.orocos_type_name} exists"
            end
        rescue Orocos::NotFound
            raise ArgumentError, "cannot create a logger port of name #{sink_port_name} and type #{logged_port_type}"
        end
    end
    logged_ports << [sink_port_name, logged_port_type]
end

#default_logger=(value) ⇒ Object

True if this logger is its deployment's default logger

In this case, it will set itself up using the deployment's logging configuration



16
# File 'lib/syskit/network_generation/logger.rb', line 16

attr_predicate :default_logger?, true

#default_logger?Boolean

True if this logger is its deployment's default logger

In this case, it will set itself up using the deployment's logging configuration

Returns:

  • (Boolean)


16
# File 'lib/syskit/network_generation/logger.rb', line 16

attr_predicate :default_logger?, true

#initialize(arguments = Hash.new) ⇒ Object



18
19
20
21
# File 'lib/syskit/network_generation/logger.rb', line 18

def initialize(arguments = Hash.new)
    super
    @logged_ports = Set.new
end

#start_only_when_connected?Boolean

Returns:

  • (Boolean)


23
24
25
# File 'lib/syskit/network_generation/logger.rb', line 23

def start_only_when_connected?
    false
end