CEP (Complex Event Processing)
Table of Contents
- Overview
- Screen Layout — EQL Screen in Automation Group
- Query Screen (
/query/index) - Statement Screen (
/statement/index) - Trigger Screen Reference
- Use Case Scenarios
- Frequently Asked Questions
- Related Screens
Overview
The CEP (Complex Event Processing) feature is a rule engine that identifies meaningful patterns in real-time event streams and immediately performs actions (save, publish, alarm). In the left menu, it is currently exposed as EQL Query and Statement under the Automation group.
| Sub-menu | Internal URL | Purpose |
|---|---|---|
| EQL Query | /query/index | Send temporary EQL (Event Query Language) queries to a real-time stream to view results immediately |
| Statement | /statement/index | View domain rules (state/aggregation/event/command) by asset unit |
The results of CEP rules are automatically connected as asset triggers (flow_on_asset_event, etc.) in Flow.
Screen Layout — EQL Screen in Automation Group
| Screen | Primary User | Summary |
|---|---|---|
| Query | Operations Analyst | Execute a single line of EQL immediately to see results from the real-time stream |
| Statement | Operator | View the status and execution statistics of domain rules registered to assets |
Query Screen (/query/index)
This screen allows you to write temporary EQL queries and execute them immediately using the ▶ button to view results from the real-time stream.
Top — Query Save/History
🔍 쿼리 [💾 이 쿼리를 저장] [↩ 마지막 쿼리] [▼ 이력 ▼]
| Button | Action |
|---|---|
| Save This Query | saveQueryHistory() — Save current EQL to favorites |
| Last Query | loadLastQuery() — Load the most recently executed query |
| History Dropdown | loadQueryHistory() — Display saved query history in a dropdown (scroll up to 400px) |
Queries written in the EQL input window at the top or in the left menu are automatically transferred to this screen for execution.
EQL Input Panel
A large input box with a black border (textarea[name=epl], 8 rows high) and two icons in the top right.
| Icon | Action |
|---|---|
| ▶ (Play, White) | runQuery() — Execute EQL |
| ⚙ (Gear, Gray) | resultConfig() — Result display options dialog (display_count, expire_time, result_format, chart options, etc.) |
Execution Result Panel
The header of the result panel displays the following:
| Item | Display |
|---|---|
| Left | ⚪ "Query Execution Result" + (if saved query) [배치시간=..., EQL ID=...] |
| Right | ▶ Start / ⏸ Stop buttons (Pause real-time result reception) |
Result Chart (query_result_chart, 160px)
- Displays input count (
input_count_cur) and inputs per minute (input_count_min) in the top right. - The chart fills as result data begins to arrive in the form of a real-time line chart.
- Before data arrives, it shows "Waiting for chart data reception..." (rotating icon).
Result Table (query_result_table)
| Column | Description |
|---|---|
| # | Row number |
| Output Time | The time the EQL emitted the result |
| Row Count | Number of rows in a single emit |
| Data | Result body in JSON or table format |
The result table will continue to accumulate unless execution is stopped. Accumulation stops when the Stop button is pressed or a new query is executed.
Trigger Screen Reference
A separate Trigger menu is not present in the left menu. For installation environments currently operating with the existing /trigger/index screen or internal APIs, use the following content for legacy reference only. New automation should prioritize the trigger nodes in Flow and the Automation > EQL Query / Statement workflow.
Manage custom triggers that publish EQL matching results to external message channels or save them to storage.
Top Tools
⚡ 트리거 [➕ 트리거 추가] [↻]
List Table
The right side of the list panel header contains three buttons: Deploy Selected Triggers / Undeploy / Redeploy All.
| Column | Width | Description |
|---|---|---|
| Select | 50px | Checkbox for batch deploy/undeploy |
| Status | 80px | Deploy/Undeploy badge |
| Trigger ID | 110px | System-assigned ID |
| Trigger Name | Description | Auto | Operator-defined metadata |
| MQ Streaming | 70px | Use of MQ publishing (Y/N) |
| Storage Save | 70px | Use of storage loading for results (Y/N) |
| Total Execution Count | 70px | Cumulative matching count |
| Last Execution Date | 110px | Most recent matching time |
| Error | 70px | Cumulative error count |
| Registration Date | 110px | Registration time |
| Last Modified Date | 110px | Last modification time |
| Action | 80px | Edit/Delete buttons |
A guide box is displayed at the bottom of the page.
Using Custom Triggers You can add custom triggers that perform actions when specific conditions are met. Additionally, these can be streamed via MQ or saved to storage.
Trigger Add/Edit Form
Click the Add Trigger button at the top to navigate to the form screen (/trigger/form).
1) Basic Information fieldset
| Input | path | Width | Note |
|---|---|---|---|
| Trigger ID | trigger_id | 200px | Read Only — System assigned |
| Trigger Name | trigger_name | 450px | Human-identifiable name |
| Description | trigger_desc | 600 × 100px (textarea) | Trigger purpose |
2) EQL fieldset
| Input | path | Description |
|---|---|---|
| EQL | epl | 8-row textarea — Write EQL query (SELECT ... FROM ... WHERE ...) |
| ▶ Test Run | (Icon) | runQuery() — Immediately test run the written EQL. Results are displayed in the Query Result table (graph_query_result) below |
Query Result Table (Test Run Preview):
| Column | Description |
|---|---|
| Output Time | The time the EQL emitted the result |
| Data | Result body |
3) Streaming fieldset
| Input | path | Description |
|---|---|---|
| MQ Output Enabled | use_mq (Checkbox) | Whether to publish result data to an external message channel |
| Protocol | mq_protocol (Selector) | MQTT or KAFKA |
| Destination | mq_destination (450px) | Target topic/channel for publishing — Separator: KAFKA -, MQTT /. Example: device-machine-topic-1 or device/machine/topic_1 |
4) Storage Save fieldset
| Input | path | Description |
|---|---|---|
| Storage Save Enabled | use_storage (Checkbox) | Whether to load result data into storage |
The storage table name and column definition area are currently disabled as the trigger result storage table is fixed.
Form Submission
| Button | Action |
|---|---|
| List(☰) | Return to trigger list screen |
| Save (Blue) | Save after input validation. Saving alone does not deploy; you must click Deploy Selected Triggers in the list screen to start actual operation |
Redeploy All
| Button | Location | Action |
|---|---|---|
| Redeploy All | Right of list panel header (🔁) | Batch redeploy all registered triggers. Use after rule engine restart or system inspection |
Operating Procedure
- Add Trigger → Enter EQL, Streaming, and Storage options → Save
- Check the trigger in the list → Click Deploy Selected Triggers → Status changes to "Deployed"
- To temporarily stop during operation, click Undeploy → Status changes to "Undeployed"
- After inspection, use Redeploy All for batch restart
Statement Screen (/statement/index)
This screen is used to view the status and execution statistics of domain rules (state/aggregation/event/command) registered by asset unit.
Top Search/Filter
√ 스테이트먼트 [유형 ▼] [검색 ...] [조회] [↻]
| Control | Option | Description |
|---|---|---|
Type Selector (search_type) | All Types, State (CONTEXT), Aggregation (AGGREGATION), Event (EVENT), Command (COMMAND) | Filter for the 4 rule types |
Search Input (txt) | (250px) | placeholder: "Search ..." — Rule name/applied asset ID/description keywords |
| Inquiry | (Red + 🔍) | search() — Refresh list based on conditions |
| Refresh | (Red + ↻) | refresh() — Refresh screen |
4 Rule Types
| Code | English | Meaning |
|---|---|---|
CONTEXT | State | Defines the current state of an asset (running/stopped/anomaly) using EQL |
AGGREGATION | Aggregation | Aggregates values like average/maximum over a certain window |
EVENT | Event | Publishes a domain event when a specific pattern (e.g., threshold exceedance) occurs |
COMMAND | Command | Publishes a command (flow_on_asset_command) to the asset upon rule match |
List Table
| Column | Width | Description |
|---|---|---|
| Status | 80px | Active/Inactive badge |
| Applied Asset ID | 150px | Identifier of the asset to which the rule is assigned |
| Type | 80px | One of the 4 types (see table above) |
| Statement Name | Auto | Rule name |
| Description | 300px | Rule memo |
| Total Execution Count | 80px | Cumulative number of rule matches |
| Last Execution Date | 120px | Most recent matching time |
| Error | 60px | Cumulative error count |
| Registration Date | 120px | Rule registration time |
| Details | 50px | Click to view rule details screen (/statement/view) |
Creating Statements — Required Fields by Type
Statements are attached to equipment. Select equipment from the asset tree and open Add Statement in the Registry tab (visible to ADMIN only). This screen (/statement/index) is for inquiry and operation.
For EQL SELECT, all output fields designated for the specific type must be provided for the statement to be saved. This is because the Platform reads values by those names. Other fields are optional.
| Type | Dialog Name | Required Fields |
|---|---|---|
EVENT | Event | timestamp · plugin · name · color · from_timestamp · to_timestamp · value |
CONTEXT | Context | timestamp · plugin · key · value |
AGGREGATION | Aggregation | timestamp · plugin · key · value |
COMMAND | Command | timestamp · plugin · key · value |
| Field | Meaning |
|---|---|
timestamp | Event time (epoch ms) |
plugin | Source plugin (OEE, RAM, EMS, etc.) |
key | Item name (Name of state, aggregation, or command) |
value | Value |
name | Event name |
color | Display color |
from_timestamp · to_timestamp | Start · End time (epoch ms) |
Fields are output using ... AS 칸 or by selecting an existing field with the same name. SELECT * will not pass because the field name is not present in the sentence. Selecting a type changes the Fields required for this type guide, and the editor is filled with the template for that type if it is empty.
SELECT
timestamp AS timestamp,
'-' AS plugin,
'' AS key,
'' AS value
FROM Point(tag_id = '...')
The dialog is designed to be validated first via EQL Execution (▶) before saving. If a field is missing, saving is rejected (HTTP 422, asset_statement.eql.missing_columns), and the missing field is displayed in an orange box below the EQL editor.
The EQL of the AGGREGATION statement is missing required fields: key. You must output timestamp, plugin, key, and value using the output name of SELECT (... AS field).
The same rule applies to Console, V5, ISO plugin application, plugin templates, and MCP validate_eql. Values other than the four specified types are rejected as asset_statement.eql.unknown_type.
View Details
Clicking the Details button in the list navigates to a separate screen (/statement/view/{asset_id}/{statement_name}) where the following can be viewed (refer to Statement Details Screen below).
- Rule EQL body
- Execution result history
- Execution trend/aggregation
- Analysis performance trend
- Status history
Statement Details Screen
An analysis view (statement/view.jsp, 715 lines) entered via the details button. It consolidates all operational information for a single rule into one screen.
Top — Identification Header
√ 스테이트먼트 | {statement_name} [ {asset_id} ] [← 목록] [↻]
| Button | Action |
|---|---|
| List(←) | Return to /statement/index |
| Refresh | Reload screen |
Panel 1 — Statement Information (5-Column Table)
| Column | Width | Description |
|---|---|---|
| Status | 250px | Active/Inactive + Last execution time |
| Statement Name | Auto | Rule name |
| Applied Asset | 200px | Asset domain badge — Click to move to Asset Tree |
| Type | 200px | State (CONTEXT), Aggregation (AGGREGATION), Event (EVENT), Command (COMMAND) |
| Registration Date | 160px | Rule registration time |
EQL Body fieldset
The EQL query body of the rule is displayed exactly. You can copy it from the text area and paste it into the Query Screen for a test run.
Input/Output fieldset
| Area | Display |
|---|---|
| Input Series | List of tags and event types used as rule inputs |
| Output Series | Domain event types published by the rule |
| Reset Error Count | Reset only the cumulative error count to 0 (resetErrorCount(asset_id, statement_name)) |
Panel 2 — Execution Result History (4-Column Table)
| Column | Width | Description |
|---|---|---|
| Execution Time | 160px | Time the rule was executed |
| Result | 60px | Success (Green) / Error (Red) |
| Result Value / Error Message | Auto | Result body if successful, error message if error |
| Copy | 50px | 📋 — Copy result value/error message to clipboard |
Panel 3 — Execution Trend Chart
| Item | Description |
|---|---|
| Header | 📊 "Execution Trend" |
| Button | Today (switchTrendDay(0)) / Yesterday (switchTrendDay(-1)) toggle |
| Chart | Cumulative success/error bars by hour for 24 hours (Series: Success, Error) |
Panel 4 — Execution Aggregation
| Item | Description |
|---|---|
| Header | 📊 "Execution Aggregation" |
| Button | Today (switchAggDay(0)) / Yesterday (switchAggDay(-1)) toggle |
| fieldset 1 | Minute-level aggregation (Count by hour, average throughput, etc.) |
| fieldset 2 | Priority or result distribution |
Panel 5 — Analysis Performance Trend
| Item | Description |
|---|---|
| Header | 🖥 "Analysis Performance Trend" |
| Button | Today (switchCpuDay(0)) / Yesterday (switchCpuDay(-1)) toggle |
| Chart | Time series of CPU/processing time used for rule processing — Identify heavy rules |
Panel 6 — Status History Table
| Column | Description |
|---|---|
| Change Time | Time of rule status change (Active, Undeployed, Redeployed, etc.) |
| Status | Changed status |
Used to track the rule lifecycle (when it was activated, undeployed, or modified).
Utilization Patterns
| Analysis Flow | Screen Flow |
|---|---|
| Error Rule Diagnosis | Execution Result History → Error Message → Copy → Review EQL Body → Test Run in Query Screen |
| Identifying Heavy Rules | Analysis Performance Trend → Time period with high CPU usage → Simplify EQL Body |
| Rule Match Distribution Analysis | Execution Trend + Aggregation → Matching patterns by hour |
| Operational Rule Maintenance | Status History → Track activation/undeploy timing |
Use Case Scenarios
| Scenario | Screen | Procedure |
|---|---|---|
| Immediate check of current line operation status | Query | Enter SELECT * FROM AssetData.win:time(1 sec) WHERE asset_id='LINE-A' in EQL input window → ▶ |
| Testing and deploying a new alarm rule | Trigger | Add → Write EQL → ▶ Test Run → Verify result → Save → Deploy |
| Relaying asset events to external SCADA | Trigger | Publish EQL matching messages to MQTT topic scada/line-a/events |
| Inspection of rules by asset unit | Statement | Type=EVENT + Search Asset ID → Active rule list + Execution count |
| Suspected rule flooding | Statement | Check rules with large total execution counts first → Review EQL/Input in Details |
| Receiving rule results via automation | Flow | Receive domain rule results directly via flow_on_asset_event trigger |
Frequently Asked Questions
Q. Is EQL the same as SQL?
A. While they use similar syntax, EQL is an event processing language that adds the concepts of time windows and streams. For example, Point.win:time(5 sec) processes only data from the last 5 seconds, while Point.win:length(100) processes only the last 100 records.
Q. Are queries executed in the Query screen saved? A. Execution via ▶ is temporary; you must click the Save This Query button to save it to favorites. For one-time analysis, you do not need to save.
Q. I saved a trigger, but it is not working. A. Saving only registers the definition. You must check that trigger in the list and click Deploy Selected Triggers for it to be registered in the rule engine and begin matching.
Q. How should I define the trigger destination? A. The separator differs based on the Protocol:
- KAFKA: Hyphen (
-) separator — Example:device-machine-topic-1 - MQTT: Slash (
/) separator — Example:device/machine/topic_1
Q. Searches in the Statement screen are returning no results. A. Please check if "Type" (All) is selected in the type selector. Also, partial match searches are performed even if only a part of the asset ID is entered.
Q. The total execution count is abnormally high.
A. It is likely that the rule's input window is too narrow or the matching conditions are too broad. Review the EQL via the Details button or use trigger patterns (*_pattern) in Flow to pre-filter messages.
Q. The EQL test run result for the trigger is empty.
A. There may be no data inflow at the time of the test, or the EQL window may be too long, delaying the first match. Wait for about 1 minute and check again, or adjust the window to be shorter (win:time(1 sec)) for testing.
Q. How do I temporarily stop a trigger? A. Check the trigger in the list and click Undeploy. To start it again, use Deploy Selected Triggers.
Q. Are rules automatically assigned to assets? A. Depending on the operating environment settings, basic domain rules may be automatically assigned when an asset is registered. Check the currently applied rules in the Statement screen; if additions or removals are needed, proceed via the system administrator or the asset-specific settings screen.
Q. I want to process EQL results automatically.
A. You can automatically receive domain rule results via asset triggers (flow_on_asset_event/flow_on_asset_alarm, etc.) in Flow and link them to follow-up actions (issuing work orders, email, external API calls).
Related Screens
- Data Point — Time series tag data that serves as EQL input
- Alarm — Operational screen for alarms generated by triggers
- Flow — Automatic processing of rule results via asset triggers
- Factory Management — Rule assignment in the asset tree
- Status Code Definition — Status codes (NORMAL/WARN/ERROR) evaluated by rules
- Diagnostic — Error logs during rule processing