Module: LogStruct::Integrations::Shrine

Extended by:
IntegrationInterface, T::Sig
Defined in:
lib/log_struct/integrations/shrine.rb

Overview

Shrine integration for structured logging

Class Method Summary collapse

Methods included from IntegrationInterface

setup

Class Method Details

.setup(config) ⇒ Boolean?

Set up Shrine structured logging

Parameters:

Returns:

  • (Boolean, nil)


19
20
21
22
23
24
25
26
27
28
29
30
31
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
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
89
90
91
92
93
94
# File 'lib/log_struct/integrations/shrine.rb', line 19

def self.setup(config)
  return nil unless defined?(::Shrine)
  return nil unless config.enabled
  return nil unless config.integrations.enable_shrine

  # Create a structured log subscriber for Shrine
  # ActiveSupport::Notifications::Event has name, time, end, transaction_id, payload, and duration
  shrine_log_subscriber = T.unsafe(lambda do |event|
    payload = event.payload.except(:io, :metadata, :name).dup

    # Map event name to Event type
    event_type = case event.name
    when :upload then Event::Upload
    when :download then Event::Download
    when :delete then Event::Delete
    when :metadata then Event::Metadata
    when :exists then Event::Exist # ActiveStorage uses 'exist', may as well use that
    else Event::Unknown
    end

    # Create structured log data
    # Ensure storage is always a symbol
    storage_sym = payload[:storage].to_sym

    log_data = case event_type
    when Event::Upload
      Log::Shrine::Upload.new(
        storage: storage_sym,
        location: payload[:location],
        uploader: payload[:uploader]&.to_s,
        upload_options: payload[:upload_options],
        options: payload[:options],
        duration_ms: event.duration.to_f
      )
    when Event::Download
      Log::Shrine::Download.new(
        storage: storage_sym,
        location: payload[:location],
        download_options: payload[:download_options]
      )
    when Event::Delete
      Log::Shrine::Delete.new(
        storage: storage_sym,
        location: payload[:location]
      )
    when Event::Metadata
       = {
        storage: storage_sym,
        metadata: payload[:metadata]
      }
      [:location] = payload[:location] if payload[:location]
      Log::Shrine::Metadata.new(**)
    when Event::Exist
      Log::Shrine::Exist.new(
        storage: storage_sym,
        location: payload[:location],
        exist: payload[:exist]
      )
    else
      unknown_params = {storage: storage_sym, metadata: payload[:metadata]}
      unknown_params[:location] = payload[:location] if payload[:location]
      Log::Shrine::Metadata.new(**unknown_params)
    end

    # Pass the structured hash to the logger
    # If Rails.logger has our Formatter, it will handle JSON conversion
    ::Shrine.logger.info log_data
  end)

  # Configure Shrine to use our structured log subscriber
  ::Shrine.plugin :instrumentation,
    events: %i[upload exists download delete],
    log_subscriber: shrine_log_subscriber

  true
end