SignalFx filter for None - filter

I'm trying to build a detector with signalfx and I want to make a filter query on a daat stream that will fetch me metrics with dimension name "foo" and value "baz" but also ones that do not have this dimension at all. I've been trying something like this:
filter('foo', 'baz', None)
filter('foo', 'baz', '')
but it just proudces errors.

Since my dimension value was a flag I just used a workaround and instead of filtering for value true or None I filter for not True like this:
not filter('foo' '1')
and this works since I wanted all items with foo set to '0' or ones that do not have foo at all.

Related

Ruby Array sort_by value in variable

I would like to sort Ruby Array by key in variable, but I don't know how.
Situation
my_arr.sort_by {|record| [record.year]}
Will sort by a year of the record. But I want to sort by author, label, etc. And this sort type is stored in a variable like a String. So I need to evaluate the filter like
my_arr.sort_by {|record| [record."something_in_the_var"]}
Of course, I have fixed filters. But still figuring out how to do it properly.
Thanks for tips
This is what send does
str = "label"
arr.sort_by{|rec| rec.send(str) }
send is defined on BasicObject, so every object has it.
you can use something like
sort_by_this = "label"
my_arr.sort_by {|record| [record[sort_by_this]]}

Fix deprecation warning `Dangerous query method` on `.order`

I have a custom gem which creates a AR query with input that comes from an elasticsearch instance.
# record_ids: are the returned ids of the ES results
# order: is the order of the of the ids that ES returns
search_class.where(search_class.primary_key => record_ids).order(order)
Right now the implementation is that I build the order string directly into the order variable so it looks like this: ["\"positions\".\"id\" = 'fcdc924a-21da-440e-8d20-eec9a71321a7' DESC"]
This works fine but throws a deprecation warning which ultimately will not work in rails6.
DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): "\"positions\".\"id\" = 'fcdc924a-21da-440e-8d20-eec9a71321a7' DESC". Non-attribute arguments will be disallowed in Rails 6.0. This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql()
So I tried couple of different approaches but all of them with no success.
order = ["\"positions\".\"id\" = 'fcdc924a-21da-440e-8d20-eec9a71321a7' DESC"]
# Does not work since order is an array
.order(Arel.sql(order))
# No errors but only returns an ActiveRecord_Relation
# on .inspect it returns `PG::SyntaxError: ERROR: syntax error at or near "["`
.order(Arel.sql("#{order}"))
# .to_sql: ORDER BY [\"\\\"positions\\\".\\\"id\\\" = 'fcdc924a-21da-440e-8d20-eec9a71321a7' DESC\"]"
order = ['fcdc924a-21da-440e-8d20-eec9a71321a7', ...]
# Won't work since its only for integer values
.order("idx(ARRAY#{order}, #{search_class.primary_key})")
# .to_sql ORDER BY idx(ARRAY[\"fcdc924a-21da-440e-8d20-eec9a71321a7\", ...], id)
# Only returns an ActiveRecord_Relation
# on .inspect it returns `PG::InFailedSqlTransaction: ERROR:`
.order("array_position(ARRAY#{order}, #{search_class.primary_key})")
# .to_sql : ORDER BY array_position(ARRAY[\"fcdc924a-21da-440e-8d20-eec9a71321a7\", ...], id)
I am sort of stuck since rails forces attribute arguments in the future and an has no option to opt out of this. Since the order is a code generated array and I have full control of the values I am curious how I can implement this. Maybe someone had this issue before an give some useful insight or idea?
You could try to apply Arel.sql to the elements of the array, that should work, ie
search_class.where(search_class.primary_key => record_ids)
.order(order.map {|i| i.is_a?(String) ? Arel.sql(i) : i})

Trouble reading and binding yml data in ruby

I have a yaml file that includes the following:
:common
:substitue
:foo: fee
I read this data like:
data = YAML.load(erb_data[File.basename(__FILE__, '.*')].result(binding))
common = data[:common]
def substitute_if_needed(original_value)
mapping = common.dig(:substitue, original_value)
if mapping.nil? ? original_value : mapping
end
Unfortunately, this doesn't do the substitution that I want. I want to call substitute_if_needed('foo') and get 'fee' back. I also want to call substitute_if_needed('bar') and get 'bar' back.
How can I do this?
There are several problems in your code:
YAML example looks broken. The proper one should looks like:
common:
substitute:
foo: fee
You're trying to fetch common key in common = data[:common] using a symbol as a key, but it should be a string (data["common"]). Also, I'd say it's a bad idea to spilt fetching logic into two pieces - first extract "common" outside of substitute_when_needed and then dig into it inside.
if statement is broken. It should be either proper if or proper ternary operator.
Fixing all this gives us something like (I've just replaced a file with StringIO for convenience - to make the snippet executable as is):
yaml = StringIO.new(<<~DATA)
common:
substitute:
foo: fee
DATA
def substitute_if_needed(data, original_value)
mapping = data.dig("common", "substitute", original_value)
mapping.nil? ? original_value : mapping
end
data = YAML.load(yaml)
substitute_if_needed(data, "foo") # => "fee"
substitute_if_needed(data, "bar") # => "bar"

find() from MongoDB, return result, supress fields and turn into JSON

I Have data saved in a MongoDB in the following format
{"_id": "VALVE22","state": "1","element": "BNK1FLOW","data":{"type": "SEN","descr": "TOWER6"}}
I have the following code in a Ruby script;
db = Mongo::Connection.new.db("cooler-lookup")
coll = db.collection("elements")
kitty = coll.find({"_id" => table[address][i], "state" => char}).to_a
'table[address][i]' and 'char' are variables defined & used elsewhere in the bigger script feeding data into this lookup section. For testing these can be replaced with "VALVE22" and "1" respectively (and that's how I've been testing in irb)
When run from the command line the script outputs the following correct result from a valid query.
{"_id"=>"VLAVE22", "state"=>"1", "element"=>"BNK1FLOW", "data"=>{"type"=>"SEN", "descr"=>"TOWER6"}}
But I need to suppress the _id and state fields. I've tried using :fields modifier in all sorts of ways but can't remove the fields. I have tested this in irb and along with the valid lookup I also get => nil returned. I'm sure this is something really simple but I can't see what I need to be able to JSON.generate the query results without the ID & State fields and then puts it.
Using the code below I was able to get this working, however when I tried to do kittylitter = JSON.generate(kitty) I was getting a lot of empty []'s as well as my valid result. It looks like they where the failed queries from the DB coming back with no record.
After many hours of being confused I managed to find this bit of code to fix the problem
kitty.each do |key|
keyjson = JSON.generate(key)
puts keyjson
end
That gave me exactly what I needed out - which was the result on 1 line as valid JSON. Part of my head hurting confusion comes from the fact to.a makes an array, yet when I tried to do array type stuff on the result kitty nothing would work as expected. I then tried treating it like a hash which led me to that bit of code above! Once I'd done that everything worked... Am I wrong to be confused by arrays and hashes or have I missed something real obvious like my array is or contains a hash?
This works for me:
kitty = coll.find({"_id" => table[address][i], "state" => char}, :fields => {"_id" => 0, "state" => 0}).to_a
It returns
[{"element"=>"BNK1FLOW", "data"=>{"type"=>"SEN", "descr"=>"TOWER6"}}]
See http://api.mongodb.org/ruby/current/Mongo/Collection.html#find-instance_method for usage instructions for Mongo::Collection#find
Using gem mongo -v 2.4.3 , the following works for me
mongo_results = collection.find({"shop_id" => shop_id}, :projection => {"_id" => 0, "child_products" => 0}).to_a
In the example above, I'm omitting "_id" and "child_products" from showing up in the results.

Create an object if one is not found

How do I create an object if one is not found? This is the query I was running:
#event_object = #event_entry.event_objects.find_all_by_plantype('dog')
and I was trying this:
#event_object = EventObject.new unless #event_entry.event_objects.find_all_by_plantype('dog')
but that does not seem to work. I know I'm missing something very simple like normal :( Thanks for any help!!! :)
find_all style methods return an array of matching records. That is an empty array if no matching records are found. And an empty is truthy. Which means:
arr = []
if arr
puts 'arr is considered turthy!' # this line will execute
end
Also, the dynamic finder methods (like find_by_whatever) are officially depreacted So you shouldn't be using them.
You probably want something more like:
#event_object = #event_entry.event_objects.where(plantype: 'dog').first || EventObject.new
But you can also configure the event object better, since you obviously want it to belong to #event_entry.
#event_object = #event_entry.event_objects.where(plantype: 'dog').first
#event_object ||= #event_entry.event_objects.build(plantype: dog)
In this last example, we try to find an existing object by getting an array of matching records and asking for the first item. If there are no items, #event_object will be nil.
Then we use the ||= operator that says "assign the value on the right if this is currently set to a falsy value". And nil is falsy. So if it's nil we can build the object form the association it should belong to. And we can preset it's attributes while we are at it.
Why not use built in query methods like find_or_create_by or find_or_initialize_by
#event_object = #event_entry.event_objects.find_or_create_by(plantype:'dog')
This will find an #event_entry.event_object with plantype = 'dog' if one does not exist it will then create one instead.
find_or_initialize_by is probably more what you want as it will leave #event_object in an unsaved state with just the association and plantype set
#event_object = #event_entry.event_objects.find_or_initialize_by(plantype:'dog')
This assumes you are looking for a single event_object as it will return the first one it finds with plantype = 'dog'. If more than 1 event_object can have the plantype ='dog' within the #event_entry scope then this might not be the best solution but it seems to fit with your description.

Resources