Оператор сканирования

Переключайте службы с помощью раскрывающегося списка Версия. Дополнительные сведения о навигации.
Область применения: ✅ Microsoft Fabric ✅ Azure Data Explorer ✅ Azure Monitor ✅ Microsoft Sentinel

Сканирует данные, сопоставляет их и создает последовательности на основе предикатов.

Соответствующие записи определяются в соответствии с предикатами, определенными в шагах оператора. Предикат может зависеть от состояния, созданного предыдущими шагами. Выходные данные для соответствующей записи определяются входной записью и назначениями, определенными в шагах оператора.

Syntax

T| scan [ with_match_id=MatchIdColumnName ] [ declare(ColumnDeclarations ] )with()

Синтаксис columnDeclarations

ColumnName:ColumnType[=DefaultValue ] [ ..., ]

Синтаксис StepDefinition

step StepName [ output = all | last | none:] Условие [ =>Назначение= [, ... ];

Дополнительные сведения о соглашениях синтаксиса.

Parameters

Name Type Required Description
T string ✔️ Входной табличный источник.
MatchIdColumnName string Имя столбца типа long , добавляемого к выходным данным в рамках выполнения сканирования. Указывает 0-й индекс соответствия для записи.
ColumnDeclarations string Объявляет расширение для схемы T. Эти столбцы назначаются значениями в шагах. Если значение не назначено, возвращается значение DefaultValue . Если иное не указано, значение DefaultValue не задано null.
StepName string ✔️ Используется для ссылки на значения в состоянии сканирования условий и назначений. Имя шага должно быть уникальным.
Condition string ✔️ Выражение, которое оценивается true или false определяет, какие записи из входных данных соответствуют шагу. Запись соответствует шагу, когда условие находится true в состоянии шага или с состоянием предыдущего шага.
Assignment string Скалярное выражение, назначенное соответствующему столбцу, когда запись соответствует шагу.
output string Управляет логикой вывода шага на повторяющихся совпадениях. all Выводит все записи, соответствующие шагу, last выводит только последнюю запись в серии повторяющихся совпадений для шага и none не выводит записи, соответствующие шагу. Значение по умолчанию — all.

Returns

Запись для каждого совпадения записи из входных данных на шаг. Схема выходных данных — это схема источника, расширенная с столбцом в предложении declare .

Логика сканирования

scan передает сериализованные входные данные, запись по записи, сравнивая каждую запись с условием каждого шага при учете текущего состояния каждого шага.

State

Базовое состояние scan оператора можно рассматривать как таблицу с строкой для каждого.step Каждый шаг сохраняет собственное состояние с последними значениями столбцов и объявленными переменными из всех предыдущих шагов и текущего шага. При необходимости он также содержит идентификатор соответствия для текущей последовательности.

Если оператор сканирования имеет n шагов с именем s_1, s_2, ..., s_n, то s_k шаг будет иметь записи k в своем состоянии, соответствующем s_1, s_2, ..., s_k. Имя шага. Формат ColumnName используется для ссылки на значение в состоянии. Например, будет ссылаться на столбецs_2.col1, col1 принадлежащий шагу s_2 в состоянии s_k. Подробный пример см. в пошаговом руководстве по логике сканирования.

Состояние запускается пустым и обновляется всякий раз, когда сканированная входная запись соответствует шагу. Если состояние текущего шага не является непустым, шаг называется активным последовательность.

Логика сопоставления

Каждая входная запись вычисляется по всем шагам в обратном порядке от последнего шага до первого. При оценке записи на некоторых шагах s_k применяется следующая логика:

  • Проверка 1. Если состояние предыдущего шага (s_k-1) непустимо, а r соответствует условию s_k, то возникает совпадение. Совпадение приводит к следующим действиям:

    1. Состояние s_k очищается.
    2. Состояние s_k-1 способствует тому, чтобы стать состоянием s_k.
    3. Назначения s_k вычисляются и расширяются.
    4. Расширенный r добавляется в выходные данные и в состояние s_k.

    Note

    Если проверка 1 приводит к совпадению, проверка 2 игнорируется, и r переходит к оценке по s_k-1.

  • Проверка 2. Если состояние s_k имеет активную последовательность или s_k является первым шагом, а r соответствует условию s_k, то возникает совпадение. Совпадение приводит к следующим действиям:

    1. Назначения s_k вычисляются и расширяются.
    2. Значения, представляющие s_k в состоянии s_k , заменяются значениями расширенного r.
    3. Если s_k определен как output=all, расширенный r добавляется в выходные данные.
    4. Если s_k является первым шагом, начинается новая последовательность, а идентификатор соответствия увеличивается на 1. Это влияет только на выходные данные при with_match_id использовании.

После завершения проверок s_kr переходит к оценке по s_k-1.

Подробный пример этой логики см. в пошаговом руководстве по логике сканирования.

Examples

В этом разделе показано, как использовать синтаксис для начала работы.

Примеры, приведенные в этой статье, используют общедоступные таблицы в кластере справки, например StormEvents таблицу в базе данных Samples .

В примерах этой статьи используются общедоступные таблицы, такие как Weather таблица в коллекции примеров Weather Analytics. Возможно, потребуется изменить имя таблицы в примере запроса, чтобы она соответствовала таблице в рабочей области.

Совокупная сумма

Вычислите совокупную сумму для входного столбца. Результат этого примера эквивалентен использованию 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;
)

Output

x cumulative_x
1 1
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);
)

Output

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

Заливка столбца вперед

Заполните строковый столбец. Каждое пустое значение присваивается последнему видное значение nonempty.

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);
)

Output

Ts Event 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 , которое назначает уникальное значение для каждого отдельного совпадения (сеанса) сканирования. Кроме того, обратите внимание на то, что в этом примере используется специальное использование двух шагов , inSessiontrue поэтому оно записывает и выводит все записи из входных данных при endSession записи записей, которые происходят более 30 млн из sessionStart значения текущего совпадения. Шаг endSession имеет значение, output=none что он не создает выходные записи. Этот endSession шаг используется для продвижения состояния текущего совпадения до inSessionendSession, что позволяет начать новый матч (сеанс), начиная с текущей записи.

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;
)

Output

Ts Event 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

Вычисление длины сеанса на пользователя

Вычислите время начала сеанса, время окончания и длительность сеанса каждого пользователя с помощью scan оператора. Сеанс определяется как период между именем входа пользователя и последующим выходом. Объединение и partitionscanoutput=none использование output=all этого шаблона гарантирует, что одна строка возвращается на сеанс (т. е. для каждой пары входа и выхода), а не для каждой строки на событие.

Логика работает следующими способами:

  • На шаге s1. Запись метки времени входа с помощью шага сканирования output=none
  • На шаге s2: создание строки только при обнаружении соответствующего выхода с помощью output=all
let LogsEvents = datatable(Timestamp:datetime, userID:int, EventType:string)
[
    datetime(2024-05-28 08:15:23), 1, "login",
    datetime(2024-05-28 08:30:15), 2, "login",
    datetime(2024-05-28 09:10:27), 3, "login",
    datetime(2024-05-28 12:30:45), 1, "logout",
    datetime(2024-05-28 11:45:32), 2, "logout",
    datetime(2024-05-28 13:25:19), 3, "logout"
];
LogsEvents
| sort by userID, Timestamp
| partition hint.strategy=native by userID (
    sort by Timestamp asc 
    | scan declare (start: datetime, end: datetime, sessionDuration: timespan) with (
        step s1 output=none: EventType == "login" => start = Timestamp;
        step s2 output=all: EventType == "logout" => start = s1.start, end = Timestamp, sessionDuration = Timestamp - s1.start;
    )
)
| project start, end, userID, sessionDuration

Output

userID start end sessionDuration
1 2024-05-28 08:15:23.0000 2024-05-28 12:30:45.0000 04:15:22
3 2024-05-28 09:10:27.0000 2024-05-28 13:25:19.0000 04:14:52
2 2024-05-28 08:30:15.0000 2024-05-28 11:45:32.0000 03:15:17

События между запуском и остановкой

Найдите все последовательности событий между событием Start и событием Stop , которое происходит в течение 5 минут. Назначьте идентификатор соответствия для каждой последовательности.

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;
)

Output

Ts Event m_id
00:01:00 Start 0
00:02:00 B 0
00:03:00 D 0
00:04:00 Stop 0
00:08:00 Start 1
00:11:00 E 1
00:12:00 Stop 1

Вычисление настраиваемой воронки событий

Вычислите завершение воронки последовательности Hail —>Tornado>Thunderstorm Wind с State пользовательскими порогами времени между событиями (Tornadoвнутри 1h и Thunderstorm Wind внутри).2h Этот пример похож на подключаемый модуль 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

Output

EventType dcount_State
Hail 50
Tornado 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;
)

Output

Ts Event m_id
00:01:00 Start 0
00:02:00 B 0
00:03:00 D 0
00:04:00 Stop 0
00:08:00 Start 1
00:11:00 E 1
00:12:00 Stop 1

Состояние

Подумайте о состоянии scan оператора в виде таблицы со строкой для каждого шага, в котором каждый шаг имеет собственное состояние. Это состояние содержит последние значения столбцов и объявленные переменные из всех предыдущих шагов и текущего шага. Дополнительные сведения см. в разделе "Состояние".

В этом примере состояние может быть представлено в следующей таблице:

step m_id s1.Ts s1.Event s2.Ts s2.Event s3.Ts s3.Event
s1 X X X X
s2 X X
s3

Значение "X" указывает, что определенное поле не имеет значения для этого шага.

Логика сопоставления

Этот раздел следует логике сопоставления по каждой записи Events таблицы, объясняя преобразование состояния и выходных данных на каждом шаге.

Note

Входная запись вычисляется по шагам в обратном порядке с последнего шага (s3) до первого шага (s1).

Запись 1

Ts Event
0m "A"

Запись оценки на каждом шаге:

  • s3: проверка 1 не передается, так как состояние s2 пусто, и проверка 2 не передается, так как s3 отсутствует активная последовательность.
  • s2: проверка 1 не передается, так как состояние s1 пусто, и проверка 2 не передается, так как s2 отсутствует активная последовательность.
  • s1: проверка 1 не имеет значения, потому что нет предыдущего шага. Проверка 2 не передается, так как запись не соответствует условию Event == "Start". Запись 1 удаляется без влияния на состояние или выходные данные.

State:

step m_id s1.Ts s1.Event s2.Ts s2.Event s3.Ts s3.Event
s1 X X X X
s2 X X
s3

Запись 2

Ts Event
1m "Start"

Запись оценки на каждом шаге:

  • s3: проверка 1 не передается, так как состояние s2 пусто, и проверка 2 не передается, так как s3 отсутствует активная последовательность.
  • s2: проверка 1 не передается, так как состояние s1 пусто, и проверка 2 не передается, так как s2 отсутствует активная последовательность.
  • s1: проверка 1 не имеет значения, потому что нет предыдущего шага. Проверка 2 передается, так как запись соответствует условию Event == "Start". Это совпадение инициирует новую последовательность и m_id назначается. Запись 2 и ее m_id (0) добавляются в состояние и выходные данные.

State:

step m_id s1.Ts s1.Event s2.Ts s2.Event s3.Ts s3.Event
s1 0 00:01:00 "Start" X X X X
s2 X X
s3

Запись 3

Ts Event
2m "B"

Запись оценки на каждом шаге:

  • s3: проверка 1 не передается, так как состояние s2 пусто, и проверка 2 не передается, так как s3 отсутствует активная последовательность.
  • s2: проверка 1 передается, так как состояние s1 неmpty и запись соответствует условию Ts - s1.Ts < 5m. Это совпадение приводит к очистке состоянияs1, а последовательность s1 должна быть повышена.s2 Запись 3 и ее m_id (0) добавляются в состояние и выходные данные.
  • s1: проверка 1 не имеет значения, так как предыдущий шаг отсутствует, и проверка 2 не передается, так как запись не соответствует условию Event == "Start".

State:

step m_id s1.Ts s1.Event s2.Ts s2.Event s3.Ts s3.Event
s1 X X X X
s2 0 00:01:00 "Start" 00:02:00 "B" X X
s3

Запись 4

Ts Event
3m "D"

Запись оценки на каждом шаге:

  • s3: проверка 1 не передается, так как запись не соответствует условию Event == "Stop", и проверка 2 не передается, так как s3 отсутствует активная последовательность.
  • s2: проверка 1 не передается, так как состояние s1 пусто. Она проходит проверку 2 , так как она соответствует условию Ts - s1.Ts < 5m. Запись 4 и ее m_id (0) добавляются в состояние и выходные данные. Значения из этой записи перезаписывают предыдущие значения состояния для s2.Ts и s2.Event.
  • s1: проверка 1 не имеет значения, так как предыдущий шаг отсутствует, и проверка 2 не передается, так как запись не соответствует условию Event == "Start".

State:

step m_id s1.Ts s1.Event s2.Ts s2.Event s3.Ts s3.Event
s1 X X X X
s2 0 00:01:00 "Start" 00:03:00 "D" X X
s3

Запись 5

Ts Event
4m "Stop"

Запись оценки на каждом шаге:

  • s3: проверка 1 передается, так как s2 не является немплетной, и она соответствует условию s3Event == "Stop". Это совпадение приводит к очистке состоянияs2, а последовательность s2 должна быть повышена.s3 Запись 5 и ее m_id (0) добавляются в состояние и выходные данные.
  • s2: проверка 1 не передается, так как состояние s1 пусто, и проверка 2 не передается, так как s2 отсутствует активная последовательность.
  • s1: проверка 1 не имеет значения, потому что нет предыдущего шага. Проверка 2 не передается, так как запись не соответствует условию Event == "Start".

State:

step m_id s1.Ts s1.Event s2.Ts s2.Event s3.Ts s3.Event
s1 X X X X
s2 X X
s3 0 00:01:00 "Start" 00:03:00 "D" 00:04:00 "Stop"

Запись 6

Ts Event
6m "C"

Запись оценки на каждом шаге:

  • s3: проверка 1 не передается, так как состояние s2 пусто, и проверка 2 не передается, так как s3 не соответствует условию s3Event == "Stop".
  • s2: проверка 1 не передается, так как состояние s1 пусто, и проверка 2 не передается, так как s2 отсутствует активная последовательность.
  • s1: проверка 1 не передается, так как нет предыдущего шага, и проверка 2 не передается, так как она не соответствует условию Event == "Start". Запись 6 удаляется без влияния на состояние или выходные данные.

State:

step m_id s1.Ts s1.Event s2.Ts s2.Event s3.Ts s3.Event
s1 X X X X
s2 X X
s3 0 00:01:00 "Start" 00:03:00 "D" 00:04:00 "Stop"

Запись 7

Ts Event
8m "Start"

Запись оценки на каждом шаге:

  • s3: проверка 1 не передается, так как состояние s2 пусто, и проверка 2 не передается, так как она не соответствует условию Event == "Stop".
  • s2: проверка 1 не передается, так как состояние s1 пусто, и проверка 2 не передается, так как s2 отсутствует активная последовательность.
  • s1: проверка 1 не пройдена, так как предыдущий шаг отсутствует. Она проходит проверку 2 , так как она соответствует условию Event == "Start". Это совпадение инициирует новую последовательность с s1 новым m_id. Запись 7 и ее m_id (1) добавляются в состояние и выходные данные.

State:

step m_id s1.Ts s1.Event s2.Ts s2.Event s3.Ts s3.Event
s1 1 00:08:00 "Start" X X X X
s2 X X
s3 0 00:01:00 "Start" 00:03:00 "D" 00:04:00 "Stop"

Note

Теперь в состоянии есть две активные последовательности.

Запись 8

Ts Event
11m "E"

Запись оценки на каждом шаге:

  • s3: проверка 1 не передается, так как состояние s2 пусто, и проверка 2 не передается, так как она не соответствует s3 условию Event == "Stop".
  • s2: проверка 1 передается, так как состояние s1 неmpty и запись соответствует условию Ts - s1.Ts < 5m. Это совпадение приводит к очистке состоянияs1, а последовательность s1 должна быть повышена.s2 Запись 8 и ее m_id (1) добавляются в состояние и выходные данные.
  • s1: проверка 1 не имеет значения, так как предыдущий шаг отсутствует, и проверка 2 не передается, так как запись не соответствует условию Event == "Start".

State:

step m_id s1.Ts s1.Event s2.Ts s2.Event s3.Ts s3.Event
s1 X X X X
s2 1 00:08:00 "Start" 00:11:00 "E" X X
s3 0 00:01:00 "Start" 00:03:00 "D" 00:04:00 "Stop"

Запись 9

Ts Event
12m "Stop"

Запись оценки на каждом шаге:

  • s3: проверка 1 передается, так как s2 не является немплетной, и она соответствует условию s3Event == "Stop". Это совпадение приводит к очистке состоянияs2, а последовательность s2 должна быть повышена.s3 Запись 9 и ее m_id (1) добавляются в состояние и выходные данные.
  • s2: проверка 1 не передается, так как состояние s1 пусто, и проверка 2 не передается, так как s2 отсутствует активная последовательность.
  • s1: проверка 1 не передается, так как нет предыдущего шага, и проверка 2 не передается, так как запись не соответствует условию event == "Start".

State:

step m_id s1.Ts s1.Event s2.Ts s2.Event s3.Ts s3.Event
s1 X X X X
s2 X X
s3 1 00:08:00 "Start" 00:11:00 "E" 00:12:00 "Stop"

Окончательные выходные данные

Ts Event m_id
00:01:00 Start 0
00:02:00 B 0
00:03:00 D 0
00:04:00 Stop 0
00:08:00 Start 1
00:11:00 E 1
00:12:00 Stop 1