<commit_before>#!/usr/bin/env ruby

# monitoring daemon for ruby checks

require 'daemons'
require 'json'

module Monitoring

  class Check
    attr_accessor :clazz, :options, :interval, :retry, :timeout, :storage
  end

  class MonDaemon < BundleCommand

    def initialize
      super(false)
      @var = "#{DEVOPS_ROOT}/var"
      system("mkdir -p #{@var}")

      @config_file = "#{DEVOPS_ROOT}/etc/monitoring/config.json"
      @loaded_checks = {}
      @class_map = {}
      @reports = []
    end

    def reload_config
      if File.exists? @config_file then
        checks = JSON.parse(File.read(@config_file))
        load_all_checks(checks)
      else
        @loaded_checks = {}
      end
    end

    # Run the specified Check
    #
    # @param [Check] check
    def run_check(check)

      obj = check.clazz.new(check.options.dup)
      obj.storage = check.storage

      obj.monitor()
      obj.status == "OK" if obj.status.nil?

      obj.save_storage()
      check.storage = obj.storage

      @reports << obj
    end

    def send_reports
      req = JsonRequest.new("metrics:put_check_result", [ @reports ])
      res = req.exec()

      if not res.success? then
        # TODO failover to disk buffer??
        puts "error reporting to server:"
        puts res
      end

      @reports.clear
    end

    def load_all_checks(checks)

      # array of classes already loaded
      # we maintain this in order to figure out which Class was loaded during 'require'
      # a bit hacky..
      loaded_classes = class_map.values.dup # @loaded_checks.values.map{ |c| c.clazz }

      checks.each do |check|

        # create command and validate
        command = CommandSpec.new(check["command"])
        begin
          command.validate()
        rescue Exception => ex
          puts "error loading check: #{command}"
          puts ex
          return
        end

        next if command.command !~ /\.rb$/ # skip non-ruby checks

        # require script if necessary
        key = command.bundle + "/" + command.command
        if not @class_map.include? key then
          # puts "loading #{key}"
          lib = "#{command.bundle_dir}/lib"
          $:.unshift(lib) if File.directory? lib and not $:.include? lib
          # puts "require #{command.command_file}"
          require command.command_file

          subclasses = Monitoring::Base.subclasses - loaded_classes
          clazz = subclasses.first
          loaded_classes << clazz
          class_map[key] = clazz
        end

        # instantiate the Check
        c = Check.new

        c.clazz    = class_map[key]
        c.options  = JSON.parse(command.stdin)
        c.interval = check["interval"]
        c.retry    = check["retry"]
        c.timeout  = check["timeout"]
        c.storage  = c.clazz.new(c.options.dup).load_storage()

        @loaded_checks[key] = c

      end # checks.each
    end # load_all_checks<commit_msg>fixed var scope<commit_after>#!/usr/bin/env ruby

# monitoring daemon for ruby checks

require 'daemons'
require 'json'

module Monitoring

  class Check
    attr_accessor :clazz, :options, :interval, :retry, :timeout, :storage
  end

  class MonDaemon < BundleCommand

    def initialize
      super(false)
      @var = "#{DEVOPS_ROOT}/var"
      system("mkdir -p #{@var}")

      @config_file = "#{DEVOPS_ROOT}/etc/monitoring/config.json"
      @loaded_checks = {}
      @class_map = {}
      @reports = []
    end

    def reload_config
      if File.exists? @config_file then
        checks = JSON.parse(File.read(@config_file))
        load_all_checks(checks)
      else
        @loaded_checks = {}
      end
    end

    # Run the specified Check
    #
    # @param [Check] check
    def run_check(check)

      obj = check.clazz.new(check.options.dup)
      obj.storage = check.storage

      obj.monitor()
      obj.status == "OK" if obj.status.nil?

      obj.save_storage()
      check.storage = obj.storage

      @reports << obj
    end

    def send_reports
      req = JsonRequest.new("metrics:put_check_result", [ @reports ])
      res = req.exec()

      if not res.success? then
        # TODO failover to disk buffer??
        puts "error reporting to server:"
        puts res
      end

      @reports.clear
    end

    def load_all_checks(checks)

      # array of classes already loaded
      # we maintain this in order to figure out which Class was loaded during 'require'
      # a bit hacky..
      loaded_classes = @class_map.values.dup # @loaded_checks.values.map{ |c| c.clazz }

      checks.each do |check|

        # create command and validate
        command = CommandSpec.new(check["command"])
        begin
          command.validate()
        rescue Exception => ex
          puts "error loading check: #{command}"
          puts ex
          return
        end

        next if command.command !~ /\.rb$/ # skip non-ruby checks

        # require script if necessary
        key = command.bundle + "/" + command.command
        if not @class_map.include? key then
          # puts "loading #{key}"
          lib = "#{command.bundle_dir}/lib"
          $:.unshift(lib) if File.directory? lib and not $:.include? lib
          # puts "require #{command.command_file}"
          require command.command_file

          subclasses = Monitoring::Base.subclasses - loaded_classes
          clazz = subclasses.first
          loaded_classes << clazz
          @class_map[key] = clazz
        end

        # instantiate the Check
        c = Check.new

        c.clazz    = @class_map[key]
        c.options  = JSON.parse(command.stdin)
        c.interval = check["interval"]
        c.retry    = check["retry"]
        c.timeout  = check["timeout"]
        c.storage  = c.clazz.new(c.options.dup).load_storage()

        @loaded_checks[key] = c

      end # checks.each
    end # load_all_checks
{'fraction_non_alphanumeric': 0.10552420044467248, 'fraction_numerical': 0.0, 'mean_word_length': 2.0569785676947205, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '230751', 'n_tokens_mistral': 1798, 'n_tokens_neox': 1707, 'n_words': 451}