Class: VendorLogger

Inherits:
Object
  • Object
show all
Defined in:
app/my_lib/vendor_logger.rb

Overview

VendorLogger provides structured logging for vendor-related API interactions.

This logger standardizes log categories and messages for vendor requests and responses, compresses large payloads for efficient storage, and provides helper methods for logging vendor events.

Usage:

VendorLogger.log_event(:request, route, payload)
VendorLogger.log_event(:response, route, payload: data)
VendorLogger.log_event(:webhook_out, route, payload: data, custom_message: "Custom response message")
VendorLogger.log_event(:webhook_out, route, payload: data, custom_message: :error)

Supported Categories:

  • :request - Incoming API call from vendor

  • :response - Our response to the vendor API

  • :webhook_in - Webhook received from vendor

  • :webhook_out - Webhook sent to vendor

Input Parameters:

  • type [Symbol]: The log type/category (:request, :response, :webhook_in, :webhook_out)

  • route [String]: The API route or action being logged

  • payload [Hash, Array, String, ActionController::Parameters, Object, nil]: The data to be logged (keyword argument) Supports Hash, Array, String, ActionController::Parameters, or any object that responds to as_json

  • custom_message [String, Symbol, nil]: Optional custom message or :error for default error message (keyword argument)

Return Value:

  • Boolean: true if logging succeeded, false if validation failed or an error occurred

Implementation Details:

  • Uses BUSINESS_LOGGER for all vendor-related logging

  • Handles Hash, Array, String, ActionController::Parameters, and serializable objects (responding to as_json)

  • Compresses payloads using Zlib and Base64 encoding to reduce log size

  • Validates all input parameters and reports validation errors to APM

  • Provides decompression utility for reading compressed log data

  • Converts ActionController::Parameters to unsafe hash before processing

  • Serializes objects using as_json method when available

  • Provides default messages for blank payloads based on log type

  • Designed for use in vendor API controllers and webhook handlers

Constant Summary collapse

CATEGORIES =

Categories for vendor log filtering.

{
  request: 'request',          # Incoming API call from vendor
  response: 'response',        # Our response to the vendor API
  webhook_in: 'webhook_in',    # Webhook received from vendor
  webhook_out: 'webhook_out',  # Webhook sent to vendor
}.freeze
CATEGORY_MESSAGES =

Default messages for each category.

{
  request: 'Incoming vendor API request',
  response: 'Outgoing response to vendor',
  webhook_in: 'Incoming webhook from vendor',
  webhook_out: 'Outgoing webhook to vendor',
}.freeze
CATEGORY_ERROR_MESSAGES =

Default error messages for categories that may have error scenarios.

{
  webhook_out: 'Failed to send webhook to vendor',
}.freeze
CATEGORY_SUCCESS_MESSAGES =

Default success messages for categories if payload is blank.

{
  request: 'Request received',
  response: 'Response sent successfully',
  webhook_in: 'Webhook received successfully',
  webhook_out: 'Webhook sent successfully',
}.freeze

Class Method Summary collapse

Class Method Details

.log_event(type, route, payload: nil, custom_message: nil) ⇒ Boolean

Logs vendor events with structured format and payload compression.

Implementation details:

  • Validates all input parameters and reports validation errors to APM

  • Compresses payloads using Zlib and Base64 encoding for efficient storage

  • Handles blank payloads with appropriate default messages based on log type

  • Converts ActionController::Parameters to unsafe hash before processing

  • Serializes objects using as_json method when available

  • Hash and Array payloads are converted to JSON before compression

  • String payloads are compressed as-is

  • Uses BUSINESS_LOGGER with structured data including compression metadata

  • Reports any errors during logging to APM and returns false

Parameters:

  • type (Symbol)

    The log type/category (:request, :response, :webhook_in, :webhook_out)

  • route (String)

    The API route or action

  • payload (Hash, Array, String, ActionController::Parameters, Object, nil) (defaults to: nil)

    The payload to log (keyword argument) Supports Hash, Array, String, ActionController::Parameters, or any object that responds to as_json

  • custom_message (String, Symbol, nil) (defaults to: nil)

    Optional custom message for the log entry (keyword argument)

    • When String: Used as-is in the log message

    • When :error: Uses predefined error message for the category if available

    • When nil: Uses default message for the category

Returns:

  • (Boolean)

    true if logging succeeded, false if validation failed or error occurred



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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
# File 'app/my_lib/vendor_logger.rb', line 91

def self.log_event(type, route, payload: nil, custom_message: nil)
  if ENV['RAILS_ENV_REAL'] != 'production' && type == :webhook_out
    APMErrorHandler.report(
      "[VendorLogger] #{type}:#{route} #{custom_message}",
      payload: payload,
    )
  end

  unless type.is_a?(Symbol)
    APMErrorHandler.report(
      'VendorLogger: Invalid type parameter - must be a Symbol',
      context: { type: type, type_class: type.class.name, route: route },
    )
    raise ArgumentError, 'Invalid type parameter - must be a Symbol'
  end

  unless CATEGORIES.key?(type)
    APMErrorHandler.report(
      "VendorLogger: Unknown log type '#{type}'",
      context: { type: type, route: route, payload_class: payload&.class&.name },
    )
    raise ArgumentError, "Unknown log type '#{type}'"
  end

  unless route.is_a?(String)
    APMErrorHandler.report(
      'VendorLogger: Invalid route parameter - must be a String',
      context: { route: route, route_class: route.class.name, type: type },
    )
    raise ArgumentError, 'Invalid route parameter - must be a String'
  end

  unless payload.nil? || payload.is_a?(Hash) || payload.is_a?(Array) || payload.is_a?(String) ||
      payload.is_a?(ActionController::Parameters) || payload.respond_to?(:as_json)
    APMErrorHandler.report(
      'VendorLogger: Invalid payload parameter - must be nil, Hash, Array, String, ActionController::Parameters, or respond to as_json',
      context: { payload_class: payload.class.name, type: type, route: route },
    )
    raise ArgumentError,
          'Invalid payload parameter - must be nil, Hash, Array, String, ActionController::Parameters, or respond to as_json'
  end

  unless custom_message.nil? || custom_message.is_a?(String) || custom_message.is_a?(Symbol)
    APMErrorHandler.report(
      'VendorLogger: Invalid custom_message parameter - must be nil, String, or Symbol',
      context: { custom_message_class: custom_message.class.name, type: type, route: route },
    )
    raise ArgumentError, 'Invalid custom_message parameter - must be nil, String, or Symbol'
  end

  formatted_payload =
    if payload.blank?
      CATEGORY_SUCCESS_MESSAGES[type]
    elsif payload.is_a?(ActionController::Parameters)
      payload.to_unsafe_h.to_json
    else
      payload.to_json
    end

  # If custom_message is :error, use the default error message for the category if available.
  message =
    if custom_message == :error && CATEGORY_ERROR_MESSAGES.key?(type)
      "#{route}##{CATEGORIES[type]} #{CATEGORY_ERROR_MESSAGES[type]}"
    elsif custom_message.present?
      "#{route}##{CATEGORIES[type]} #{custom_message}"
    else
      "#{route}##{CATEGORIES[type]} #{CATEGORY_MESSAGES[type]}"
    end

  BUSINESS_LOGGER.info(
    message,
    data_snapshot: formatted_payload,
    category: CATEGORIES[type],
    route: route,
  )

  true
rescue StandardError => e
  # Catch any error in the entire log_event method and report to APM
  APMErrorHandler.report(
    'VendorLogger: Failed to log event',
    exception: e,
    context: { type: type, route: route, payload_class: payload&.class&.name },
    payload: payload,
  )
  false
end