azuredatetimeazure-data-explorerkqldate-conversion

KQL Azure Log Analytics can't parse datetime from regex expression


Given a table with columns "RawData" and "_ResourceId", which is the Azure ARM ID, I want to parse a string from a server log file like:

"09:08:52,198 INFO [web.org.perfmon4j.extras.jbossweb7.P....."

and pull parts of the string into my custom table for later analysis.

The Kusto KQL query in the Azure Log Analytics editor:

suggest_CL
| project dt = todatetime(extract("^([\\:0-9]+)\\,([0-9]+)", 1, 
       "09:08:52,198 INFO [web.org.perfmon4j.extras.jbossweb7.P")),
dtstr = extract("^([\\:0-9]+)\\,([0-9]+)", 1, 
        "09:08:52,198 INFO [web.org.perfmon4j.extras.jbossweb7.P"),
statictimestr = "09:09:52",
statictime = todatetime("09:09:52"),
 _ResourceId, RawData

where suggest_CL is the Custom Table

The dtstr column shows that the regex works and returns the correct time value.

I include some test strings:

statictimestr = "09:09:52",

This is a simple time only string. The doc says it will use today's date if the date is not included.

statictime = todatetime("09:09:52"),

This is the above string converted to datetime

The output is

dt [UTC] dtstr statictimestr statictime [UTC]
09:08:52 09:09:52 2023-06-15T09:09:52Z

and the dt column is empty, implying that the todatetime(...) expression evaluated to null. The statictime column is noted as [UTC], so the parsing of the time-only expression was successful for the string literal. Outputting isnull(todatetime(...)) shows true.

The output of the extract(regex) expression is NOT parsed correctly.

Another SO question answers by saying the format is incorrect. There seems to be more problem here than that, like a bug handling function expressions as an argument to todatetime(). That possibility was expressed in the other question.

Any ideas?


Solution

  • todatetime() has different implementations for constant values and for calculated values - not the same set of formats is supported in both. The official set of supported formats (for both) is documented here.

    This is why for an unsupported format, it may work for you when you provide a constant value, but may not otherwise.

    For unsuppported formats, one thing you could try is to parse the separate date parts using the parse operator, then use the make_datetime() function to create a datetime value out of them.

    For example:

    print input = "09:08:52,198 INFO [web.org.perfmon4j.extras.jbossweb7.P....."
    | parse input with hours:int ":" minutes:int ":" seconds:double "," *
    | extend dt = make_datetime(datetime_part("Year", now()), datetime_part("Month", now()), datetime_part("Day", now()), hours, minutes, seconds)