Class: CloseYourIt::LogEvent

Inherits:
Event
  • Object
show all
Defined in:
lib/closeyourit/events/log_event.rb

Overview

Voce di log strutturata spedita all'ingest /logs (NON formato Sentry: i log sono uno stream con message/level/attributes/logger). message E attributes passano dallo Scrubber (denylist + pattern) come ErrorEvent — un log può contenere PII/segreti quanto un errore. trace_id è congelato alla COSTRUZIONE (thread della richiesta) → correlazione log↔errori della stessa request anche quando il flush avviene su un thread timer diverso.

Constant Summary collapse

LEVELS =

Livelli canonici del backend (enum) + alias dei nomi stile ::Logger. Normalizzati QUI (fonte unica) così ogni costruzione — via CloseYourIt.log, .logger o diretta — produce un livello valido. L'indice in LEVELS è anche la severità numerica del livello (debug=0 … fatal=4): la STESSA mappa di dart/js, così il gating per soglia (logs_min_level) filtra identico cross-SDK (CYRB-6).

%w[debug info warning error fatal].freeze
LEVEL_ALIASES =
{ "warn" => "warning", "err" => "error", "unknown" => "fatal" }.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(message, level:, attributes:, configuration:, logger: nil) ⇒ LogEvent

Returns a new instance of LogEvent.



34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/closeyourit/events/log_event.rb', line 34

def initialize(message, level:, attributes:, configuration:, logger: nil)
  super(configuration)
  @message = message
  @level = self.class.normalize_level(level)
  @attributes = attributes || {}
  @logger = logger
  @scrubber = Scrubber.new(configuration)
  # trace_id catturato QUI, sul thread della richiesta: il LogEvent viene bufferizzato e flushato
  # su un thread timer diverso, dove lo Scope corrente è di un'ALTRA richiesta (o vuoto) → leggerlo
  # lazy in to_h romperebbe la correlazione log↔errore. Lo congeliamo alla costruzione.
  @trace_id = CloseYourIt::Scope.current.trace_id
end

Class Method Details

.normalize_level(level) ⇒ Object

Normalizza qualsiasi livello (simbolo/stringa, maiuscole, alias) al nome canonico del backend. Ignoto → "info". Metodo di classe: fonte unica riusata da CloseYourIt.log per il gating.



22
23
24
25
26
# File 'lib/closeyourit/events/log_event.rb', line 22

def self.normalize_level(level)
  value = level.to_s.downcase
  value = LEVEL_ALIASES.fetch(value, value)
  LEVELS.include?(value) ? value : "info"
end

.severity(level) ⇒ Object

Severità numerica del livello (indice in LEVELS), identica alla mappa cross-SDK. Usata per il confronto con logs_min_level prima di costruire/spedire il log.



30
31
32
# File 'lib/closeyourit/events/log_event.rb', line 30

def self.severity(level)
  LEVELS.index(normalize_level(level))
end

Instance Method Details

#ingest_path(project_id) ⇒ Object



62
63
64
# File 'lib/closeyourit/events/log_event.rb', line 62

def ingest_path(project_id)
  "/api/v1/projects/#{project_id}/logs"
end

#to_hObject



47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/closeyourit/events/log_event.rb', line 47

def to_h
  compact(
    "event_id" => SecureRandom.uuid.delete("-"),
    "timestamp" => @occurred_at,
    "level" => @level,
    "message" => @scrubber.scrub_message(@message.to_s),
    "attributes" => scrubbed_attributes,
    "logger" => @logger,
    "trace_id" => @trace_id,
    "environment" => environment,
    "release" => @configuration.release,
    "sdk" => sdk
  )
end