如何在不考虑依赖项持续时间的情况下评估 Application Insights 请求 "own" 持续时间?
How to evaluate Application Insights requests "own" duration, without considering duration of dependencies?
我正在尝试生成一个 Kusto 查询来测量请求的“自己”持续时间(减去依赖项的持续时间)。但是,我真的不知道如何通过纯 Kusto 查询来解决这个问题。
为了更好地理解预期结果,下面是一个示例案例:
高级视图(其中 R 是请求,Dx 是依赖项)
R =============================== (31ms)
D1 ******* (7ms)
D2 ******** (8ms)
D3 ****** (6ms)
D4 ** (2ms)
D5 **** (4ms)
Proj ==*************======******====
D1
在 2 毫秒内重叠 D2
D5
和 D4
不应被视为与其他依赖项完全重叠
Proj
是 潜在 中间步骤的投影,其中仅显示有意义的依赖项片段
给定以下测试平台数据集
let reqs = datatable (timestamp: datetime, id:string, duration: real)
[
datetime("2020-12-15T08:00:00.000Z"), "r1", 31 // R
];
let deps = datatable (timestamp: datetime, operation_ParentId:string, duration: real)
[
datetime("2020-12-15T08:00:00.002Z"), "r1", 7, // D1
datetime("2020-12-15T08:00:00.007Z"), "r1", 8, // D2
datetime("2020-12-15T08:00:00.021Z"), "r1", 6, // D3
datetime("2020-12-15T08:00:00.023Z"), "r1", 2, // D4
datetime("2020-12-15T08:00:00.006Z"), "r1", 4, // D5
];
在这种特殊情况下,连接两个数据表的 Kusto 查询应该能够检索 12
(请求持续时间,删除所有依赖项),即
Expected total duration = 31 - (7 + 8 - 2) - (6) = 12
如果能帮助推动这一进程,我们将不胜感激 <3
看看下面的查询是否能满足您的要求:
let reqs = datatable (timestamp: datetime, id:string, duration: real, key1:string)
[
datetime("2020-12-15T08:00:00.000Z"), "r1", 31 , "k1" // R
];
let deps = datatable (timestamp: datetime, operation_ParentId:string, duration: real,name:string)
[
datetime("2020-12-15T08:00:00.002Z"), "r1", 7, "D1",
datetime("2020-12-15T08:00:00.007Z"), "r1", 8, "D2",
datetime("2020-12-15T08:00:00.021Z"), "r1", 6, "D3",
datetime("2020-12-15T08:00:00.023Z"), "r1", 2, "D4",
datetime("2020-12-15T08:00:00.006Z"), "r1", 4, "D5"
];
let d2 = deps
| where name !in ("D4","D5")
| summarize a=sum(duration)-2
| extend key1="k1";
reqs
| join d2 on key1
| extend result = duration - a
| project result
测试结果:
我使用 row_window_session()
. This is a Window function. You can read more about it at Window functions overview.
成功解决了这个问题
解决方法是:
let reqs = datatable (timestamp: datetime, operation_ParentId:string, duration: real)
[
datetime("2020-12-15T08:00:00.000Z"), "r1", 31 // R
];
let deps = datatable (timestamp: datetime, operation_ParentId:string, duration: real)
[
datetime("2020-12-15T08:00:00.002Z"), "r1", 7, // D1
datetime("2020-12-15T08:00:00.007Z"), "r1", 8, // D2
datetime("2020-12-15T08:00:00.021Z"), "r1", 6, // D3
datetime("2020-12-15T08:00:00.006Z"), "r1", 4, // D5
datetime("2020-12-15T08:00:00.023Z"), "r1", 2, // D4
];
deps
| extend endTime = timestamp + totimespan(duration * 10000)
| sort by timestamp asc
| serialize | extend SessionStarted = row_window_session(timestamp, 1h, 1h, timestamp > prev(endTime))
| summarize max(endTime) by operation_ParentId, SessionStarted
| extend diff = max_endTime - SessionStarted
| summarize todouble(sum(diff)) by operation_ParentId
| join reqs on operation_ParentId
| extend diff = duration - sum_diff / 10000
| project diff
这里的思路是按照打开时间对条目进行排序,只要下一个上一个结束时间晚于当前开始时间,我们就不会打开新的会话。让我们解释一下这个查询的每一行,看看这是如何完成的:
- 根据持续时间计算
endTime
。为了规范化数据,我将持续时间乘以 10000:
| extend endTime = timestamp + totimespan(duration * 10000)
- 按开始时间排序:
| sort by timestamp asc
- 这是本解法的关键。它是在
timestamp
列上计算的。接下来的两个参数是何时开始新桶的限制。由于我们不想根据过去的时间来密封桶,因此我提供了 1 小时,该时间不会影响此输入。第四个参数帮助我们创建一个基于数据的新会话。只要有更多的行会导致 timestamp > prev(endTime)
,它们就会有相同的开始时间。
| serialize | extend SessionStarted = row_window_session(timestamp, 1h, 1h, timestamp > prev(endTime))
- 现在每个会话开始时我们有多个行。所以我们只想保留每个会话的最新时间。我们还保留
operation_ParentId
以便稍后加入该键:
| summarize max(endTime) by operation_ParentId, SessionStarted
- 计算每个会话的时间:
| extend diff = max_endTime - SessionStarted
- 总结所有会话时间:
| summarize todouble(sum(diff)) by operation_ParentId
- 加入
req
以获得总开始时间:
| join reqs on operation_ParentId
- 计算总时间和会话时间之间的差异。非规范化数据:
| extend diff = duration - sum_diff / 10000
- 投影最终结果:
| project diff
您可以在 Kusto Samples open database 找到此查询 运行。
话虽如此,请注意这是线性运算。这意味着如果有 2 个后续段,它们应该在同一段下,但它们不相交,它将失败。例如,将以下内容添加到 deps
中:
datetime("2020-12-15T08:00:00.026Z"), "r1", 1, // D6
这不应该在计算中添加任何东西,导致它行为不端。这是因为d4
是前一个点,它与d6
没有任何联系,虽然d3
涵盖了两者。
要解决这个问题,您需要重复步骤 3-5 的相同逻辑。不幸的是,Kusto 没有递归,因此您无法为任何类型的输入解决此问题。但是假设没有真正深度的案例打破这个逻辑,我认为这已经足够了。
我正在尝试生成一个 Kusto 查询来测量请求的“自己”持续时间(减去依赖项的持续时间)。但是,我真的不知道如何通过纯 Kusto 查询来解决这个问题。
为了更好地理解预期结果,下面是一个示例案例:
高级视图(其中 R 是请求,Dx 是依赖项)
R =============================== (31ms)
D1 ******* (7ms)
D2 ******** (8ms)
D3 ****** (6ms)
D4 ** (2ms)
D5 **** (4ms)
Proj ==*************======******====
D1
在 2 毫秒内重叠D2
D5
和D4
不应被视为与其他依赖项完全重叠Proj
是 潜在 中间步骤的投影,其中仅显示有意义的依赖项片段
给定以下测试平台数据集
let reqs = datatable (timestamp: datetime, id:string, duration: real)
[
datetime("2020-12-15T08:00:00.000Z"), "r1", 31 // R
];
let deps = datatable (timestamp: datetime, operation_ParentId:string, duration: real)
[
datetime("2020-12-15T08:00:00.002Z"), "r1", 7, // D1
datetime("2020-12-15T08:00:00.007Z"), "r1", 8, // D2
datetime("2020-12-15T08:00:00.021Z"), "r1", 6, // D3
datetime("2020-12-15T08:00:00.023Z"), "r1", 2, // D4
datetime("2020-12-15T08:00:00.006Z"), "r1", 4, // D5
];
在这种特殊情况下,连接两个数据表的 Kusto 查询应该能够检索 12
(请求持续时间,删除所有依赖项),即
Expected total duration = 31 - (7 + 8 - 2) - (6) = 12
如果能帮助推动这一进程,我们将不胜感激 <3
看看下面的查询是否能满足您的要求:
let reqs = datatable (timestamp: datetime, id:string, duration: real, key1:string)
[
datetime("2020-12-15T08:00:00.000Z"), "r1", 31 , "k1" // R
];
let deps = datatable (timestamp: datetime, operation_ParentId:string, duration: real,name:string)
[
datetime("2020-12-15T08:00:00.002Z"), "r1", 7, "D1",
datetime("2020-12-15T08:00:00.007Z"), "r1", 8, "D2",
datetime("2020-12-15T08:00:00.021Z"), "r1", 6, "D3",
datetime("2020-12-15T08:00:00.023Z"), "r1", 2, "D4",
datetime("2020-12-15T08:00:00.006Z"), "r1", 4, "D5"
];
let d2 = deps
| where name !in ("D4","D5")
| summarize a=sum(duration)-2
| extend key1="k1";
reqs
| join d2 on key1
| extend result = duration - a
| project result
测试结果:
我使用 row_window_session()
. This is a Window function. You can read more about it at Window functions overview.
解决方法是:
let reqs = datatable (timestamp: datetime, operation_ParentId:string, duration: real)
[
datetime("2020-12-15T08:00:00.000Z"), "r1", 31 // R
];
let deps = datatable (timestamp: datetime, operation_ParentId:string, duration: real)
[
datetime("2020-12-15T08:00:00.002Z"), "r1", 7, // D1
datetime("2020-12-15T08:00:00.007Z"), "r1", 8, // D2
datetime("2020-12-15T08:00:00.021Z"), "r1", 6, // D3
datetime("2020-12-15T08:00:00.006Z"), "r1", 4, // D5
datetime("2020-12-15T08:00:00.023Z"), "r1", 2, // D4
];
deps
| extend endTime = timestamp + totimespan(duration * 10000)
| sort by timestamp asc
| serialize | extend SessionStarted = row_window_session(timestamp, 1h, 1h, timestamp > prev(endTime))
| summarize max(endTime) by operation_ParentId, SessionStarted
| extend diff = max_endTime - SessionStarted
| summarize todouble(sum(diff)) by operation_ParentId
| join reqs on operation_ParentId
| extend diff = duration - sum_diff / 10000
| project diff
这里的思路是按照打开时间对条目进行排序,只要下一个上一个结束时间晚于当前开始时间,我们就不会打开新的会话。让我们解释一下这个查询的每一行,看看这是如何完成的:
- 根据持续时间计算
endTime
。为了规范化数据,我将持续时间乘以 10000:| extend endTime = timestamp + totimespan(duration * 10000)
- 按开始时间排序:
| sort by timestamp asc
- 这是本解法的关键。它是在
timestamp
列上计算的。接下来的两个参数是何时开始新桶的限制。由于我们不想根据过去的时间来密封桶,因此我提供了 1 小时,该时间不会影响此输入。第四个参数帮助我们创建一个基于数据的新会话。只要有更多的行会导致timestamp > prev(endTime)
,它们就会有相同的开始时间。| serialize | extend SessionStarted = row_window_session(timestamp, 1h, 1h, timestamp > prev(endTime))
- 现在每个会话开始时我们有多个行。所以我们只想保留每个会话的最新时间。我们还保留
operation_ParentId
以便稍后加入该键:| summarize max(endTime) by operation_ParentId, SessionStarted
- 计算每个会话的时间:
| extend diff = max_endTime - SessionStarted
- 总结所有会话时间:
| summarize todouble(sum(diff)) by operation_ParentId
- 加入
req
以获得总开始时间:| join reqs on operation_ParentId
- 计算总时间和会话时间之间的差异。非规范化数据:
| extend diff = duration - sum_diff / 10000
- 投影最终结果:
| project diff
您可以在 Kusto Samples open database 找到此查询 运行。
话虽如此,请注意这是线性运算。这意味着如果有 2 个后续段,它们应该在同一段下,但它们不相交,它将失败。例如,将以下内容添加到 deps
中:
datetime("2020-12-15T08:00:00.026Z"), "r1", 1, // D6
这不应该在计算中添加任何东西,导致它行为不端。这是因为d4
是前一个点,它与d6
没有任何联系,虽然d3
涵盖了两者。
要解决这个问题,您需要重复步骤 3-5 的相同逻辑。不幸的是,Kusto 没有递归,因此您无法为任何类型的输入解决此问题。但是假设没有真正深度的案例打破这个逻辑,我认为这已经足够了。