Class: Mihari::Analyzers::Base

Inherits:
Mihari::Actor show all
Defined in:
lib/mihari/analyzers/base.rb

Overview

Base class for analyzers

Constant Summary

Constants included from Concerns::Retriable

Concerns::Retriable::DEFAULT_CONDITION, Concerns::Retriable::RETRIABLE_ERRORS

Instance Attribute Summary collapse

Attributes inherited from Mihari::Actor

#options

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Mihari::Actor

key, key_aliases, keys, #retry_exponential_backoff, #retry_interval, #retry_times, #timeout, type, #validate_configuration!

Methods included from Concerns::Retriable

#retry_on_error

Methods included from Concerns::Configurable

#configuration_keys?, #configured?

Constructor Details

#initialize(query, options: nil) ⇒ Base

Returns a new instance of Base.

Parameters:

  • query (String)
  • options (Hash, nil) (defaults to: nil)


16
17
18
19
20
# File 'lib/mihari/analyzers/base.rb', line 16

def initialize(query, options: nil)
  super(options: options)

  @query = query
end

Instance Attribute Details

#queryString (readonly)

Returns:

  • (String)


10
11
12
# File 'lib/mihari/analyzers/base.rb', line 10

def query
  @query
end

Class Method Details

.from_query(params) ⇒ Mihari::Analyzers::Base

Initialize an analyzer by query params

Parameters:

  • params (Hash)

Returns:



121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/mihari/analyzers/base.rb', line 121

def from_query(params)
  copied = params.deep_dup

  # convert params into arguments for initialization
  query = copied[:query]

  # delete analyzer and query
  i[analyzer query].each { |key| copied.delete key }

  copied[:options] = copied[:options] || nil

  new(query, **copied)
end

.inherited(child) ⇒ Object



135
136
137
138
# File 'lib/mihari/analyzers/base.rb', line 135

def inherited(child)
  super
  Mihari.analyzers << child
end

Instance Method Details

#artifactsArray<String>, Array<Mihari::Models::Artifact>

Returns:

Raises:

  • (NotImplementedError)


51
52
53
# File 'lib/mihari/analyzers/base.rb', line 51

def artifacts
  raise NotImplementedError, "You must implement #{self.class}##{__method__}"
end

#callArray<Mihari::Models::Artifact>

Returns:



78
79
80
# File 'lib/mihari/analyzers/base.rb', line 78

def call
  normalized_artifacts
end

#ignore_error?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/mihari/analyzers/base.rb', line 39

def ignore_error?
  options[:ignore_error] || Mihari.config.ignore_error
end

#normalized_artifactsArray<Mihari::Models::Artifact>

Normalize artifacts

  • Convert data (string) into an artifact

  • Reject an invalid artifact

Returns:



62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/mihari/analyzers/base.rb', line 62

def normalized_artifacts
  artifacts.compact.sort.map do |artifact|
    # No need to set data_type manually
    # It is set automatically in #initialize
    artifact = artifact.is_a?(Models::Artifact) ? artifact : Models::Artifact.new(data: artifact)

    artifact.source = self.class.key
    artifact.query = query

    artifact
  end.select(&:valid?).uniq(&:data)
end

#pagination_intervalInteger

Returns:

  • (Integer)


25
26
27
# File 'lib/mihari/analyzers/base.rb', line 25

def pagination_interval
  options[:pagination_interval] || Mihari.config.pagination_interval
end

#pagination_limitInteger

Returns:

  • (Integer)


32
33
34
# File 'lib/mihari/analyzers/base.rb', line 32

def pagination_limit
  options[:pagination_limit] || Mihari.config.pagination_limit
end

#parallel?Boolean

Returns:

  • (Boolean)


46
47
48
# File 'lib/mihari/analyzers/base.rb', line 46

def parallel?
  options[:parallel] || Mihari.config.parallel
end

#resultObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/mihari/analyzers/base.rb', line 82

def result(...)
  result = Try[StandardError] do
    retry_on_error(
      times: retry_times,
      interval: retry_interval,
      exponential_backoff: retry_exponential_backoff
    ) do
      call(...)
    end
  end.to_result

  return result if result.success?

  # Wrap failure with AnalyzerError to explicitly name a failed analyzer
  error = AnalyzerError.new(result.failure.message, self.class.key, cause: result.failure)
  return Failure(error) unless ignore_error?

  # Return Success if ignore_error? is true with logging
  Mihari.logger.warn("Analyzer:#{self.class.key} with #{truncated_query} failed - #{result.failure}")
  Success([])
end

#truncated_queryString

Truncate query for logging

Returns:

  • (String)


109
110
111
# File 'lib/mihari/analyzers/base.rb', line 109

def truncated_query
  query.truncate(32)
end