Esper filter events by pattern - esper

I try select some events from flow through match_recognize function and receive error message. I can't understand why my pattern not work or I something miss in my statement. Maybe somebody can help me with my statement.
I have EPL Statement:
create schema Event1(alert_id string, user_dst string, host_src string, ip_src string);
SELECT * FROM Event1.win:time(5 minute)
MATCH_RECOGNIZE (
partition by ip_src
measures A as a, B as b, C as c
pattern (A B+ C)
define
A as A.alert_id !='account:logout',
B as B.alert_id !='account:logout' and B.user_dst != A.user_dst,
C as C.alert_id !='account:logout' and C.user_dst != A.user_dst and C.user_dst != B.user_dst
)
and events sequence:
Event1={alert_id='account:logon-success', user_dst='admin1', host_src='xxx.ru', ip_src='10.10.0.1'}
t=t.plus(5 seconds)
Event1={alert_id='account:logon-success', user_dst='admin', host_src='xxx.ru', ip_src='10.10.0.1'}
t=t.plus(500 seconds)
Event1={alert_id='account:logon-success', user_dst='admin2', host_src='yyy.ru', ip_src='10.10.0.2'}
t=t.plus(5 seconds)
Event1={alert_id='account:logout', user_dst='admin3', host_src='yyy.ru', ip_src='10.10.0.2'}
t=t.plus(5 seconds)
Event1={alert_id='account:logon-success', user_dst='admin4', host_src='yxy.ru', ip_src='10.10.0.2'}
t=t.plus(5 seconds)
Event1={alert_id='account:logon-success', user_dst='admin', host_src='yxy.ru', ip_src='10.10.0.2'}
t=t.plus(5 seconds)
Event1={alert_id='account:logon-success', user_dst='admin', host_src='yxy.ru', ip_src='10.10.0.2'}
t=t.plus(5 seconds)
Event1={alert_id='account:logon-success', user_dst='admin3', host_src='yyy.ru', ip_src='10.10.0.2'}
As result of processing statement I wait those events:
Event1={alert_id='account:logon-success', user_dst='admin4', host_src='yxy.ru', ip_src='10.10.0.2'}
Event1={alert_id='account:logon-success', user_dst='admin', host_src='yxy.ru', ip_src='10.10.0.2'}
Event1={alert_id='account:logon-success', user_dst='admin3', host_src='yyy.ru', ip_src='10.10.0.2'}
PS: I test my statement at Esper EPL Online: http://esper-epl-tryout.appspot.com/epltryout/mainform.html

I found solution, need was use C.user_dst != B[0].user_dst insted of C.user_dst != B.user_dst

Related

add days to given timestamp (YYYY-mm-dd HH:MM:SS.sss) in lua script

Summary
I would like to add 1 day to given timestamp in lua script.
My try
local creation_date = "2016-01-01 00:00:00.000"
local y, m, d, Hr, Min, Sec, Milli = creation_date:match '(%d+)-(%d+)-(%d+) (%d+):(%d+):(%d+).(%d+)'
local dt = y .. '-' .. m .. '-'..d.. ' '..Hr..':'..Min..'-'..Sec..'.'..Milli
print(dt)
local new_ts = os.time
{ year = y, month = m, day = d,
hour = Hr, min = Min, sec = Sec, mill=Milli } + 1*24*60*60
print(new_ts)
I am getting new_ts = 1452470400
Expected result
2016-01-01 00:01:00.000 (in this format only)
The closest you may be able to get is something like this:
local creation_date = "2016-01-01 00:00:00.000"
local y, m, d, Hr, Min, Sec, Milli = creation_date:match '(%d+)-(%d+)-(%d+) (%d+):(%d+):(%d+).(%d+)'
local dt = y .. '-' .. m .. '-'..d.. ' '..Hr..':'..Min..'-'..Sec..'.'..Milli
print(dt)
local new_ts = os.time { year = y, month = m, day = d, hour = Hr, min = Min, sec = Sec } + 1*24*60*60
print(string.format("%s.%03d", os.date("%Y-%m-%d %H:%M:%S", new_ts), Milli))
The Mill entry in the table that you pass on to os.time() is being ignored, and the resulting value doesn't provide millisecond precision, so there's no point in including it. To get the format you desire, you need os.date() with an appropriate format, and then you can append the milliseconds to that again, manually.
With that, it looks like this:
$ lua script.lua
2016-01-01 00:00-00.000
2016-01-02 00:00:00.000
With the suggestion from #Nifim it can be simplified further, confirmed by the documentation
When the function is called, the values in these fields do not need to be inside their valid ranges. For instance, if sec is -10, it means 10 seconds before the time specified by the other fields; if hour is 1000, it means 1000 hours after the time specified by the other fields. - Lua 5.4 Reference Manual: os.time
local creation_date = "2016-01-31 00:00:00.000"
local y, m, d, Hr, Min, Sec, Milli = creation_date:match '(%d+)-(%d+)-(%d+) (%d+):(%d+):(%d+).(%d+)'
local dt = y .. '-' .. m .. '-'..d.. ' '..Hr..':'..Min..'-'..Sec..'.'..Milli
print(dt)
local new_ts = os.time { year = y, month = m, day = d + 1, hour = Hr, min = Min, sec = Sec }
print(string.format("%s.%03d", os.date("%Y-%m-%d %H:%M:%S", new_ts), Milli))
Output:
$ lua script.lua
2016-01-31 00:00-00.000
2016-02-01 00:00:00.000

Can I use os.date to convert seconds to time format?

I need a simple function to convert seconds into a time string that humans can read to represent the countdown. I can get the results what I need through very intuitive mathematical calculations, but not elegant enough.
Then I noticed that there is a function named os.date, but I can't get the result I want, what is wrong with my calling, here is my code:
#!usr/bin/env lua
local function getDate1(sec)
local days = math.floor(sec / 86400)
local hours = math.floor((sec % 86400) / 3600)
local minutes = math.floor((sec % 3600) / 60)
local seconds = math.floor(sec % 60)
return days, hours, minutes, seconds
end
local function getDate2(sec)
local date = os.date("*t", sec)
return date["day"], date["hour"], date["min"], date["sec"]
end
local function printDate(d, h, m, s)
print(string.format("%02d %02d:%02d:%02d", d, h, m, s))
end
function main()
printDate(getDate1(999999))
printDate(getDate2(999999))
end
main()
11 13:46:39
12 21:46:39
local function getDate2(sec)
local date = os.date("!*t", sec)
return date["day"]-1, date["hour"], date["min"], date["sec"]
end

Lua - calculating if a time is between two time stamps

Given the following examples:
--Test current start end between
--1 10:00 09:00 12:00 true
--2 01:00 07:34 09:54 false
--3 17:00 16:00 03:00 true
--4 10:00 10:00 15:00 true
--5 10:30 10:00 10:30 true
In Lua, how is it best to create a function that I can call:
BetweenTimes ("10:00", "09:00","12:00")
and in this case (Test 1) return true. The issue I have is will Test case 3.
I can assume that the first time is always before the second time.
I think this might be it:
local function parse_time(str)
local hour, min = str:match("(%d+):(%d+)")
return os.time{hour = hour, min = min, day = 1, month = 1, year = 1970}
end
local function BetweenTimes(between, start, stop)
between = parse_time(between)
start = parse_time(start)
stop = parse_time(stop)
if stop < start then
return (start <= between) or (between <= stop)
else
return (start <= between) and (between <= stop)
end
end
print(BetweenTimes("10:00", "09:00", "12:00")) -- true
print(BetweenTimes("15:00", "09:00", "12:00")) -- false
print(BetweenTimes("15:00", "09:00", "01:00")) -- true
print(BetweenTimes("10:00", "10:00", "11:00")) -- true
print(BetweenTimes("11:00", "10:00", "11:00")) -- true
print(BetweenTimes("19:00", "17:00", "03:30")) -- true
print(BetweenTimes("03:00", "04:00", "05:30")) -- false
print(BetweenTimes("03:00", "02:00", "05:30")) -- true
print(BetweenTimes("01:00", "09:00", "02:30")) -- true
or even just the following should work to remove os.time():
local function BetweenTimes(between, start, stop)
local start = string.gsub(start,":", "")
local between = string.gsub(between,":", "")
local stop = string.gsub(stop,":", "")
if stop < start then
return (start <= between) or (between <= stop)
else
return (start <= between) and (between <= stop)
end
end
Your approach sounds overly complicated. Just parse the hours and minutes out of the string and convert it to a UNIX timestamp. These are regular integers and you can easily compare them using < and >.
local function parse_time(str)
local hour, min = str:match("(%d+):(%d+)")
return os.time{hour = hour, min = min, day = 1, month = 1, year = 1970}
end
local function BetweenTimes(between, start, stop)
between = parse_time(between)
start = parse_time(start)
stop = parse_time(stop)
if stop < start then
stop = stop + 24*60*60 -- add 24 h
end
return (start <= between) and (between <= stop)
end
print(BetweenTimes("10:00", "09:00", "12:00")) -- true
print(BetweenTimes("15:00", "09:00", "12:00")) -- false
print(BetweenTimes("15:00", "09:00", "01:00")) -- true
Why are you even using the date when you only have hours and minutes? Unless you expect to handle any other time units in future, a simple multiplication will suffice.
local function parse_time(str)
local hour, min = str:match("(%d+):(%d+)")
return min * 60 + hour
end
I won't copy BetweenTimes from Henri Menke's answer - it is exactly the same with the only change inside wrapping handling because my parse_time returns minutes, not seconds:
stop = stop + 24*60

This code causes Corona to become unresponsive

When I run this code in Corona on Windows 7 it instantly crashes. It works fine in ZeroBrane. Any ideas why?
--Stopwatch--
local startTime
function start()
startTime = os.time()
--Start the stop watch--
end
function secondsEllapsed()
--Return the number of seconds since the stop watch was started--
return os.time() - startTime
end
start()
while true do
-- Get the time ellapsed and convert it to hours, minutes and seconds
ellapsed = secondsEllapsed()
hours = math.floor(ellapsed / 3600)
minutes = math.floor((ellapsed - (hours * 3600)) / 60)
seconds = math.floor((ellapsed - (hours * 3600) - (minutes * 60)))
-- Print the time ellapsed to the command line
print(hours .. 'h', minutes .. 'm', seconds .. 's')
end
It crashes probably because you run infinity loop.

active record grouping and sum with json data

I'm using Rails 4.1, Ruby 2.1 and the groupdate gem 2.4
I have a records table with these columns:
:value (json) :day (datetime)
current_user.time_zone gives the users' time zone.
value gives a json object like this:
{"430"=>1079.27, "400"=>10.23 }
I'm trying to add up all the value['430'] fields for each week
This gives an error
Record.where(:user_id => current_user.id).group_by_week(:day, time_zone: current_user.time_zone).sum("value#>>'{430}'")
(40.3ms) SELECT SUM(value#>>'{430}') AS sum_value_430, (DATE_TRUNC('week', (day::timestamptz - INTERVAL '6 day' - INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai') + INTERVAL '6 day' + INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai' AS week FROM "eats" WHERE "eats"."user_id" = 53 AND (day IS NOT NULL) GROUP BY (DATE_TRUNC('week', (day::timestamptz - INTERVAL '6 day' - INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai') + INTERVAL '6 day' + INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai'
PG::UndefinedFunction: ERROR: function sum(text) does not exist
LINE 1: SELECT SUM(value#>>'{430}') AS sum_total_nutr...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
: SELECT SUM(value#>>'{430}') AS sum_value_430, (DATE_TRUNC('week', (day::timestamptz - INTERVAL '6 day' - INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai') + INTERVAL '6 day' + INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai' AS week FROM "eats" WHERE "eats"."user_id" = 53 AND (day IS NOT NULL) GROUP BY (DATE_TRUNC('week', (day::timestamptz - INTERVAL '6 day' - INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai') + INTERVAL '6 day' + INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai'
ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR: function sum(text) does not exist
LINE 1: SELECT SUM(value#>>'{430}') AS sum_total_nutr...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
: SELECT SUM(value#>>'{430}') AS sum_value_430, (DATE_TRUNC('week', (day::timestamptz - INTERVAL '6 day' - INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai') + INTERVAL '6 day' + INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai' AS week FROM "eats" WHERE "eats"."user_id" = 53 AND (day IS NOT NULL) GROUP BY (DATE_TRUNC('week', (day::timestamptz - INTERVAL '6 day' - INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai') + INTERVAL '6 day' + INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai'
After trying
Record.where(:user_id => current_user.id).group_by_week(:day, time_zone: current_user.time_zone).sum("CAST(value->>'430'AS integer)")
I got
ActiveRecord::StatementInvalid at /records
PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: "1063.32"
: SELECT SUM(CAST(value->>'430'AS integer)) AS sum_cast_value_430_as_integer, (DATE_TRUNC('week', (day::timestamptz - INTERVAL '6 day' - INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai') + INTERVAL '6 day' + INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai' AS week FROM "records" WHERE "records"."user_id" = 53 AND (day IS NOT NULL) GROUP BY (DATE_TRUNC('week', (day::timestamptz - INTERVAL '6 day' - INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai') + INTERVAL '6 day' + INTERVAL '0' hour) AT TIME ZONE 'Asia/Shanghai'
You perhaps need to cast the JSON typed field to an integer (I've removed the other query methods for clarity).
Record.sum("CAST(value->>'430'AS integer)")
You can try this:
value = Record.where(:user_id => current_user.id).group_by_week(:day, time_zone: current_user.time_zone).pluck(:value)
sum = value.reduce(:+)

Resources