Class: Tasker::Telemetry::PluginRegistry

Inherits:
Registry::BaseRegistry show all
Includes:
Singleton
Defined in:
lib/tasker/telemetry/plugin_registry.rb

Overview

Registry for managing export plugins

Provides centralized management of export plugins with discovery, registration, and format-based lookup capabilities. Now modernized with BaseRegistry patterns for consistency across all registry systems.

Examples:

Register a plugin

registry = Tasker::Telemetry::PluginRegistry.instance
registry.register('my_exporter', MyExporter.new)

Find plugins by format

json_plugins = registry.find_by_format('json')
csv_plugins = registry.find_by_format('csv')

Auto-discover plugins

registry.auto_discover_plugins

Constant Summary

Constants included from Concerns::StructuredLogging

Concerns::StructuredLogging::CORRELATION_ID_KEY

Instance Method Summary collapse

Methods inherited from Registry::BaseRegistry

#base_stats, #health_check, #healthy?, #log_registration, #log_registry_error, #log_registry_operation, #log_unregistration, #log_validation_failure, #thread_safe_operation, #validate_registration_params!

Methods included from Concerns::StructuredLogging

#correlation_id, #correlation_id=, #log_exception, #log_orchestration_event, #log_performance_event, #log_step_event, #log_structured, #log_task_event, #with_correlation_id

Constructor Details

#initializePluginRegistry

Returns a new instance of PluginRegistry.



28
29
30
31
32
33
# File 'lib/tasker/telemetry/plugin_registry.rb', line 28

def initialize
  super
  @plugins = Concurrent::Hash.new
  @formats = Concurrent::Hash.new
  log_registry_operation('initialized', total_plugins: 0, total_formats: 0)
end

Instance Method Details

#all_itemsHash

Get all registered plugins (required by BaseRegistry)

Returns:

  • (Hash)

    All registered plugins



122
123
124
# File 'lib/tasker/telemetry/plugin_registry.rb', line 122

def all_items
  all_plugins
end

#all_pluginsHash

Get all registered plugins

Returns:

  • (Hash)

    Hash of plugin name => plugin info



115
116
117
# File 'lib/tasker/telemetry/plugin_registry.rb', line 115

def all_plugins
  @plugins.dup
end

#auto_discover_plugins(directory = nil) ⇒ Integer

Auto-discover plugins in the plugins directory

Parameters:

  • directory (String) (defaults to: nil)

    Directory to search for plugins

Returns:

  • (Integer)

    Number of plugins discovered



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
# File 'lib/tasker/telemetry/plugin_registry.rb', line 173

def auto_discover_plugins(directory = nil)
  directory ||= File.join(File.dirname(__FILE__), 'plugins')

  return 0 unless Dir.exist?(directory)

  discovered_count = 0

  Dir.glob(File.join(directory, '*_exporter.rb')).each do |file|
    require file

    # Extract class name from filename
    class_name = File.basename(file, '.rb').camelize
    full_class_name = "Tasker::Telemetry::Plugins::#{class_name}"

    # Try to instantiate the plugin
    plugin_class = full_class_name.constantize
    plugin_instance = plugin_class.new

    register(class_name.underscore, plugin_instance, auto_discovered: true)
    discovered_count += 1

    log_registry_operation('auto_discovered_plugin',
                           plugin_name: class_name,
                           plugin_class: full_class_name,
                           file_path: file)
  rescue StandardError => e
    log_registry_error('auto_discovery_failed', e,
                       file_path: file,
                       class_name: File.basename(file, '.rb').camelize)
  end

  discovered_count
end

#clear!Boolean

Clear all registered plugins (required by BaseRegistry)

Returns:

  • (Boolean)

    True if cleared successfully



225
226
227
228
229
230
231
232
# File 'lib/tasker/telemetry/plugin_registry.rb', line 225

def clear!
  thread_safe_operation do
    @plugins.clear
    @formats.clear
    log_registry_operation('cleared_all')
    true
  end
end

#clear_all!Boolean

Legacy method for backward compatibility

Returns:

  • (Boolean)

    True if cleared successfully



237
238
239
# File 'lib/tasker/telemetry/plugin_registry.rb', line 237

def clear_all!
  clear!
end

#find_by(format:) ⇒ Array<Object>

Find plugins by criteria (supports keyword arguments for test compatibility)

Parameters:

  • format (String, Symbol)

    Format to search for

Returns:

  • (Array<Object>)

    Array of plugin instances



150
151
152
# File 'lib/tasker/telemetry/plugin_registry.rb', line 150

def find_by(format:)
  find_by_format(format)
end

#find_by_format(format) ⇒ Array<Object>

Find plugins that support a specific format

Parameters:

  • format (String, Symbol)

    Format to search for

Returns:

  • (Array<Object>)

    Array of plugin instances



139
140
141
142
143
144
# File 'lib/tasker/telemetry/plugin_registry.rb', line 139

def find_by_format(format)
  format = format.to_s.downcase
  plugin_names = @formats[format].to_a

  plugin_names.filter_map { |name| get_plugin(name) }
end

#get_plugin(name) ⇒ Object?

Get plugin by name

Parameters:

  • name (String, Symbol)

    Plugin identifier

Returns:

  • (Object, nil)

    Plugin instance or nil if not found



130
131
132
133
# File 'lib/tasker/telemetry/plugin_registry.rb', line 130

def get_plugin(name)
  plugin_config = @plugins[name.to_s]
  plugin_config&.dig(:instance)
end

#register(name, plugin, replace: false, **options) ⇒ Boolean

Register a plugin

Parameters:

  • name (String, Symbol)

    Plugin identifier

  • plugin (Object)

    Plugin instance

  • replace (Boolean) (defaults to: false)

    Whether to replace existing plugin

  • options (Hash)

    Plugin options

Returns:

  • (Boolean)

    True if registration successful



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/tasker/telemetry/plugin_registry.rb', line 42

def register(name, plugin, replace: false, **options)
  name = name.to_s

  thread_safe_operation do
    # Validate plugin interface
    begin
      Registry::InterfaceValidator.validate_plugin!(plugin)
    rescue ArgumentError => e
      log_validation_failure('telemetry_plugin', name, e.message)
      raise
    end

    # Check for existing plugin
    if @plugins.key?(name) && !replace
      raise ArgumentError, "Plugin '#{name}' already registered. Use replace: true to override."
    end

    # Remove existing plugin if replacing
    if @plugins.key?(name)
      existing_config = @plugins[name]
      unregister_format_mappings(name, existing_config[:supported_formats])
      log_unregistration('telemetry_plugin', name, existing_config[:instance].class)
    end

    # Get supported formats
    supported_formats = get_supported_formats(plugin)

    # Register plugin
    plugin_config = {
      instance: plugin,
      name: name,
      options: options.merge(replace: replace),
      registered_at: Time.current,
      supported_formats: supported_formats
    }

    @plugins[name] = plugin_config

    # Index by supported formats
    register_format_mappings(name, supported_formats)

    log_registration('telemetry_plugin', name, plugin.class,
                     { supported_formats: supported_formats, format_count: supported_formats.size, **options })

    true
  end
end

#statsHash

Get comprehensive registry statistics

Returns:

  • (Hash)

    Detailed statistics about the registry



210
211
212
213
214
215
216
217
218
219
220
# File 'lib/tasker/telemetry/plugin_registry.rb', line 210

def stats
  base_stats.merge(
    total_plugins: @plugins.size,
    total_formats: @formats.size,
    supported_formats: @formats.keys.sort,
    plugins_by_format: @formats.transform_values(&:size),
    average_formats_per_plugin: calculate_average_formats_per_plugin,
    most_popular_formats: find_most_popular_formats,
    plugin_distribution: calculate_plugin_distribution
  )
end

#supported_formatsArray<String>

Get supported formats across all plugins

Returns:

  • (Array<String>)

    Array of supported format names



157
158
159
# File 'lib/tasker/telemetry/plugin_registry.rb', line 157

def supported_formats
  @formats.keys.sort
end

#supports_format?(format) ⇒ Boolean

Check if a format is supported by any plugin

Parameters:

  • format (String, Symbol)

    Format to check

Returns:

  • (Boolean)

    True if format is supported



165
166
167
# File 'lib/tasker/telemetry/plugin_registry.rb', line 165

def supports_format?(format)
  @formats.key?(format.to_s.downcase)
end

#unregister(name) ⇒ Boolean

Unregister a plugin

Parameters:

  • name (String, Symbol)

    Plugin identifier

Returns:

  • (Boolean)

    True if unregistered successfully



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/tasker/telemetry/plugin_registry.rb', line 94

def unregister(name)
  name = name.to_s

  thread_safe_operation do
    plugin_config = @plugins.delete(name)

    if plugin_config
      # Remove from format index
      unregister_format_mappings(name, plugin_config[:supported_formats])

      log_unregistration('telemetry_plugin', name, plugin_config[:instance].class)
      true
    else
      false
    end
  end
end