Class: WavefrontCli::EventStore

Inherits:
Object
  • Object
show all
Includes:
Constants
Defined in:
lib/wavefront-cli/event_store.rb

Overview

Encapsulation of everything needed to manage the locally stored state of events opened by the CLI. This is our own addition, entirely separate from Wavefront’s API.

When the user creates an open-ended event (i.e. one that does not have and end time, and is not instantaneous) a state file is created in a local directory. (*)

That directory is defined by the EVENT_STATE_DIR constant, but may be overriden with an option in the constructor. The tests do this.

(*) The user may specifically request that no state file be created with the –nostate flag.

Constant Summary

Constants included from Constants

Constants::ALL_PAGE_SIZE, Constants::DEFAULT_CONFIG, Constants::DEFAULT_OPTS, Constants::EVENT_STATE_DIR, Constants::HUMAN_TIME_FORMAT, Constants::HUMAN_TIME_FORMAT_MS, Constants::SEARCH_SPLIT

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options, state_dir = nil) ⇒ EventStore

Returns a new instance of EventStore.

Parameters:

  • state_dir (Pathname) (defaults to: nil)

    override the default dir for testing



33
34
35
36
37
# File 'lib/wavefront-cli/event_store.rb', line 33

def initialize(options, state_dir = nil)
  @options = options
  @dir = event_state_dir(state_dir) + (Etc.getlogin || 'notty')
  create_dir(dir)
end

Instance Attribute Details

#dirObject (readonly)

Returns the value of attribute dir.



29
30
31
# File 'lib/wavefront-cli/event_store.rb', line 29

def dir
  @dir
end

#optionsObject (readonly)

Returns the value of attribute options.



29
30
31
# File 'lib/wavefront-cli/event_store.rb', line 29

def options
  @options
end

Instance Method Details

#create!(id) ⇒ Nil

Write a state file. We put the hosts bound to the event into the file. These aren’t currently used by anything in the CLI, but they might be useful to someone, somewhere, someday.

Returns:

  • (Nil)


118
119
120
121
122
123
124
125
126
# File 'lib/wavefront-cli/event_store.rb', line 118

def create!(id)
  return unless state_file_needed?

  fname = dir + id
  File.open(fname, 'w') { |fh| fh.puts(event_file_data) }
  puts "Event state recorded at #{fname}."
rescue StandardError
  puts 'NOTICE: event was created but state file was not.'
end

#create_dir(state_dir) ⇒ Object



139
140
141
142
143
144
145
146
147
# File 'lib/wavefront-cli/event_store.rb', line 139

def create_dir(state_dir)
  FileUtils.mkdir_p(state_dir)
  raise unless state_dir.exist? &&
               state_dir.directory? &&
               state_dir.writable?
rescue StandardError
  raise(WavefrontCli::Exception::SystemError,
        "Cannot create writable system directory at '#{state_dir}'.")
end

#event(id) ⇒ String

Returns the name of the most recent suitable event from the local stack directory.

Parameters:

  • id (String, Nil)

    if this is falsey, returns the event on the top of the state stack, removing its state file. If it’s an exact event ID, simply pass that ID back, NOT removing the state file. This is okay: the state file is cleaned up by WavefrontCli::Event when an event is closed. If it’s a name but not an ID, return the ID of the most recent event with the given name.

Returns:

  • (String)

    the name of the most recent suitable event from the local stack directory.



70
71
72
73
74
75
76
77
78
# File 'lib/wavefront-cli/event_store.rb', line 70

def event(id)
  if !id
    pop_event!
  elsif /^\d{13}:.+:\d+/.match?(id)
    id
  else
    pop_event!(id)
  end
end

#event_file(id) ⇒ Object



43
44
45
# File 'lib/wavefront-cli/event_store.rb', line 43

def event_file(id)
  /^\d{13}:.+/.match?(id) ? dir + id : nil
end

#event_file_dataString

Record event data in the state file. We don’t currently use it, but it might be useful to someone someday.

Returns:



132
133
134
135
136
137
# File 'lib/wavefront-cli/event_store.rb', line 132

def event_file_data
  { hosts: options[:host],
    description: options[:desc],
    severity: options[:severity],
    tags: options[:evtag] }.to_json
end

#event_state_dir(state_dir = nil) ⇒ Object

We can override the temp directory with the WF_EVENT_STATE_DIR env var. This is primarily for testing, though someone may find a valid use for it.



51
52
53
54
55
56
57
58
59
# File 'lib/wavefront-cli/event_store.rb', line 51

def event_state_dir(state_dir = nil)
  if ENV['WF_EVENT_STATE_DIR']
    Pathname.new(ENV['WF_EVENT_STATE_DIR'])
  elsif state_dir.nil?
    EVENT_STATE_DIR
  else
    Pathname.new(state_dir)
  end
end

#listObject

List events on the local stack



82
83
84
85
86
87
88
89
90
# File 'lib/wavefront-cli/event_store.rb', line 82

def list
  events = dir.children
  abort 'No locally recorded events.' if events.empty?

  events
rescue Errno::ENOENT
  raise(WavefrontCli::Exception::SystemError,
        'There is no event state directory on this host.')
end

#local_events_with_name(name = nil) ⇒ Array[String]

Event names are of the form ‘1609860826095:name:0`

Parameters:

  • name (String) (defaults to: nil)

    the user-specified (middle) portion of an event ID

Returns:



171
172
173
174
175
# File 'lib/wavefront-cli/event_store.rb', line 171

def local_events_with_name(name = nil)
  return list unless name

  list.select { |f| f.basename.to_s.split(':')[1] == name }
end

#pop_event!(name = nil) ⇒ Array[timestamp, event_name]

Get the last event this script created. If you supply a name, you get the last event with that name. If not, you get the last event. Note the ‘!’: this method (potentially) has side effects.

Parameters:

  • name (String) (defaults to: nil)

    name of event. This is the middle part of the real event name: the only part supplied by the user.

Returns:

  • (Array[timestamp, event_name])


156
157
158
159
160
161
162
163
164
165
# File 'lib/wavefront-cli/event_store.rb', line 156

def pop_event!(name = nil)
  return false unless dir.exist?

  list = local_events_with_name(name)
  return false if list.empty?

  ev_file = list.max
  File.unlink(ev_file)
  ev_file.basename.to_s
end

#run_wrapped_cmd(cmd) ⇒ Object

Run a command, stream stderr and stdout to the screen (they get combined – could be an issue for someone somewhere) and return the command’s exit code



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/wavefront-cli/event_store.rb', line 96

def run_wrapped_cmd(cmd)
  separator = '-' * (TW - 4)

  puts "Command output follows, on STDERR:\n#{separator}"
  ret = nil

  Open3.popen2e(cmd) do |_in, out, thr|
    # rubocop:disable Lint/AssignmentInCondition
    while l = out.gets do warn l end
    # rubocop:enable Lint/AssignmentInCondition
    ret = thr.value.exitstatus
  end

  puts separator
  ret
end

#state_file_needed?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/wavefront-cli/event_store.rb', line 39

def state_file_needed?
  !(options[:nostate] || options[:end] || options[:instant])
end