To_long function returning "0"

1. Describe your incident:

I am trying to use a pipeline to parse out the UNIX timestamp from a Meraki MX firewall flow log. I almost have it, but the to_long function is converting the value to “0”.

2. Describe your environment:

  • OS Information: Ubuntu 22.04

  • Package Version: 5.0.7-1

  • Service logs, configurations, and environment variables:
    PIPELINE RULE:
    rule “UNIX timestamp”
    when
    has_field(“message”) && (contains(to_string($message.message),“flows”)||contains(to_string($message.message),“firewall”))
    then
    // UNIX epoch
    let epoch_time = grok(pattern:“%{UNIXTIME}”,value:to_string($message.message)).NUMBER;
    debug(epoch_time);
    let ts_seconds_lng = to_long(epoch_time);
    debug(ts_seconds_lng);
    let new_ts = parse_unix_milliseconds(ts_seconds_lng,“America/Chicago”);
    set_field(“timestamp”, new_ts);
    end

DEBUG OUTPUT:
2023-05-17T15:59:51.554-05:00 INFO [Function] PIPELINE DEBUG: 1684341977.212982350
2023-05-17T15:59:51.555-05:00 INFO [Function] PIPELINE DEBUG: 0

3. What steps have you already taken to try and solve the problem?
I have tried different ways to extract the time stamp as well as converting to double then long, but that did not work either.

4. How can the community help?
Explain why the return value is 0 when converting to long.

I ended up poking around some more and was able to parse out the epoch timestamp without the decimals and get it to work with this code:

grok pattern:
\<[0-9][0-9][0-9]\>[0-9]\s%{DATA:ts}\.%{DATA}

rule “UNIX timestamp”
when
has_field(“message”) && (contains(to_string($message.message),“flows”)||contains(to_string($message.message),“firewall”))
then
// UNIX epoch
let epoch_time = grok(pattern:“%{UNIXTIME}”,value:to_string($message.message)).ts;
let ts_seconds_lng = to_long(epoch_time) * 1000;
let new_ts = parse_unix_milliseconds(ts_seconds_lng,“America/Chicago”);
set_field(“timestamp”, new_ts);
end

I would still like to know why the value is changing to 0 when using the to_long function, if anyone knows.

I just tested and the behavior of to_long is that it only changes the data type but doesn’t do any conversions.

Testing with

rule "TEST - to_long"
when
    true
then
    let i = to_string($message.message);
    set_field("this_is_to_long", to_long(i));
end

image

image

image

You’ll need to properly format the value to just an whole integer before using to_long.

Hope that helps!

2 Likes

Drew, I really appreciate your assistance. I did not realize that long types could not have decimals, which seems to be the issue. I was able to manually extract the data to get what I wanted using the code below:

Pipeline Rule:
rule “Meraki UNIX TS Test”
when
has_field(“message”) && (contains(to_string($message.message),“flows”)||contains(to_string($message.message),“firewall”))
then
let epoch_time_ts = to_string(grok(pattern:“%{MERAKI_MX_UNIXTIME_TEST}”,value:to_string($message.message)).ts);
let epoch_time_ms = to_string(grok(pattern:“%{MERAKI_MX_UNIXTIME_TEST}”,value:to_string($message.message)).ms);
let epoch_time_concat = concat(epoch_time_ts,substring(epoch_time_ms,0,3));
let ts_seconds = to_long(epoch_time_concat);
let new_ts = parse_unix_milliseconds(ts_seconds,“America/Chicago”);
set_field(“timestamp”, new_ts);
end

GROK Pattern:
\<[0-9][0-9][0-9]\>[0-9]\s%{WORD:ts}\.%{WORD:ms}

I am sure there is a much better/more efficient way to do this, but this works.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.