Freigeben über


scan operator

Applies to: ✅Microsoft FabricAzure Data ExplorerAzure MonitorMicrosoft Sentinel

Scannt Daten, führt Abgleiche durch und erstellt Sequenzen basierend auf den Prädikaten.

Übereinstimmende Datensätze werden gemäß den in den Schritten des Operators definierten Prädikaten bestimmt. Ein Prädikat kann vom Zustand abhängen, der durch vorherige Schritte generiert wird. Die Ausgabe für den übereinstimmenden Datensatz wird durch den Eingabedatensatz und die zuordnungen bestimmt, die in den Schritten des Operators definiert sind.

Syntax

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

ColumnDeclarations syntax

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

StepDefinition syntax

step StepName [ output = all | last | none] :Condition [ =>Column=Assignment [, ... ] ] ;

Learn more about syntax conventions.

Parameters

Name Type Required Description
T string ✔️ Die Tabellarische Eingabequelle.
MatchIdColumnName string Der Name einer Spalte vom Typ long , die als Teil der Scanausführung an die Ausgabe angefügt wird. Gibt den 0-basierten Index der Übereinstimmung für den Datensatz an.
ColumnDeclarations string Declares an extension to the schema of T. These columns are assigned values in the steps. If not assigned, the DefaultValue is returned. Unless otherwise specified, DefaultValue is null.
StepName string ✔️ Wird verwendet, um auf Werte im Status der Überprüfung für Bedingungen und Zuordnungen zu verweisen. Der Schrittname muss eindeutig sein.
Condition string ✔️ Ein Ausdruck, der ausgewertet true wird oder false definiert, welche Datensätze aus der Eingabe mit dem Schritt übereinstimmen. Ein Datensatz stimmt mit dem Schritt überein, wenn die Bedingung mit dem Status des Schritts oder mit dem Status des vorherigen Schritts übereinstimmt true .
Assignment string Ein skalarer Ausdruck, der der entsprechenden Spalte zugewiesen ist, wenn ein Datensatz einem Schritt entspricht.
output string Steuert die Ausgabelogik des Schritts für wiederholte Übereinstimmungen. all gibt alle Datensätze aus, die dem Schritt entsprechen, last gibt nur den letzten Datensatz in einer Reihe wiederholter Übereinstimmungen für den Schritt aus und none gibt keine Datensätze aus, die dem Schritt entsprechen. Der Standardwert ist all.

Returns

Ein Datensatz für jede Übereinstimmung eines Datensatzes von der Eingabe zu einem Schritt. Das Schema der Ausgabe ist das Schema der Quelle, die mit der Spalte in der declare Klausel erweitert wird.

Scan logic

scan überschreitet die serialisierten Eingabedaten, datensätze nach Datensatz, vergleicht jeden Datensatz mit der Bedingung jedes Schritts und berücksichtigt dabei den aktuellen Zustand jedes Schritts.

State

Der zugrunde liegende Zustand des scan Operators kann als Tabelle mit jeweils einer Zeile stepbetrachtet werden. Jeder Schritt behält seinen eigenen Zustand mit den neuesten Werten der Spalten und deklarierten Variablen aus allen vorherigen Schritten und dem aktuellen Schritt. Falls relevant, enthält sie auch die Übereinstimmungs-ID für die fortlaufende Sequenz.

If a scan operator has n steps named s_1, s_2, ..., s_n then step s_k would have k records in its state corresponding to s_1, s_2, ..., s_k. The StepName.ColumnName format is used to reference a value in the state. For instance, s_2.col1 would reference column col1 that belongs to step s_2 in the state of s_k. Ein ausführliches Beispiel finden Sie in der exemplarischen Vorgehensweise zur Überprüfungslogik.

Der Zustand beginnt leer und wird aktualisiert, wenn ein gescannter Eingabedatensatz einem Schritt entspricht. When the state of the current step is nonempty, the step is referred to as having an active sequence.

Matching logic

Jeder Eingabedatensatz wird von dem letzten Schritt bis zum ersten Schritt anhand aller Schritte in umgekehrter Reihenfolge ausgewertet. When a record r is evaluated against some step s_k, the following logic is applied:

  • Check 1: If the state of the previous step (s_k-1) is nonempty, and r meets the Condition of s_k, then a match occurs. Die Übereinstimmung führt zu den folgenden Aktionen:

    1. The state of s_k is cleared.
    2. The state of s_k-1 is promoted to become the state of s_k.
    3. The assignments of s_k are calculated and extend r.
    4. The extended r is added to the output and to the state of s_k.

    Note

    If Check 1 results in a match, Check 2 is disregarded, and r moves on to be evaluated against s_k-1.

  • Check 2: If the state of s_k has an active sequence or s_k is the first step, and r meets the Condition of s_k, then a match occurs. Die Übereinstimmung führt zu den folgenden Aktionen:

    1. The assignments of s_k are calculated and extend r.
    2. The values that represent s_k in the state of s_k are replaced with the values of the extended r.
    3. If s_k is defined as output=all, the extended r is added to the output.
    4. If s_k is the first step, a new sequence begins and the match ID increases by 1. Dies wirkt sich nur auf die Ausgabe aus, wenn with_match_id sie verwendet wird.

Once the checks for s_k are complete, r moves on to be evaluated against s_k-1.

Ein ausführliches Beispiel für diese Logik finden Sie in der exemplarischen Vorgehensweise zur Überprüfungslogik.

Examples

Das Beispiel in diesem Abschnitt zeigt, wie Sie die Syntax verwenden, um Ihnen bei den ersten Schritten zu helfen.

The examples in this article use publicly available tables in the help cluster, such as the StormEvents table in the Samples database.

The examples in this article use publicly available tables, such as the Weather table in the Weather analytics sample gallery. Möglicherweise müssen Sie den Tabellennamen in der Beispielabfrage so ändern, dass er der Tabelle in Ihrem Arbeitsbereich entspricht.

Cumulative sum

Berechnen Sie die kumulierte Summe für eine Eingabespalte. The result of this example is equivalent to using 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

Kumulierte Summe für mehrere Spalten mit einer Zurücksetzungsbedingung

Berechnen Sie die kumulierte Summe für zwei Eingabespalten, setzen Sie den Summenwert auf den aktuellen Datensatzwert zurück, wenn die kumulierte Summe 10 oder mehr erreicht hat.

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

Weiterleiten einer Spalte

Füllen Sie eine Zeichenfolgenspalte vorwärts aus. Jedem leeren Wert wird der zuletzt angezeigte Nichterwendwert zugewiesen.Each empty value is assigned the last seen nonempty value.

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

Sessions tagging

Teilen Sie die Eingabe in Sitzungen auf: Eine Sitzung endet 30 Minuten nach dem ersten Ereignis der Sitzung, nach dem eine neue Sitzung gestartet wird. Note the use of with_match_id flag, which assigns a unique value for each distinct match (session) of scan. Also note the special use of two steps in this example, inSession has true as condition so it captures and outputs all the records from the input while endSession captures records that happen more than 30m from the sessionStart value for the current match. Der endSession Schritt hat output=none die Bedeutung, dass es keine Ausgabedatensätze erzeugt. Der endSession Schritt wird verwendet, um den Status der aktuellen Übereinstimmung von inSession zu zu endSessionwechseln, sodass eine neue Übereinstimmung (Sitzung) beginnen kann, beginnend mit dem aktuellen Datensatz.

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

Berechnen der Sitzungslänge pro Benutzer

Berechnen Sie die Startzeit, die Endzeit und die Dauer der Sitzung der einzelnen Benutzer mithilfe des scan Operators. Eine Sitzung wird als Zeitraum zwischen der Anmeldung eines Benutzers und der nachfolgenden Abmeldung definiert. Durch kombinieren partition und scan mit und output=nonemit output=all diesem Muster wird sichergestellt, dass pro Sitzung (d. h. pro Login/Logout-Paar) statt einer Zeile pro Ereignis eine einzelne Zeile zurückgegeben wird.

Die Logik funktioniert wie folgt:

  • In Schritt 1: Erfassen des Anmeldezeitstempels mithilfe eines Scanschritts mit output=none
  • In Schritt 2: Ausstrahlen einer Zeile nur dann, wenn ein übereinstimmender Abmeldung mithilfe einer übereinstimmenden Abmeldung gefunden wird 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

Ereignisse zwischen Start und Stopp

Suchen Sie alle Abfolgen von Ereignissen zwischen dem Ereignis Start und dem Ereignis Stop , die innerhalb von 5 Minuten auftreten. Weisen Sie für jede Sequenz eine Übereinstimmungs-ID zu.

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

Berechnen eines benutzerdefinierten Trichters von Ereignissen

Berechnen Eines Trichterabschlusses der Sequenz Hail ->Tornado>Thunderstorm Wind nach State benutzerdefinierten Schwellenwerten für die Zeiten zwischen den Ereignissen (Tornado innerhalb 1h und Thunderstorm Wind innerhalb ).2h This example is similar to the funnel_sequence_completion plugin, but allows greater flexibility.

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
Thunderstorm Wind 32

Exemplarische Vorgehensweise zur Überprüfungslogik

This section demonstrates the scan logic using a step-by-step walkthrough of the Events between start and stop example:

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

The state

Stellen Sie sich den Status des scan Operators als Tabelle mit einer Zeile für jeden Schritt vor, in der jeder Schritt über einen eigenen Zustand verfügt. Dieser Zustand enthält die neuesten Werte der Spalten und deklarierten Variablen aus allen vorherigen Schritten und dem aktuellen Schritt. To learn more, see State.

In diesem Beispiel kann der Zustand mit der folgenden Tabelle dargestellt werden:

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

Das "X" gibt an, dass für diesen Schritt ein bestimmtes Feld irrelevant ist.

Die entsprechende Logik

This section follows the matching logic through each record of the Events table, explaining the transformation of the state and output at each step.

Note

Ein Eingabedatensatz wird anhand der Schritte in umgekehrter Reihenfolge ausgewertet, von dem letzten Schritt (s3) bis zum ersten Schritt (s1).

Record 1

Ts Event
0m "A"

Aufzeichnen der Auswertung bei jedem Schritt:

  • s3: Check 1 isn't passed because the state of s2 is empty, and Check 2 isn't passed because s3 lacks an active sequence.
  • s2: Check 1 isn't passed because the state of s1 is empty, and Check 2 isn't passed because s2 lacks an active sequence.
  • s1: Check 1 is irrelevant because there's no previous step. Check 2 isn't passed because the record doesn't meet the condition of Event == "Start". Record 1 is discarded without affecting the state or output.

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

Record 2

Ts Event
1m "Start"

Aufzeichnen der Auswertung bei jedem Schritt:

  • s3: Check 1 isn't passed because the state of s2 is empty, and Check 2 isn't passed because s3 lacks an active sequence.
  • s2: Check 1 isn't passed because the state of s1 is empty, and Check 2 isn't passed because s2 lacks an active sequence.
  • s1: Check 1 is irrelevant because there's no previous step. Check 2 is passed because the record meets the condition of Event == "Start". Diese Übereinstimmung initiiert eine neue Sequenz und wird m_id zugewiesen. Record 2 and its m_id (0) are added to the state and the output.

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

Record 3

Ts Event
2m "B"

Aufzeichnen der Auswertung bei jedem Schritt:

  • s3: Check 1 isn't passed because the state of s2 is empty, and Check 2 isn't passed because s3 lacks an active sequence.
  • s2: Check 1 is passed because the state of s1 is nonempty and the record meets the condition of Ts - s1.Ts < 5m. Diese Übereinstimmung bewirkt, dass der Zustand der s1 Löschung erfolgt und die Reihenfolge s1 höhergestuft s2wird. Record 3 and its m_id (0) are added to the state and the output.
  • s1: Check 1 is irrelevant because there's no previous step, and Check 2 isn't passed because the record doesn't meet the condition of 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

Record 4

Ts Event
3m "D"

Aufzeichnen der Auswertung bei jedem Schritt:

  • s3: Check 1 isn't passed because the record doesn't meet the condition of Event == "Stop", and Check 2 isn't passed because s3 lacks an active sequence.
  • s2: Check 1 isn't passed because the state of s1 is empty. it passes Check 2 because it meets the condition of Ts - s1.Ts < 5m. Record 4 and its m_id (0) are added to the state and the output. Die Werte aus diesem Datensatz überschreiben die vorherigen Zustandswerte für s2.Ts und s2.Event.
  • s1: Check 1 is irrelevant because there's no previous step, and Check 2 isn't passed because the record doesn't meet the condition of 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

Record 5

Ts Event
4m "Stop"

Aufzeichnen der Auswertung bei jedem Schritt:

  • s3: Check 1 is passed because s2 is nonempty and it meets the s3 condition of Event == "Stop". Diese Übereinstimmung bewirkt, dass der Zustand der s2 Löschung erfolgt und die Reihenfolge s2 höhergestuft s3wird. Record 5 and its m_id (0) are added to the state and the output.
  • s2: Check 1 isn't passed because the state of s1 is empty, and Check 2 isn't passed because s2 lacks an active sequence.
  • s1: Check 1 is irrelevant because there's no previous step. Check 2 isn't passed because the record doesn't meet the condition of 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"

Record 6

Ts Event
6m "C"

Aufzeichnen der Auswertung bei jedem Schritt:

  • s3: Check 1 isn't passed because the state of s2 is empty, and Check 2 isn't passed because s3 doesn't meet the s3 condition of Event == "Stop".
  • s2: Check 1 isn't passed because the state of s1 is empty, and Check 2 isn't passed because s2 lacks an active sequence.
  • s1: Check 1 isn't passed because there's no previous step, and Check 2 isn't passed because it doesn't meet the condition of Event == "Start". Record 6 is discarded without affecting the state or output.

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"

Record 7

Ts Event
8m "Start"

Aufzeichnen der Auswertung bei jedem Schritt:

  • s3: Check 1 isn't passed because the state of s2 is empty, and Check 2 isn't passed because it doesn't meet the condition of Event == "Stop".
  • s2: Check 1 isn't passed because the state of s1 is empty, and Check 2 isn't passed because s2 lacks an active sequence.
  • s1: Check 1 isn't passed because there's no previous step. it passes Check 2 because it meets the condition of Event == "Start". Diese Übereinstimmung initiiert eine neue Sequenz s1 mit einer neuen m_id. Record 7 and its m_id (1) are added to the state and the output.

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

Es gibt nun zwei aktive Sequenzen im Zustand.

Record 8

Ts Event
11m "E"

Aufzeichnen der Auswertung bei jedem Schritt:

  • s3: Check 1 isn't passed because the state of s2 is empty, and Check 2 isn't passed because it doesn't meet the s3 condition of Event == "Stop".
  • s2: Check 1 is passed because the state of s1 is nonempty and the record meets the condition of Ts - s1.Ts < 5m. Diese Übereinstimmung bewirkt, dass der Zustand der s1 Löschung erfolgt und die Reihenfolge s1 höhergestuft s2wird. Record 8 and its m_id (1) are added to the state and the output.
  • s1: Check 1 is irrelevant because there's no previous step, and Check 2 isn't passed because the record doesn't meet the condition of 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"

Record 9

Ts Event
12m "Stop"

Aufzeichnen der Auswertung bei jedem Schritt:

  • s3: Check 1 is passed because s2 is nonempty and it meets the s3 condition of Event == "Stop". Diese Übereinstimmung bewirkt, dass der Zustand der s2 Löschung erfolgt und die Reihenfolge s2 höhergestuft s3wird. Record 9 and its m_id (1) are added to the state and the output.
  • s2: Check 1 isn't passed because the state of s1 is empty, and Check 2 isn't passed because s2 lacks an active sequence.
  • s1: Check 1 isn't passed because there's no previous step. it passes Check 2 because it meets the condition of Event == "Start". Diese Übereinstimmung initiiert eine neue Sequenz s1 mit einer neuen m_id.

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"

Final 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