Class: LittleGhost::Support::ContentCapture

Inherits:
Object
  • Object
show all
Defined in:
lib/little_ghost/support/content_capture.rb

Overview

ContentCapture lets an application opt selected diagnostic content into telemetry after redaction and scrubbing. Capture stays off until an application installs an enabled policy.

policy = LittleGhost::Support::ContentCapture.new(
enabled: true,
max_bytes: 16_384,
redactions: [ENV.fetch("API_TOKEN")]
)
LittleGhost::Instrumentation.capture_content(policy)

Security and trust

Enabling capture may place model input, output, tool definitions, and exception details into telemetry. Redaction and a custom scrubber reduce accidental disclosure but are not a security boundary. Configure one policy per trusted process and apply exporter-side controls as well.

Constant Summary collapse

CaptureLimitExceeded =

:nodoc:

Class.new(StandardError)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(enabled: false, max_bytes: nil, scrubber: nil, redactions: []) ⇒ ContentCapture

Configures a policy. max_bytes is applied per captured attribute and scrubber receives already redacted values.

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
# File 'lib/little_ghost/support/content_capture.rb', line 32

def initialize(enabled: false, max_bytes: nil, scrubber: nil, redactions: [])
  @enabled = enabled == true
  @max_bytes = Integer(max_bytes) if max_bytes
  @scrubber = scrubber
  @redactor = Redactor.new(redactions:, stringify_keys: true)
  raise ArgumentError, "max_bytes must be at least 64" if @max_bytes && @max_bytes < 64
  raise ArgumentError, "scrubber must be callable" if @scrubber && !@scrubber.respond_to?(:call)
end

Class Method Details

.disabledObject

Creates a policy that never captures diagnostics.



28
# File 'lib/little_ghost/support/content_capture.rb', line 28

def self.disabled = new(enabled: false)

Instance Method Details

#capture(values) ⇒ Object

Produces scrubbed, JSON-encoded diagnostic attributes selected from values, or an empty hash when disabled.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/little_ghost/support/content_capture.rb', line 43

def capture(values)
  return {} unless @enabled && values.is_a?(Hash)

  values.each_with_object({}) do |(key, value), captured|
    next unless %i[input output exception tool_definitions].include?(key.to_sym)

    captured[:"diagnostic_#{key}"] = if key.to_sym == :tool_definitions
      capture_tool_definitions(value)
    else
      value = structured_output(value) if key.to_sym == :output
      scrubbed = scrub(value)
      scrubbed = scrub(@scrubber.call(scrubbed)) if @scrubber
      truncate(JSON.generate(scrubbed))
    end
  rescue JSON::GeneratorError, Encoding::UndefinedConversionError
    captured[:"diagnostic_#{key}"] = JSON.generate("[UNSERIALIZABLE]")
  end
end