Skip to content

Commit

Permalink
adding ifql parser
Browse files Browse the repository at this point in the history
  • Loading branch information
Esity committed Jun 29, 2021
1 parent 544cfb0 commit 9470e75
Show file tree
Hide file tree
Showing 9 changed files with 493 additions and 40 deletions.
16 changes: 13 additions & 3 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,24 @@ Layout/LineLength:
Max: 120
Exclude:
- 'spec/**'
- 'spec/ifql/**'
Metrics/MethodLength:
Max: 100
Metrics/ClassLength:
Max: 1500
Metrics/BlockLength:
Max: 100
Max: 200
Metrics/PerceivedComplexity:
Max: 13
Metrics/CyclomaticComplexity:
Max: 11
Metrics/AbcSize:
Exclude:
- 'spec/**'
- 'spec/ifql/**'
- 'lib/telemetry/ifql/parser.rb'
Naming/MethodParameterName:
Enabled: false
Style/Documentation:
Enabled: false
Style/ModuleFunction:
Expand All @@ -17,6 +29,4 @@ AllCops:
NewCops: enable
SuggestExtensions: false
Style/FrozenStringLiteralComment:
Enabled: false
Naming/FileName:
Enabled: false
99 changes: 99 additions & 0 deletions lib/telemetry/ifql/formats.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
module Telemetry
module IFQL
module Formats
def measurement_error(message, show_error_message: true, status: 500, **)
response = MEASUREMENT.dup
response[:result] = {
error: message,
show_error_message: show_error_message,
status: status
}
response
end
module_function :measurement_error

MEASUREMENT = {
results: [
{
statement_id: 0,
series: [
{
name: 'measurements',
columns: ['name'],
values: []
}
]
}
]
}.freeze

FIELD_KEYS = {
results: [
{
statement_id: 0,
series: [
{
name: nil,
columns: %w[fieldKey fieldType],
values: []
}
]
}
]
}.freeze

DATABASE = {
results: [
{
statement_id: 0,
series: [
{
name: 'databases',
columns: ['name'],
values: [['telegraf']]
}
]
}
]
}.freeze

RETENTION_POLCIES = {
results: [
{
statement_id: 0,
series: [
{
columns: %w[
name
duration
shardGroupDuration
replicaN
default
],
values: [['autogen', '9600h0m0s', '24h0m0s', 1, true]]
}
]
}
]
}.freeze

TAG_VALUES = {
results: [
{
statement_id: 0,
series: [
{
name: 'conflux',
columns: %w[
key
value
],
values: []
}
]
}
]
}.freeze
end
end
end
151 changes: 151 additions & 0 deletions lib/telemetry/ifql/parser.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
require 'telemetry/number_helper'

module Telemetry
module IFQL
class Parser
include Telemetry::NumberHelper
attr_reader :query, :database, :params

def initialize(query, db: 'telegraf', **params)
@original_query = query
@query = query.downcase
if @query.include? 'ms'
@query.scan(/(\d+)ms/).flatten.each do |ms_time|
@query.sub! "#{ms_time}ms", (ms_time.to_f.round(-4) / 1000).to_s
end
end

@database = db
@params = params
@time_filter = nil
@limit_processed = false
end

def query_type(query: @query)
@query_type ||= if query.include? ';'
:multi_data
elsif query.include?('show measurements')
:measurement
elsif query.include? 'show databases'
:database
elsif query.include? 'show retention policies'
:rp
elsif query.include? 'show field keys'
:field_key
elsif query.include? 'show tag keys'
:tag_key
elsif query.include? 'show tag values'
:tag_value
elsif query.include? 'show series'
:series
else
:data
end
end

def measurement(query = @query)
@measurement ||= if query.include?('from')
query.split('from').last.split.first.split('.').last.tr('"', '')
elsif query.include?('with measurement')
query.split('with measurement').last.split('/')[1]
end
end

def limit?
return !limit.nil? if @limit_processed

!limit.nil?
end

def limit(query = @query)
return @limit if @limit_processed && @limit.is_a?(Integer)
return nil unless query.include? 'limit'

limit = query.split('limit').last.split.first
return nil unless integer?(limit)

@limit_processed = true
@limit = limit.to_i
end

def time_filter?
!@time_filter.nil? if @time_filter_processed

conditions.each do |cond|
if cond.include?('time')
@time_filter = cond
break
end
end

@time_filter_processed = true

!@time_filter.nil?
end

def conditions(query = @query)
return @conditions unless @conditions.nil?
return @conditions = [] unless query.include?('where')

@conditions = query.split('where').last
@conditions = @conditions.split('group').first if @conditions.include?('group')
@conditions = @conditions.split('fill').first if @conditions.include?('fill')
@conditions = @conditions.split('and').collect { |e| e.strip.tr('\\', '') }
@conditions.collect do |cond|
cond.chop! if cond[-1, 1] == ')' && cond[-2, 1] != '('
cond[0] = '' if cond[0] == '('
end

@conditions
rescue StandardError
[]
end

def group_by(query = @query)
@group_by ||= query.split('group by')[1].split('fill').first.tr('\\', '').split(',').collect(&:strip)
rescue StandardError
[]
end

def group_by_time
@group_by_time unless @group_by_time
@group_by_time = nil
group_by.each do |group|
next unless group.include?('time')

@group_by_time = group.split('(')[1].split(')').first.split(',').first
temp_time = @group_by_time.include?('h') ? @group_by_time.split('h').first.to_i * 60 * 60 : 0

if @group_by_time.include?('h') && @group_by_time.include?('m')
temp_time += @group_by_time.split('h').last.split('m').first.to_i * 60
elsif @group_by_time.include? 'm'
temp_time += @group_by_time.split('m').first.to_i * 60
end

if @group_by_time.include?('s') && @group_by_time.include?('m')
temp_time += @group_by_time.split('s').first.to_i
elsif @group_by_time.include?('s')
temp_time += @group_by_time.split('m').last.split('s').first.to_i
end

@group_by_time = temp_time
break
end
@group_by_time
end

def group_by_time?
@group_by_time unless @group_by_time.nil?
group_by.each do |group|
if group.include?('time')
@group_by_time = true
break
end
end

@group_by_time = false if @group_by_time.nil?
@group_by_time
end
end
end
end
4 changes: 2 additions & 2 deletions lib/telemetry/metrics/parser/line_protocol.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
require 'shellwords'
require 'telemetry/metrics/parser/number_helper'
require 'telemetry/number_helper'

module Telemetry
module Metrics
module Parser
module LineProtocol
extend Telemetry::Metrics::Parser::NumberHelper
extend Telemetry::NumberHelper

def parse(line, use_shellwords: false)
if use_shellwords
Expand Down
33 changes: 0 additions & 33 deletions lib/telemetry/metrics/parser/number_helper.rb

This file was deleted.

29 changes: 29 additions & 0 deletions lib/telemetry/number_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module Telemetry
module NumberHelper
def number?(str)
[str.to_f.to_s, str.to_i.to_s].include?(str)
end
module_function :number?

def float?(string)
string == string.to_f.to_s
end
module_function :float?

def integer?(string)
string == string.to_i.to_s
end
module_function :integer?

def convert_to_number(string)
if integer?(string)
string.to_i
elsif float?(string)
string.to_f
else
string
end
end
module_function :convert_to_number
end
end
30 changes: 30 additions & 0 deletions spec/ifql/formats_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require 'spec_helper'
require 'telemetry/ifql/formats'

RSpec.describe Telemetry::IFQL::Formats do
it 'can run measurement_error' do
expect(Telemetry::IFQL::Formats.measurement_error('error message', status: 501)).to be_a Hash
results = Telemetry::IFQL::Formats.measurement_error('error message', status: 501)
expect(results[:result][:status]).to eq 501
expect(results[:result][:error]).to eq 'error message'
end
it 'has a default measurement' do
expect(Telemetry::IFQL::Formats::MEASUREMENT).to be_a Hash
end

it 'has field keys' do
expect(Telemetry::IFQL::Formats::FIELD_KEYS).to be_a Hash
end

it 'has database' do
expect(Telemetry::IFQL::Formats::DATABASE).to be_a Hash
end

it 'has retention policies' do
expect(Telemetry::IFQL::Formats::RETENTION_POLCIES).to be_a Hash
end

it 'has tag values' do
expect(Telemetry::IFQL::Formats::TAG_VALUES).to be_a Hash
end
end
Loading

0 comments on commit 9470e75

Please sign in to comment.