Kusto interface

Warning, this blog post is going way into the weeds of Kusto and Log Analytics.

Let’s say for a minute that you wanted to call http_request_post to post some data to an API. The query below is a two part query. The first part identifies any anomalies in usage data (a good query to check out).

let min_t = toscalar(now(-1d));

let max_t = toscalar(now());

let content = Usage

| make-series statuschanges=count() default=0 on todatetime(TimeGenerated) from min_t to max_t step 1h by Type

| extend (flag_adx, score_adx, baseline_adx)=series_decompose_anomalies(statuschanges, 1.5, -1, ‘linefit’)

| project timestamp=todatetime(TimeGenerated[-1]), anomaly_score=score_adx[-1], flag=flag_adx[-1];

 

The second half of this would (in theory) write the content gathered in the first section via a http_request_post. However, it does not work.

 

Please note: I am using http://www.bing.com just to show a URL, not to actually perform the http_request_post to send the data there.

 

let uri = “http://www.bing.com”;

let headers = dynamic({});

let options = dynamic({});

let content_dummy = “some content here”;

let content2 = tostring(toscalar(content));

evaluate http_request_post(uri, headers, options, content2);

 

The query appears to run but actually it is not working. The issue shown below is identified by the red underline shown below on “content2”.

Kusto with content2 underlined

Kusto with content2 underlined

If you hover over the red underlined section, you see the real hint as to what’s wrong. “Error: The expression must be a constant. content2: string”

Kusto error expression must be constant

Kusto error expression must be constant

What this is telling us is that the http_request_post cannot be used unless the third parameter is a constant. We can verify this by trying the hardcoded version of this query using the “content_dummy”.  Notice the lack of the red underline shown below:

content_dummy with no error

content_dummy with no error

This puts us in a less than optimal situation as http_request_post doesn’t let us write data that isn’t hardcoded. The work-around (thank you to Matt Dowst) is to wrap the http_request_post into a function as shown below.

 

let min_t = toscalar(now(-1d));

let max_t = toscalar(now());

let content = Usage

| make-series statuschanges=count() default=0 on todatetime(TimeGenerated) from min_t to max_t step 1h by Type

| extend (flag_adx, score_adx, baseline_adx)=series_decompose_anomalies(statuschanges, 1.5, -1, ‘linefit’)

| project timestamp=todatetime(TimeGenerated[-1]), anomaly_score=score_adx[-1], flag=flag_adx[-1];

let uri = “http://www.bing.com”;

let headers = dynamic({});

let options = dynamic({});

let content_dummy = “some content here”;

let content2 = tostring(toscalar(content));

let request = (uri:string, headers:dynamic, options:dynamic, json:string){

evaluate http_request_post(uri, headers, options, json);

};

request(uri, headers, options, content2)

In the bolded section above, we have created a function that does the same thing we were trying to do but it runs the http_request_post in a function. If we re-hover over content2 we can now see it is no longer underlined.

No error on content2

No error on content2

Summary: Are you running into “Error: The expression must be a constant” in Kusto? Try wrapping whatever you were trying to run in a function and then calling that function. I owe a huge shout-out to Matt Dowst who provided the way to make this work. Check out his blog posts, recent book release, and updates on Twitter on PowerShell!!