Class: Tasker::Logging::CorrelationIdGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/tasker/logging/correlation_id_generator.rb

Overview

CorrelationIdGenerator creates unique correlation IDs for distributed tracing

Generates correlation IDs that are:

  • Unique across distributed systems
  • URL-safe and log-friendly
  • Sortable by generation time
  • Human-readable length

Format: tsk_[timestamp_base36][random_suffix] Example: tsk_l7k9m2p4_a8x3f9

Constant Summary collapse

PREFIX =

Prefix for all Tasker correlation IDs

'tsk'
RANDOM_SUFFIX_LENGTH =

Length of random suffix

6

Class Method Summary collapse

Class Method Details

.from_existing(existing_id) ⇒ String

Generate correlation ID from an existing ID (for HTTP propagation)

Examples:

# With existing valid ID
id = from_existing("req_abc123")
# => "req_abc123"

# With invalid/missing ID
id = from_existing(nil)
# => "tsk_l7k9m2p4_a8x3f9"

Parameters:

  • existing_id (String, nil)

    Existing correlation ID from headers

Returns:

  • (String)

    Valid correlation ID (existing or newly generated)



50
51
52
53
54
55
56
57
# File 'lib/tasker/logging/correlation_id_generator.rb', line 50

def from_existing(existing_id)
  return generate if existing_id.blank?
  return existing_id if valid_correlation_id?(existing_id)

  # If existing ID is invalid, create a new one but log the attempt
  Rails.logger.debug { "Invalid correlation ID received: #{existing_id}. Generating new ID." }
  generate
end

.from_headers(headers, header_name = nil) ⇒ String?

Extract correlation ID from HTTP headers

Examples:

id = from_headers(request.headers)
id = from_headers(env, 'X-Request-ID')

Parameters:

  • headers (Hash)

    HTTP headers hash

  • header_name (String) (defaults to: nil)

    Header name to check (defaults to config)

Returns:

  • (String, nil)

    Correlation ID if found and valid



68
69
70
71
72
73
74
75
76
77
# File 'lib/tasker/logging/correlation_id_generator.rb', line 68

def from_headers(headers, header_name = nil)
  header_name ||= Tasker::Configuration.configuration.telemetry.correlation_id_header

  # Handle different header formats (rack vs rails)
  header_value = headers[header_name] ||
                 headers["HTTP_#{header_name.upcase.tr('-', '_')}"] ||
                 headers[header_name.downcase]

  from_existing(header_value)
end

.generateString

Generate a new correlation ID

Examples:

id = Tasker::Logging::CorrelationIdGenerator.generate
# => "tsk_l7k9m2p4_a8x3f9"

Returns:

  • (String)

    A unique correlation ID



30
31
32
33
34
35
# File 'lib/tasker/logging/correlation_id_generator.rb', line 30

def generate
  timestamp_part = generate_timestamp_component
  random_part = generate_random_component

  "#{PREFIX}_#{timestamp_part}_#{random_part}"
end

.valid_correlation_id?(id) ⇒ Boolean

Validate if a string is a valid correlation ID format

Examples:

valid_correlation_id?("tsk_l7k9m2p4_a8x3f9")  # => true
valid_correlation_id?("invalid")              # => false
valid_correlation_id?("")                     # => false

Parameters:

  • id (String)

    The ID to validate

Returns:

  • (Boolean)

    Whether the ID is valid



88
89
90
91
92
93
94
95
# File 'lib/tasker/logging/correlation_id_generator.rb', line 88

def valid_correlation_id?(id)
  return false if id.blank?
  return false if id.length > 100 # Reasonable max length

  # Allow various prefixes for external system compatibility
  # But ensure it's alphanumeric with underscores/hyphens only
  id.match?(/\A[a-zA-Z0-9][a-zA-Z0-9_\-]*\z/)
end