How to render a cumulative histogram based on ALA - azure

I'd like to render a cumulative histogram of the duration of various workflows.
This is the query I use to compute the duration of various workflows, and the timeElapsedInMs result can be used to do things like compute percentiles (as shown). The durations span a fairly sizable range, from under a second to several minutes. What I would like to do is render a cumulative histogram of the data. My best guess at this point is that the accumulate property of one of the render types might work, but I can't seem to wrap my head around how to do that.
let start = fluentbit_CL
| where log_s has_cs "<starting event>"
| project trackingId = trackingId_g, timestampStart= _timestamp_t;
let finish = fluentbit_CL
| where log_s contains "<ending event>"
| project trackingId = trackingId_g, timestampFinish = _timestamp_t;
start
| join finish on trackingId
| extend timeElapsedInMs = datetime_diff('millisecond', todatetime(timestampFinish ), todatetime(timestampStart))
| summarize min=min(timeElapsedInMs), avg=avg(timeElapsedInMs), percentiles_array(timeElapsedInMs, 50, 95), max=max(timeElapsedInMs)
I'd also be happy with another sensible way to render the data to get a look at the percentiles, but my current best approaches don't get a very clear impression of the data.

There is no need to write one query for starting event and one for ending event and then join them. This can be done with a single query, using summarize.
Histogram can be easily created using bin (doc)
Accumulated histogram can be easily rendered using with (accumulate=True) (doc)
// This part of the code is just for data sample generation and is not part of the solution
let start = materialize (range trackingId_g from 1 to 100 step 1 | extend _timestamp_t = ago(24h * rand()), log_s = "<starting event>");
let finish = materialize (start | extend _timestamp_t = _timestamp_t + 5m * rand(), log_s = "<ending event>");
let fluentbit_CL = (union start, finish);
// The solution starts from here
fluentbit_CL
| summarize duration = anyif(_timestamp_t, log_s has_cs "<ending event>") - anyif(_timestamp_t, log_s has_cs "<starting event>")
by trackingId_g
| summarize count() by bin(duration, 10s)
| order by duration asc
| render timechart with (accumulate=True)
Fiddle

Related

How do I create a variable and set it equal to the count of a specific customEvent?

I have telemetry in my code that creates two custom events(longNameHere_event_success/longNameHere_event_error). I have a small AI Analytics query that looks for my events, gets the count of each, and renders a pie chart for a percentage metric.
As my event names are rather long, I'd like to create a variable for each to make the pie chart more legible.
customEvents
| where name contains "event"
|summarize count() by name
| render piechart
Current result is a pie chart with percentages for "longNameHere_event_success" and "longNameHere_event_error"
Desired result would be renaming "longNameHere_event_success" to "Success" and "longNameHere_event_error" to "Failure".
You can rename the column value as follows (I used an inline function for readability, but you can replace the function call with the case statement). Is this what you were looking for?
let rename = (original:string)
{
case(original == "longNameHere_event_success", "success",
original == "longNameHere_event_error", "error",
"unknown")
};
let customEvents = datatable(name:string)
[
"longNameHere_event_success",
"longNameHere_event_success",
"longNameHere_event_error"
];
customEvents
| where name contains "event"
| summarize count() by name
| project name = rename(name), count_
| render piechart

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 to write a query for reordering elements

I'm working on a code that will have a list of items in a specific order and I'd like to reorder them at will. The setup isn't really that important, but to summarize it, it's a node server with MSSQL database.
For the sake of the demonstration lets say we're discussing forum categories that show in a specific order.
Id | OrderNumber | Name
------------------------
1 | 1 | Rules
2 | 3 | Off-topic
5 | 2 | General
8 | 4 | Global
I've already handled the front end that will allow me to reorder them as I like and the problem is what should happen when I press the save button on the database.
Ideally I'd like to send a JavaScript object containing item IDs in the right order to the API endpoint on the server that will execute a stored procedure. Something like:
Data = {
IDs:"5,2,8,1"
}
Is there a way that I can program a that stored procedure that it's only parameter is the list of Ids but that it can go through that list and do something I can only describe as the following pseudo code:
var Order = 1;
foreach ID in Data.IDs
UPDATE Categories SET OrderNum = Order WHERE Id = ID
Order = Order + 1
My biggest problem is that I'm not very experienced with advanced SQL commands, but that's the only part I need help with, I handled everything else already. Thank you for your help.
Example
Declare #IDs varchar(max) = '5,2,8,1'
Update A
set OrderNumber=B.RetSeq
From YourTable A
Join (
Select RetSeq = row_number() over (order by (select null))
,RetVal = B.n.value('(./text())[1]', 'int')
From ( values (cast('<x>' + replace(#IDs,',','</x><x>')+'</x>' as xml) )) A(xmldata)
Cross Apply xmldata.nodes('x') B(n)
) B on A.ID=B.RetVal
Updated Table
Id OrderNumber Name
1 4 Rules
2 2 Off-topic
5 1 General
8 3 Global

How to rename axes in Azure Log Analytics Timechart Query

I have the following query that I want to change the name of the axes. I tried the optional attributes of render, but it doesn't seem to recognize any of them. What am I missing?
AzureStorage_CL
| where ResourceGroup == "rg-sdl-adw"
| where PercentClientOtherError_d > 0
| summarize AV = any(PercentClientOtherError_d) by bin(TimeGenerated, 30m) |
render timechart with (ytitle = "Y new title")
Current results:
The "ytitle" isn't supported in Log Analytics since it uses a different rendering engine.
An issue has been submitted to track it.
Did you get your answer to this?
The axis aren't easy to edit, and the format you are constrained by are a bit restrictive, but essentially you need to rename the axes by taking your query:
AzureStorage_CL
| where ResourceGroup == "rg-sdl-adw"
| where PercentClientOtherError_d > 0
| summarize AV = any(PercentClientOtherError_d) by bin(TimeGenerated, 30m)
| render timechart
Now add in an extra line to rename the axis | project-rename NewAxisTitle = AV where the NewAxisTitle is your desired name, and the AV is your old name:
AzureStorage_CL
| where ResourceGroup == "rg-sdl-adw"
| where PercentClientOtherError_d > 0
| summarize AV = any(PercentClientOtherError_d) by bin(TimeGenerated, 30m)
| project-rename NewAxisTitle = AV
| render timechart
Be aware that any time you refer to the axis after the point you rename it you need to refer to it as it's new name.
Hope that all makes sense.
There are now some keywords available to achieve this (at least in the log analytics workspace) as here from GitHub.
For example, you maybe able to say:
| render timechart with (title = "Your Title", xtitle= "Your X Axis Title", yaxis = "Your X Axis title")
Please mark this as the answer if you that agree this feature is now supported. Thank you

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