|
| 1 | +require 'telemetry/number_helper' |
| 2 | + |
| 3 | +module Telemetry |
| 4 | + module IFQL |
| 5 | + class Parser |
| 6 | + include Telemetry::NumberHelper |
| 7 | + attr_reader :query, :database, :params |
| 8 | + |
| 9 | + def initialize(query, db: 'telegraf', **params) |
| 10 | + @original_query = query |
| 11 | + @query = query.downcase |
| 12 | + if @query.include? 'ms' |
| 13 | + @query.scan(/(\d+)ms/).flatten.each do |ms_time| |
| 14 | + @query.sub! "#{ms_time}ms", (ms_time.to_f.round(-4) / 1000).to_s |
| 15 | + end |
| 16 | + end |
| 17 | + |
| 18 | + @database = db |
| 19 | + @params = params |
| 20 | + @time_filter = nil |
| 21 | + @limit_processed = false |
| 22 | + end |
| 23 | + |
| 24 | + def query_type(query: @query) |
| 25 | + @query_type ||= if query.include? ';' |
| 26 | + :multi_data |
| 27 | + elsif query.include?('show measurements') |
| 28 | + :measurement |
| 29 | + elsif query.include? 'show databases' |
| 30 | + :database |
| 31 | + elsif query.include? 'show retention policies' |
| 32 | + :rp |
| 33 | + elsif query.include? 'show field keys' |
| 34 | + :field_key |
| 35 | + elsif query.include? 'show tag keys' |
| 36 | + :tag_key |
| 37 | + elsif query.include? 'show tag values' |
| 38 | + :tag_value |
| 39 | + elsif query.include? 'show series' |
| 40 | + :series |
| 41 | + else |
| 42 | + :data |
| 43 | + end |
| 44 | + end |
| 45 | + |
| 46 | + def measurement(query = @query) |
| 47 | + @measurement ||= if query.include?('from') |
| 48 | + query.split('from').last.split.first.split('.').last.tr('"', '') |
| 49 | + elsif query.include?('with measurement') |
| 50 | + query.split('with measurement').last.split('/')[1] |
| 51 | + end |
| 52 | + end |
| 53 | + |
| 54 | + def limit? |
| 55 | + return !limit.nil? if @limit_processed |
| 56 | + |
| 57 | + !limit.nil? |
| 58 | + end |
| 59 | + |
| 60 | + def limit(query = @query) |
| 61 | + return @limit if @limit_processed && @limit.is_a?(Integer) |
| 62 | + return nil unless query.include? 'limit' |
| 63 | + |
| 64 | + limit = query.split('limit').last.split.first |
| 65 | + return nil unless integer?(limit) |
| 66 | + |
| 67 | + @limit_processed = true |
| 68 | + @limit = limit.to_i |
| 69 | + end |
| 70 | + |
| 71 | + def time_filter? |
| 72 | + !@time_filter.nil? if @time_filter_processed |
| 73 | + |
| 74 | + conditions.each do |cond| |
| 75 | + if cond.include?('time') |
| 76 | + @time_filter = cond |
| 77 | + break |
| 78 | + end |
| 79 | + end |
| 80 | + |
| 81 | + @time_filter_processed = true |
| 82 | + |
| 83 | + !@time_filter.nil? |
| 84 | + end |
| 85 | + |
| 86 | + def conditions(query = @query) |
| 87 | + return @conditions unless @conditions.nil? |
| 88 | + return @conditions = [] unless query.include?('where') |
| 89 | + |
| 90 | + @conditions = query.split('where').last |
| 91 | + @conditions = @conditions.split('group').first if @conditions.include?('group') |
| 92 | + @conditions = @conditions.split('fill').first if @conditions.include?('fill') |
| 93 | + @conditions = @conditions.split('and').collect { |e| e.strip.tr('\\', '') } |
| 94 | + @conditions.collect do |cond| |
| 95 | + cond.chop! if cond[-1, 1] == ')' && cond[-2, 1] != '(' |
| 96 | + cond[0] = '' if cond[0] == '(' |
| 97 | + end |
| 98 | + |
| 99 | + @conditions |
| 100 | + rescue StandardError |
| 101 | + [] |
| 102 | + end |
| 103 | + |
| 104 | + def group_by(query = @query) |
| 105 | + @group_by ||= query.split('group by')[1].split('fill').first.tr('\\', '').split(',').collect(&:strip) |
| 106 | + rescue StandardError |
| 107 | + [] |
| 108 | + end |
| 109 | + |
| 110 | + def group_by_time |
| 111 | + @group_by_time unless @group_by_time |
| 112 | + @group_by_time = nil |
| 113 | + group_by.each do |group| |
| 114 | + next unless group.include?('time') |
| 115 | + |
| 116 | + @group_by_time = group.split('(')[1].split(')').first.split(',').first |
| 117 | + temp_time = @group_by_time.include?('h') ? @group_by_time.split('h').first.to_i * 60 * 60 : 0 |
| 118 | + |
| 119 | + if @group_by_time.include?('h') && @group_by_time.include?('m') |
| 120 | + temp_time += @group_by_time.split('h').last.split('m').first.to_i * 60 |
| 121 | + elsif @group_by_time.include? 'm' |
| 122 | + temp_time += @group_by_time.split('m').first.to_i * 60 |
| 123 | + end |
| 124 | + |
| 125 | + if @group_by_time.include?('s') && @group_by_time.include?('m') |
| 126 | + temp_time += @group_by_time.split('s').first.to_i |
| 127 | + elsif @group_by_time.include?('s') |
| 128 | + temp_time += @group_by_time.split('m').last.split('s').first.to_i |
| 129 | + end |
| 130 | + |
| 131 | + @group_by_time = temp_time |
| 132 | + break |
| 133 | + end |
| 134 | + @group_by_time |
| 135 | + end |
| 136 | + |
| 137 | + def group_by_time? |
| 138 | + @group_by_time unless @group_by_time.nil? |
| 139 | + group_by.each do |group| |
| 140 | + if group.include?('time') |
| 141 | + @group_by_time = true |
| 142 | + break |
| 143 | + end |
| 144 | + end |
| 145 | + |
| 146 | + @group_by_time = false if @group_by_time.nil? |
| 147 | + @group_by_time |
| 148 | + end |
| 149 | + end |
| 150 | + end |
| 151 | +end |
0 commit comments