scan 연산자
적용 대상: ✅Microsoft Fabric✅Azure Data Explorer✅Azure Monitor✅Microsoft Sentinel
조건자를 기준으로 데이터를 검사하고, 일치시키고, 시퀀스를 빌드합니다.
일치 레코드는 연산자의 단계에 정의된 조건자에 따라 결정됩니다. 조건자는 이전 단계에서 생성된 상태에 따라 달라질 수 있습니다. 일치하는 레코드의 출력은 연산자의 단계에 정의된 입력 레코드 및 할당에 의해 결정됩니다.
구문
T | scan
[ with_match_id
=
MatchIdColumnName ] [ declare
(
ColumnDeclarations )
] with
(
StepDefinitions )
ColumnDeclarations 구문
ColumnName :
ColumnType[=
DefaultValue ] [,
... ]
StepDefinition 구문
step
StepName [ output
| none
all
last
= | ] :
Condition [ =>
Column =
Assignment [,
... ] ];
구문 규칙에 대해 자세히 알아봅니다.
매개 변수
이름 | Type | 필수 | 설명 |
---|---|---|---|
T | string |
✔️ | 입력 테이블 형식 원본입니다. |
MatchIdColumnName | string |
검색 실행의 일부로 출력에 추가되는 형식 long 열의 이름입니다. 레코드에 대한 일치 항목의 0부터 시작하는 인덱스입니다. |
|
ColumnDeclarations | string |
T의 스키마에 대한 확장을 선언합니다. 이러한 열은 단계에서 값이 할당됩니다. 할당 되지 않은 경우 DefaultValue 가 반환됩니다. 달리 지정 하지 않는 한 DefaultValue 는 .입니다 null . |
|
StepName | string |
✔️ | 조건 및 할당에 대한 검사 상태의 값을 참조하는 데 사용됩니다. 단계 이름은 고유해야 합니다. |
Condition | string |
✔️ | 입력에서 단계와 일치하는 레코드를 true 계산하거나 false 정의하는 식입니다. 레코드는 true 조건이 단계의 상태 또는 이전 단계의 상태인 경우 단계와 일치합니다. |
양도 | string |
레코드가 단계와 일치할 때 해당 열에 할당되는 스칼라 식입니다. | |
output |
string |
반복되는 일치 항목에 대한 단계의 출력 논리를 제어합니다. all 는 단계와 일치하는 모든 레코드를 출력하고, last 일련의 반복 일치 항목에서 마지막 레코드만 출력하며, 단계와 none 일치하는 레코드를 출력하지 않습니다. 기본값은 all 입니다. |
반품
입력에서 단계로 레코드의 각 일치 항목에 대한 레코드입니다. 출력의 스키마는 절의 열로 확장된 원본의 스키마입니다 declare
.
검사 논리
scan
는 각 단계의 현재 상태를 고려하면서 각 단계의 조건과 각 레코드를 비교하여 레코드별로 직렬화된 입력 데이터를 통해 이동합니다.
State(상태)
연산자의 scan
기본 상태는 각각 step
에 대한 행이 있는 테이블로 간주할 수 있습니다. 각 단계에서는 열의 최신 값과 이전 단계 및 현재 단계의 선언된 변수를 사용하여 자체 상태를 유지합니다. 관련된 경우 진행 중인 시퀀스에 대한 일치 ID도 보유합니다.
검사 연산자에 s_1, s_2, ...라는 n 단계가 있는 경우 s_n 단계 s_k s_1, s_2, ..., s_k 해당하는 상태에 k 레코드가 있습니다. StepName입니다.ColumnName 형식은 상태의 값을 참조하는 데 사용됩니다. 예를 들어 s_k s_2.col1
상태의 단계 s_2 속하는 열을 col1
참조합니다. 자세한 예제는 검사 논리 연습을 참조 하세요.
상태는 빈 상태로 시작되고 검색된 입력 레코드가 단계와 일치할 때마다 업데이트됩니다. 현재 단계의 상태가 비어 있지 않으면 이 단계를 활성 시퀀스라고 합니다.
일치하는 논리
각 입력 레코드는 마지막 단계에서 첫 번째 단계까지 모든 단계에 대해 역순으로 평가됩니다. 레코드 r이 일부 단계 s_k 대해 평가되면 다음 논리가 적용됩니다.
확인 1: 이전 단계의 상태(s_k-1)가 없음이고 r이 s_k 조건을 충족하면 일치가 발생합니다. 일치는 다음 작업으로 이어집니다.
- s_k 상태가 지워집니다.
- s_k-1의 상태는 s_k 상태가 되도록 승격됩니다.
- s_k 할당은 계산되고 r을 확장합니다.
- 확장 r은 출력 및 s_k 상태에 추가됩니다.
참고 항목
Check 1이 일치하면 Check 2가 무시되고 r이 s_k-1에 대해 평가됩니다.
확인 2: s_k 상태에 활성 시퀀스 또는 s_k 첫 번째 단계이고 r이 s_k 조건을 충족하는 경우 일치가 발생합니다. 일치는 다음 작업으로 이어집니다.
- s_k 할당은 계산되고 r을 확장합니다.
- s_k 상태의 s_k 나타내는 값은 확장된 r의 값으로 대체됩니다.
- s_k 정의된 경우 확장 r이 출력에 추가
output=all
됩니다. - s_k 첫 번째 단계이면 새 시퀀스가 시작되고 일치 ID가 증가합니다
1
. 이는 사용되는 경우에만with_match_id
출력에 영향을 줍니다.
s_k 대한 검사가 완료되면 r은 s_k-1에 대해 평가됩니다.
이 논리의 자세한 예제는 검사 논리 연습을 참조 하세요.
예제
누적 합계
입력 열의 누적 합계를 계산합니다. 이 예제의 결과는 row_cumsum()를 사용하는 것과 같습니다.
range x from 1 to 5 step 1
| scan declare (cumulative_x:long=0) with
(
step s1: true => cumulative_x = x + s1.cumulative_x;
)
출력
x | cumulative_x |
---|---|
1 | 6 |
2 | 3 |
3 | 6 |
4 | 10 |
5 | 15 |
다시 설정 조건이 있는 여러 열의 누적 합계
두 입력 열의 누적 합계를 계산하고 누적 합계가 10개 이상에 도달할 때마다 합계 값을 현재 레코드 값으로 다시 설정합니다.
range x from 1 to 5 step 1
| extend y = 2 * x
| scan declare (cumulative_x:long=0, cumulative_y:long=0) with
(
step s1: true => cumulative_x = iff(s1.cumulative_x >= 10, x, x + s1.cumulative_x),
cumulative_y = iff(s1.cumulative_y >= 10, y, y + s1.cumulative_y);
)
출력
x | y | cumulative_x | cumulative_y |
---|---|---|---|
1 | 2 | 1 | 2 |
2 | 4 | 3 | 6 |
3 | 6 | 6 | 12 |
4 | 8 | 10 | 8 |
5 | 10 | 5 | 18 |
열 앞으로 채우기
문자열 열을 앞으로 입력합니다. 각 빈 값에는 마지막으로 볼 수 없는 값이 할당됩니다.
let Events = datatable (Ts: timespan, Event: string) [
0m, "A",
1m, "",
2m, "B",
3m, "",
4m, "",
6m, "C",
8m, "",
11m, "D",
12m, ""
]
;
Events
| sort by Ts asc
| scan declare (Event_filled: string="") with
(
step s1: true => Event_filled = iff(isempty(Event), s1.Event_filled, Event);
)
출력
Ts(Ts) | 이벤트 | Event_filled |
---|---|---|
00:00:00 | A | A |
00:01:00 | A | |
00:02:00 | B | B |
00:03:00 | B | |
00:04:00 | B | |
00:06:00 | C | C |
00:08:00 | C | |
00:11:00 | D | D |
00:12:00 | D |
세션 태그 지정
입력을 세션으로 나눕니다. 세션은 세션의 첫 번째 이벤트 이후 30분 후에 종료되며 그 후에 새 세션이 시작됩니다. 검색의 with_match_id
각 고유 일치(세션)에 대해 고유한 값을 할당하는 플래그를 사용합니다. 또한 이 예제 inSession
에서 두 단계의 특별한 사용은 true
조건으로 사용되므로 현재 일치 값에서 30m 이상 발생하는 레코드를 캡처하는 동안 endSession
입력의 sessionStart
모든 레코드를 캡처하고 출력합니다. 이 endSession
단계는 output=none
출력 레코드를 생성하지 않음을 의미합니다. 이 endSession
단계는 현재 일치 항목의 상태를 현재 레코드부터 inSession
endSession
시작하여 새 일치 항목(세션)을 시작할 수 있도록 하는 데 사용됩니다.
let Events = datatable (Ts: timespan, Event: string) [
0m, "A",
1m, "A",
2m, "B",
3m, "D",
32m, "B",
36m, "C",
38m, "D",
41m, "E",
75m, "A"
]
;
Events
| sort by Ts asc
| scan with_match_id=session_id declare (sessionStart: timespan) with
(
step inSession: true => sessionStart = iff(isnull(inSession.sessionStart), Ts, inSession.sessionStart);
step endSession output=none: Ts - inSession.sessionStart > 30m;
)
출력
Ts(Ts) | 이벤트 | sessionStart | session_id |
---|---|---|---|
00:00:00 | A | 00:00:00 | 0 |
00:01:00 | A | 00:00:00 | 0 |
00:02:00 | B | 00:00:00 | 0 |
00:03:00 | D | 00:00:00 | 0 |
00:32:00 | B | 00:32:00 | 1 |
00:36:00 | C | 00:32:00 | 1 |
00:38:00 | D | 00:32:00 | 1 |
00:41:00 | E | 00:32:00 | 1 |
01:15:00 | A | 01:15:00 | 2 |
시작과 중지 사이의 이벤트
이벤트와 5분 이내에 발생하는 이벤트 Start
사이의 모든 이벤트 Stop
시퀀스를 찾습니다. 각 시퀀스에 대한 일치 ID를 할당합니다.
let Events = datatable (Ts: timespan, Event: string) [
0m, "A",
1m, "Start",
2m, "B",
3m, "D",
4m, "Stop",
6m, "C",
8m, "Start",
11m, "E",
12m, "Stop"
]
;
Events
| sort by Ts asc
| scan with_match_id=m_id with
(
step s1: Event == "Start";
step s2: Event != "Start" and Event != "Stop" and Ts - s1.Ts <= 5m;
step s3: Event == "Stop" and Ts - s1.Ts <= 5m;
)
출력
Ts(Ts) | 이벤트 | m_id |
---|---|---|
00:01:00 | Start | 0 |
00:02:00 | B | 0 |
00:03:00 | D | 0 |
00:04:00 | 중지 | 0 |
00:08:00 | Start | 1 |
00:11:00 | E | 1 |
00:12:00 | 중지 | 1 |
이벤트의 사용자 지정 깔때기 계산
이벤트(내 1h
및 Thunderstorm Wind
내2h
) 사이의 시간에 대한 사용자 지정 임계값을 사용하여 시퀀스의>Hail
Tornado
Thunderstorm Wind
>State
깔때기형 완성을 계산합니다.Tornado
이 예제는 funnel_sequence_completion 플러그 인과 비슷하지만 유연성이 향상됩니다.
StormEvents
| partition hint.strategy=native by State
(
sort by StartTime asc
| scan with
(
step hail: EventType == "Hail";
step tornado: EventType == "Tornado" and StartTime - hail.StartTime <= 1h;
step thunderstormWind: EventType == "Thunderstorm Wind" and StartTime - tornado.StartTime <= 2h;
)
)
| summarize dcount(State) by EventType
출력
EventType | dcount_State |
---|---|
Hail | 50 |
토네이도 | 34 |
뇌우를 동반한 바람 | 32 |
논리 연습 검사
이 섹션에서는 시작 및 중지 예제 사이의 이벤트에 대한 단계별 연습을 사용하여 검사 논리를 보여 줍니다.
let Events = datatable (Ts: timespan, Event: string) [
0m, "A",
1m, "Start",
2m, "B",
3m, "D",
4m, "Stop",
6m, "C",
8m, "Start",
11m, "E",
12m, "Stop"
]
;
Events
| sort by Ts asc
| scan with_match_id=m_id with
(
step s1: Event == "Start";
step s2: Event != "Start" and Event != "Stop" and Ts - s1.Ts <= 5m;
step s3: Event == "Stop" and Ts - s1.Ts <= 5m;
)
상태
연산자의 scan
상태를 각 단계마다 행이 있는 테이블로 간주합니다. 각 단계에는 고유한 상태가 있습니다. 이 상태에는 이전 단계와 현재 단계의 모든 열 및 선언된 변수의 최신 값이 포함됩니다. 자세한 내용은 State를 참조하세요.
이 예제에서는 다음 표와 함께 상태를 나타낼 수 있습니다.
step | m_id | s1. Ts(Ts) | s1. 이벤트 | s2. Ts(Ts) | s2. 이벤트 | s3. Ts(Ts) | s3. 이벤트 |
---|---|---|---|---|---|---|---|
s1 | X | X | X | X | |||
s2 | X | X | |||||
s3 |
"X"는 특정 필드가 해당 단계와 관련이 없음을 나타냅니다.
일치하는 논리
이 섹션에서는 테이블의 각 레코드를 통해 일치하는 논리 를 Events
따라 각 단계에서 상태 및 출력의 변환을 설명합니다.
참고 항목
입력 레코드는 마지막 단계()부터 첫 번째s1
단계(s3
)에 이르는 단계의 역순으로 평가됩니다.
레코드 1
Ts(Ts) | 이벤트 |
---|---|
0m | "A" |
각 단계에서 평가를 기록합니다.
s3
: 상태가s2
비어 있으므로 Check 1이 전달되지 않고 활성 시퀀스가 없기 때문에s3
Check 2가 전달되지 않습니다.s2
: 상태가s1
비어 있으므로 Check 1이 전달되지 않고 활성 시퀀스가 없기 때문에s2
Check 2가 전달되지 않습니다.s1
: 이전 단계가 없으므로 1 이 관련이 없는지 확인합니다. 레코드가 조건을 충족하지 않으므로 Check 2 가Event == "Start"
전달되지 않습니다. 레코드 1 은 상태 또는 출력에 영향을 주지 않고 삭제됩니다.
State:
step | m_id | s1. Ts(Ts) | s1. 이벤트 | s2. Ts(Ts) | s2. 이벤트 | s3. Ts(Ts) | s3. 이벤트 |
---|---|---|---|---|---|---|---|
s1 | X | X | X | X | |||
s2 | X | X | |||||
s3 |
레코드 2
Ts(Ts) | 이벤트 |
---|---|
1분 | "시작" |
각 단계에서 평가를 기록합니다.
s3
: 상태가s2
비어 있으므로 Check 1이 전달되지 않고 활성 시퀀스가 없기 때문에s3
Check 2가 전달되지 않습니다.s2
: 상태가s1
비어 있으므로 Check 1이 전달되지 않고 활성 시퀀스가 없기 때문에s2
Check 2가 전달되지 않습니다.s1
: 이전 단계가 없으므로 1 이 관련이 없는지 확인합니다. 레코드가 조건을 충족하므로 Check 2 가Event == "Start"
전달됩니다. 이 일치 항목은 새 시퀀스를 시작하고m_id
할당됩니다. 레코드 2 와 해당m_id
(0
)가 상태 및 출력에 추가됩니다.
State:
step | m_id | s1. Ts(Ts) | s1. 이벤트 | s2. Ts(Ts) | s2. 이벤트 | s3. Ts(Ts) | s3. 이벤트 |
---|---|---|---|---|---|---|---|
s1 | 0 | 00:01:00 | "시작" | X | X | X | X |
s2 | X | X | |||||
s3 |
레코드 3
Ts(Ts) | 이벤트 |
---|---|
2m | “B” |
각 단계에서 평가를 기록합니다.
s3
: 상태가s2
비어 있으므로 Check 1이 전달되지 않고 활성 시퀀스가 없기 때문에s3
Check 2가 전달되지 않습니다.s2
: 상태가s1
비어 있지 않으며 레코드가 조건을 충족하므로 Check 1이Ts - s1.Ts < 5m
전달됩니다. 이 일치 항목으로 인해 상태가s1
지워지고 시퀀스가s1
승격됩니다s2
. 레코드 3 및 해당m_id
(0
)가 상태 및 출력에 추가됩니다.s1
: 이전 단계가 없으므로 Check 1은 관련이 없으며 레코드가 조건을Event == "Start"
충족하지 않으므로 Check 2가 전달되지 않습니다.
State:
step | m_id | s1. Ts(Ts) | s1. 이벤트 | s2. Ts(Ts) | s2. 이벤트 | s3. Ts(Ts) | s3. 이벤트 |
---|---|---|---|---|---|---|---|
s1 | X | X | X | X | |||
s2 | 0 | 00:01:00 | "시작" | 00:02:00 | “B” | X | X |
s3 |
레코드 4
Ts(Ts) | 이벤트 |
---|---|
3개월 | "D" |
각 단계에서 평가를 기록합니다.
s3
: 레코드가 조건을Event == "Stop"
충족하지 않으므로 Check 1이 전달되지 않으며 활성 시퀀스가 없기 때문에s3
Check 2가 전달되지 않습니다.s2
: 상태가s1
비어 있으므로 Check 1이 전달되지 않습니다. 의 조건을Ts - s1.Ts < 5m
충족하므로 Check 2를 전달합니다. 레코드 4 및 해당m_id
(0
)가 상태 및 출력에 추가됩니다. 이 레코드의 값은 이전 상태 값을s2.Ts
덮어쓰고s2.Event
.s1
: 이전 단계가 없으므로 Check 1은 관련이 없으며 레코드가 조건을Event == "Start"
충족하지 않으므로 Check 2가 전달되지 않습니다.
State:
step | m_id | s1. Ts(Ts) | s1. 이벤트 | s2. Ts(Ts) | s2. 이벤트 | s3. Ts(Ts) | s3. 이벤트 |
---|---|---|---|---|---|---|---|
s1 | X | X | X | X | |||
s2 | 0 | 00:01:00 | "시작" | 00:03:00 | "D" | X | X |
s3 |
레코드 5
Ts(Ts) | 이벤트 |
---|---|
4m | "중지" |
각 단계에서 평가를 기록합니다.
s3
: 1이(가) 비어 있지 않아서 1이s3
전달s2
되고 해당 조건이Event == "Stop"
충족됩니다. 이 일치 항목으로 인해 상태가s2
지워지고 시퀀스가s2
승격됩니다s3
. 레코드 5 및 해당m_id
(0
)가 상태 및 출력에 추가됩니다.s2
: 상태가s1
비어 있으므로 Check 1이 전달되지 않고 활성 시퀀스가 없기 때문에s2
Check 2가 전달되지 않습니다.s1
: 이전 단계가 없으므로 1 이 관련이 없는지 확인합니다. 레코드가 조건을 충족하지 않으므로 Check 2 가Event == "Start"
전달되지 않습니다.
State:
step | m_id | s1. Ts(Ts) | s1. 이벤트 | s2. Ts(Ts) | s2. 이벤트 | s3. Ts(Ts) | s3. 이벤트 |
---|---|---|---|---|---|---|---|
s1 | X | X | X | X | |||
s2 | X | X | |||||
s3 | 0 | 00:01:00 | "시작" | 00:03:00 | "D" | 00:04:00 | "중지" |
레코드 6
Ts(Ts) | 이벤트 |
---|---|
6m | "C" |
각 단계에서 평가를 기록합니다.
s3
: 상태가s2
비어 있으므로 Check 1이 전달되지 않고 Check 2가 조건을Event == "Stop"
충족s3
하지 않으므로 전달s3
되지 않습니다.s2
: 상태가s1
비어 있으므로 Check 1이 전달되지 않고 활성 시퀀스가 없기 때문에s2
Check 2가 전달되지 않습니다.s1
: 이전 단계가 없으므로 Check 1 이 전달되지 않으며 Check 2 가 조건을Event == "Start"
충족하지 않으므로 전달되지 않습니다. 레코드 6 은 상태 또는 출력에 영향을 주지 않고 삭제됩니다.
State:
step | m_id | s1. Ts(Ts) | s1. 이벤트 | s2. Ts(Ts) | s2. 이벤트 | s3. Ts(Ts) | s3. 이벤트 |
---|---|---|---|---|---|---|---|
s1 | X | X | X | X | |||
s2 | X | X | |||||
s3 | 0 | 00:01:00 | "시작" | 00:03:00 | "D" | 00:04:00 | "중지" |
레코드 7
Ts(Ts) | 이벤트 |
---|---|
8m | "시작" |
각 단계에서 평가를 기록합니다.
s3
: 상태가s2
비어 있으므로 Check 1이 전달되지 않고 Check 2가 조건을Event == "Stop"
충족하지 않으므로 전달되지 않습니다.s2
: 상태가s1
비어 있으므로 Check 1이 전달되지 않고 활성 시퀀스가 없기 때문에s2
Check 2가 전달되지 않습니다.s1
: 이전 단계가 없으므로 Check 1 이 전달되지 않습니다. 의 조건을Event == "Start"
충족하므로 Check 2를 전달합니다. 이 일치 항목은 새 시퀀스를 사용하여 새m_id
시퀀스를s1
시작합니다. 레코드 7 및 해당m_id
(1
)가 상태 및 출력에 추가됩니다.
State:
step | m_id | s1. Ts(Ts) | s1. 이벤트 | s2. Ts(Ts) | s2. 이벤트 | s3. Ts(Ts) | s3. 이벤트 |
---|---|---|---|---|---|---|---|
s1 | 1 | 00:08:00 | "시작" | X | X | X | X |
s2 | X | X | |||||
s3 | 0 | 00:01:00 | "시작" | 00:03:00 | "D" | 00:04:00 | "중지" |
참고 항목
이제 상태에 두 개의 활성 시퀀스가 있습니다.
레코드 8
Ts(Ts) | 이벤트 |
---|---|
11m | "E" |
각 단계에서 평가를 기록합니다.
s3
: 상태가s2
비어 있으므로 Check 1이 전달되지 않고 Check 2가 조건을Event == "Stop"
충족s3
하지 않으므로 전달되지 않습니다.s2
: 상태가s1
비어 있지 않으며 레코드가 조건을 충족하므로 Check 1이Ts - s1.Ts < 5m
전달됩니다. 이 일치 항목으로 인해 상태가s1
지워지고 시퀀스가s1
승격됩니다s2
. 레코드 8 및 해당m_id
(1
)가 상태 및 출력에 추가됩니다.s1
: 이전 단계가 없으므로 Check 1은 관련이 없으며 레코드가 조건을Event == "Start"
충족하지 않으므로 Check 2가 전달되지 않습니다.
State:
step | m_id | s1. Ts(Ts) | s1. 이벤트 | s2. Ts(Ts) | s2. 이벤트 | s3. Ts(Ts) | s3. 이벤트 |
---|---|---|---|---|---|---|---|
s1 | X | X | X | X | |||
s2 | 1 | 00:08:00 | "시작" | 00:11:00 | "E" | X | X |
s3 | 0 | 00:01:00 | "시작" | 00:03:00 | "D" | 00:04:00 | "중지" |
레코드 9
Ts(Ts) | 이벤트 |
---|---|
12m | "중지" |
각 단계에서 평가를 기록합니다.
s3
: 1이(가) 비어 있지 않아서 1이s3
전달s2
되고 해당 조건이Event == "Stop"
충족됩니다. 이 일치 항목으로 인해 상태가s2
지워지고 시퀀스가s2
승격됩니다s3
. 레코드 9 및 해당m_id
(1
)가 상태 및 출력에 추가됩니다.s2
: 상태가s1
비어 있으므로 Check 1이 전달되지 않고 활성 시퀀스가 없기 때문에s2
Check 2가 전달되지 않습니다.s1
: 이전 단계가 없으므로 Check 1 이 전달되지 않습니다. 의 조건을Event == "Start"
충족하므로 Check 2를 전달합니다. 이 일치 항목은 새 시퀀스를 사용하여 새m_id
시퀀스를s1
시작합니다.
State:
step | m_id | s1. Ts(Ts) | s1. 이벤트 | s2. Ts(Ts) | s2. 이벤트 | s3. Ts(Ts) | s3. 이벤트 |
---|---|---|---|---|---|---|---|
s1 | X | X | X | X | |||
s2 | X | X | |||||
s3 | 1 | 00:08:00 | "시작" | 00:11:00 | "E" | 00:12:00 | "중지" |
최종 출력
Ts(Ts) | 이벤트 | m_id |
---|---|---|
00:01:00 | Start | 0 |
00:02:00 | B | 0 |
00:03:00 | D | 0 |
00:04:00 | 중지 | 0 |
00:08:00 | Start | 1 |
00:11:00 | E | 1 |
00:12:00 | 중지 | 1 |