Parse Json Array in KQL - azure

Json text isn't parsing in KQL correctly. I tried using parse_json as well but that didn't work either. I did confirm the extend AllProperties is holding the correct data.
DeviceInfo
| where RegistryDeviceTag == "Standard"
| extend AllProperties = todynamic(LoggedOnUsers)
| project DeviceName, Users = AllProperties["Username"]
Output gives me the correct DeviceName but doesn't give any data in the Username field.

(based on the sample input you provided in the comment)
if the array that is "LoggedOnUsers" includes exactly one entry, you can do this:
print input = '[{"UserName":"TheUserName","DomainName":"TheDomainName","Sid":"TheSID#"}]'
| project UserName = parse_json(input)[0].UserName
otherwise, you can use mv-expand or mv-apply:
print input = '[{"UserName":"TheUserName","DomainName":"TheDomainName","Sid":"TheSID#"}]'
| project parse_json(input)
| mv-apply input on (
project UserName = input.UserName
)

Related

Get a category name from the id in the url using kusto query

I need to get the category name from category id using kusto query.
First i have got the most searched url from the website using the below kusto query and ran it in app insights logs
Requests
| where resultCode==200
| where url contains "bCatID"
| summarize count=sum(itemCount) by url
| sort by count
| take 1
From the above query i got the result like
https://www.test.com/item.aspx?idItem=123456789&bCatID=1282
So for corresponding categoryid=1282 i need to get the category name using kusto
you can use the parse operator.
for example:
print input = 'https://www.test.com/item.aspx?idItem=123456789&bCatID=1282'
| parse input with 'https://www.test.com/item.aspx?idItem=123456789&bCatID='category_id:long
parse_urlquery
print url ="https://www.test.com/item.aspx?idItem=123456789&bCatID=1282"
| extend tolong(parse_urlquery(url)["Query Parameters"]["bCatID"])
url
Query Parameters_bCatID
https://www.test.com/item.aspx?idItem=123456789&bCatID=1282
1282
Fiddle
Feedback to the OP query
Not an answer
KQL is case sensitive. The name of the table in Azure Application Insights is requests (and not Requests).
resultCode is of type string (and not integer/long) and should be compared to "200" (and not 200)
bCatID is a token and therefore can be searched using has or even has_cs, which should be preferred over contains due to performance reasons.
URLs can be used with different parameters. It might make more sense to summarize only by the Host & Path parts + the bCatID query parameter.
count is a reserved word. It can be used as alias only if qualified: ["count"] or ['count'] (or better not used at all).
sort followed by take 1 can be replaced with the more elegant top 1 by ...
requests
| where resultCode == "200"
| project url = parse_url(url), itemCount
| summarize sum(itemCount) by tostring(url.Host), tostring(url.Path), tolong(url["Query Parameters"]["bCatID"])
| top 1 by sum_itemCount

How to get parse_json result property ignore case in Azure Application Insight log query?

The log item looks like below, the currencyamount field has multiple case situation:
{ "AdditionalFields":{
"backendRequestBody":{
"currencyamount":1
} } }
{ "AdditionalFields":{
"backendRequestBody":{
"CurrencyAmount":1
} } }
{ "AdditionalFields":{
"backendRequestBody":{
"currencyAmount":1
} } }
However, the parse_json log query is case sensitive, is there any way to get the currentAmount field case insensitively using azure log query?
The query below only able to get one of the log entry which has lower case currencyamount field.
AzureDiagnostics
| where apiId_s contains "targetId" and AdditionalFields.backendRequestBody has "amount"
| extend amt = (parse_json(tostring(AdditionalFields.backendRequestBody)).currencyamount)
AFAIK, in parse Json we cannot be able to use Incase sensitive Json object. Instead of that you can use following way to achieve.
AzureActivity
| where apiId_s contains "targetId" and AdditionalFields.backendRequestBody has "amount"
| extend backendReqbody = parse_json(AdditionalFields.backendRequestBody)
| extend lowercuramount = parse_json(tostring(parse_json(backendReqbody.currencyamount)))
| extend curamount = parse_json(tostring(parse_json(backendReqbody.CurrencyAmount)))
| extend lowupcuramount = parse_json(tostring(parse_json(backendReqbody.currencyAmount)))
You can use conditions like (iff) Ms -Doc while filtering the data in a result.

Kusto query with filter depending on dashboard parameter

I want to be able to toggle a filter on my query via a parameter in dashboard. How can I turn the "where" operator off?
E.g. the parameter in the dashboard is "_toggle"
let _filter = dynamic(["A", "B"]);
Table
| where id in (_filter) // execute this line only if _toggle == true
| project id
I already tried creating a second list containing all the ids and toggle between the small an the complete list via iff() but this is too resource intensive.
you could try something like this:
let _filter = dynamic(["A", "B"]);
Table
| where _toggle == false or id in (_filter)
| project id

Is it possible to get query results in an App Insights inline function?

I am trying to write an App Insights query that will report back the timespan between two known events, specifically circuit breaker open and close events. The assumption is that these events always occur in pairs, so we need to know the time between the two for every occurrence in a time period.
My first attempt was to use an inline function. Simplified version below.
let timeOpened = (timeClosed:datetime)
{
let result = customEvents
| where name == 'CircuitBreakerStatusChange'
| where customDimensions['State'] == 'Open'
| where timestamp < timeClosed
| order by timestamp desc
| take 1
| project timestamp;
let scalar = toscalar(result);
scalar
};
customEvents
| where timestamp > ago(4h)
| where name == 'CircuitBreakerStatusChange'
| where customDimensions['State'] == 'Closed'
| extend timeOpen = timestamp - timeOpened(timestamp)
There may be a better way to do this. If so your ideas are welcome! But in this particular attempt the only feedback I get from Azure when running this is "Syntax error". However, I don't believe there's a syntax error here because if I just change the return value of the function from scalar to now() it runs successfully. Also I can run the body of the function in isolation successfully. Any idea what's wrong here?
I think you are getting syntax error because query language does not allow possibly recursive constructs. Now() worked because it was statically (not dynamically) retrieved at the query time.
I think you may achieve the desired outcome with serialize and prev() operators:
Table | order by timestamp asc | serialize
| extend previousTime = prev(timestamp,1)
| extend Diff = iff(customDimensions['State'] == 'Closed', timestamp - previousTime, 0)
| where Diff > 0
Note: I haven't tested the example above and it may need some additional thought to make it work (e.g. making sure that the previous record is actually "Opened" before doing previousTime calculation).

How can I get the Scenario Outline Examples' table?

In AfterScenario method, I want to get the rows from table "Examples" in Scenario Outline, to get the values in it, and search that specific values in the database
I know that this can be achieved by using Context.Scenario.Current...
Context.Scenario.Current[key]=value;
...but for some reason I'd like to be able to get it in a simpler way
like this:
ScenarioContext.Current.Examples();
----------- SCENARIO --------------------------------
Scenario Outline: Create a Matter
Given I create matter "< matterName >"
Examples:
| matterName |
| TAXABLE |
----------AFTER SCENARIO -----------------------------------
[AfterScenario()]
public void After()
{
string table = ScenarioContext.Current.Examples();
}
So if you look at the code for ScenarioContext you can see it inherits from SpecflowContext which is itself a Dictionary<string, object>. This means that you can simply use Values to get the collection of values, but I have no idea if they are Examples or not.
The best solution I came up with was to infer the examples by keeping my own static singleton object, then counting how many times the same scenario ran.
MyContext.Current.Counts[ScenarioContext.Current.ScenarioInfo.Title]++;
Of course, this doesn't work very well if you don't run all the tests at the same time or run them in random order. Having a table with the examples themselves would be more ideal, but if you combine my technique along with using ScenarioStepContext you could extract the parameters of the Examples table out of the rendered step definition text itself.
Feature
Scenario Outline: The system shall do something!
Given some input <input>
When something happens
Then something should have happened
Examples:
| input |
| 1 |
| 2 |
| 3 |
SpecFlow Hook
[BeforeStep]
public void BeforeStep()
{
var text = ScenarioStepContext.Current.StepInfo.Text;
var stepType = ScenarioStepContext.Current.StepInfo.StepDefinitionType;
if (text.StartsWith("some input ") && stepType == StepDefinitionType.Given)
{
var input = text.Split(' ').Last();
}
}

Resources