LoginSignup
0
0

More than 5 years have passed since last update.

norikra_query_debug.rb

Last updated at Posted at 2015-01-12

NorikraQueryDebugとは

  • お好きなテキストエディタでノリクラクエリを書くと
  • 書きなおすたびに自動的にアップロードしてくれつつ
  • クエリの結果がコンソールにながれるやつ。

コマンド

ruby norikra_query_debug.rb start_debug query.txt --host NORIKRA_HOST

クエリファイル

"@@@"で始まる行で区切って複数のクエリを書きます。

query.txt
@@@ name=query1 group=debug
SELECT ...
FROM ...
WHERE ...

@@@ name=query2 group=LOOPBACK(loopback_from_query2)
SELECT ...
FROM ...
WHERE ...

@@@ name=query3 group=debug
SELECT ...
FROM loopback_from_query2
WHERE ...

@@@ name=msg_per_second group=debug
SELECT
  COUNT(1) as mps
FROM
  target.win:time_batch(1sec)

コード

norikra_query_debug.rb
require "norikra-client"
require "thor"
require 'timeout'
require 'io/console'
require "ostruct"

class NorikraQueryDebug
  def initialize(host,port)
    @host = host
    @port = port
    @client = Norikra::Client.new(@host,@port)
    @event_count = 0
    @queries = []
  end

  def start_debug(query_file)
    puts "Hit 'q' to quit."
    next_fetch_time = Time.now
    loop do
      now = Time.now

      case input_cmd
      when :quit
        break
      end

      if file_updated?(query_file)
        @queries.each do |q|
          @client.deregister(q.name)
        end

        @queries = parse_query_file(query_file)
        @queries.each_with_index do |q,query_index|
          puts "################################################################"
          puts "## [#{'%03d' % [query_index+1]}] #{q.name},#{q.group} (#{query_file})"
          puts q.query
          if update_query(q.name, q.group, q.query)
            puts "## OK     name=#{q.name} group=#{q.group} host=#{@host} port=#{@port}"
            puts ""
          else
            puts "## FAILED name=#{q.name} group=#{q.group} host=#{@host} port=#{@port}"
            puts ""
          end
        end
        puts ""
      end

      if next_fetch_time < now
        @queries.each do |q|
          events = @client.event(q.name)
          events.each do |time,event|
            puts("[%d] %s | %s : %s" % [@event_count, Time.at(time).strftime("%Y-%m-%d %H:%M:%S"), q.name, event.inspect])
            @event_count += 1
          end
        end
        next_fetch_time = now+1
      end
    end

    @queries.each do |q|
      @client.deregister(q.name)
    end
  end

  def parse_query_file(filename)
    queries = []

    name  = nil
    group = nil
    query = ""
    query_index = 0

    s = File.read(filename)
    lines = ["@@@"] + s.lines
    commit_query = proc do
      if query!=""
        queries << OpenStruct.new({:name=>name, :group=>group, :query=>query})
        query_index += 1
      end
      name  = "query#{'%03d' % [query_index+1]}_#{`whoami`.strip}@#{`hostname`.strip}"
      group = "debug"
      query = ""
    end
    lines.each do |line|
      if line =~ /^@@@/
        commit_query.call
        if line =~ /name=(\S+)/
          name = $1
        end
        if line =~ /group=(\S+)/
          group = $1
          if group=="nil"
            group = nil
          end
        end
      else
        query << line
      end
    end
    commit_query.call
    return queries
  end

  def update_query(name, group, query)
    begin
      begin
        @client.register(name,group,query)
      rescue Norikra::RPC::ClientError => e
        if e.message =~ /query name.+already exists/
          @client.deregister(name)
          @client.register(name,group,query)
        else
          raise e
        end
      end
      return true
    rescue => e
      puts e.message
    end
    return false
  end

  def file_updated?(filename)
    unless File.exist?(filename)
      raise "not exist filename=#{filename}"
    end
    mtime = File.mtime(filename)
    size  = File.size(filename)

    @file_states ||= {}
    old_state = @file_states[filename]
    if old_state && old_state[:mtime]==mtime && old_state[:size]==size
      return false
    end
    @file_states[filename] = {:mtime=>mtime, :size=>size}
    return true
  end

  def input_cmd
    begin
      c = Timeout::timeout(0.1) do
        $stdin.getch
      end
      if c=="q"
        return :quit
      end
      if c=="\r"
        puts
      else
        putc(c)
      end
    rescue Timeout::Error => e
      return :timeout
    end
    return nil
  end

  class CLI < Thor
    desc "start_debug QUERY_FILE", "upload query for each update, and fetch result."
    option :host,  :type=>:string,  :default=>"localhost"
    option :port,  :type=>:numeric, :default=>26571
    def start_debug(query_file)
      nqd = NorikraQueryDebug.new(options[:host], options[:port])
      nqd.start_debug(query_file)
    end
    default_task :start_debug
  end
end

NorikraQueryDebug::CLI.start

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0