Class: Kotoshu::Integrity::RotationPolicy

Inherits:
Object
  • Object
show all
Defined in:
lib/kotoshu/integrity/rotation_policy.rb

Overview

Pure value object that decides when an AuditLog should rotate and produces the rename plan that realises the rotation.

The policy is intentionally IO-free so it can be unit-tested in isolation. AuditLog#record consults the policy on every write and executes the returned plan via FileUtils.

Rotation scheme: keep rotations historical files alongside the current one. On rotation:

1. Drop the oldest rotation slot (<path>.<rotations>).
2. Shift each remaining rotation up by one suffix.
3. Promote the current log to <path>.1.

Net effect: current + N rotated files, total bounded at +max_bytes * (rotations + 1)+.

Constant Summary collapse

DEFAULT_MAX_BYTES =

10 MB

10 * 1024 * 1024
DEFAULT_ROTATIONS =
5

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max_bytes: DEFAULT_MAX_BYTES, rotations: DEFAULT_ROTATIONS) ⇒ RotationPolicy

Returns a new instance of RotationPolicy.

Raises:

  • (ArgumentError)


27
28
29
30
31
32
# File 'lib/kotoshu/integrity/rotation_policy.rb', line 27

def initialize(max_bytes: DEFAULT_MAX_BYTES, rotations: DEFAULT_ROTATIONS)
  @max_bytes = max_bytes.to_i
  @rotations = rotations.to_i
  raise ArgumentError, "max_bytes must be >= 0" if @max_bytes.negative?
  raise ArgumentError, "rotations must be >= 0" if @rotations.negative?
end

Instance Attribute Details

#max_bytesObject (readonly)

Returns the value of attribute max_bytes.



25
26
27
# File 'lib/kotoshu/integrity/rotation_policy.rb', line 25

def max_bytes
  @max_bytes
end

#rotationsObject (readonly)

Returns the value of attribute rotations.



25
26
27
# File 'lib/kotoshu/integrity/rotation_policy.rb', line 25

def rotations
  @rotations
end

Instance Method Details

#plan_for(path) ⇒ Object

Plan the file operations required to rotate path.

Returns a hash with two keys:

+:deletes+ — Array<String> of paths to remove (+FileUtils.rm_f+).
+:moves+   — Array<[String, String]> of (source, dest) pairs
           (+FileUtils.mv+).

The plan is ordered so that a caller executing the deletes first and then the moves in array order will not clobber any still-live rotation. Sources that happen not to exist are silently skipped by FileUtils.mv, so the plan can be applied verbatim.

When rotations is zero, the plan deletes the current path; the caller's next append recreates it as an empty file (effectively a truncate).

Parameters:

  • path (String)

    The current log path (e.g. "/x/audit.log").



59
60
61
62
63
64
65
66
67
68
# File 'lib/kotoshu/integrity/rotation_policy.rb', line 59

def plan_for(path)
  if rotations.positive?
    {
      deletes: [rotated_path(path, rotations)],
      moves: shift_moves(path).push([path, rotated_path(path, 1)])
    }
  else
    { deletes: [path], moves: [] }
  end
end

#rotate?(current_size) ⇒ Boolean

True when the current file size exceeds the configured ceiling.

Parameters:

  • current_size (Integer)

    Bytes of the current log file.

Returns:

  • (Boolean)


37
38
39
# File 'lib/kotoshu/integrity/rotation_policy.rb', line 37

def rotate?(current_size)
  current_size > max_bytes
end