Overview
In UModel, an entity is a concrete instance of an EntitySet representing a system resource such as a service, host, or Pod. This topic covers entity data format, ingestion methods, and best practices.
For UModel, EntitySet, and entity concepts, see Introduction to the Entity Store.
Entity data format
Entity data is written to the ${workspace}__entity Logstore in EntityStore using the SLS protocol. Each record contains system fields and custom fields.
System fields
|
Field name |
Type |
Required |
Example |
Description |
|
|
string |
Yes |
apm, k8s, acs |
Domain for data isolation and categorization. |
|
|
string |
Yes |
apm.service, k8s.pod |
Entity classification. |
|
|
string |
Yes |
391274C9A1D369FB5222E273D02B81B8 |
Unique identifier. 128-bit hex string. |
|
|
string |
No (Default: Update) |
Create, Update, Expire, Delete, Revise |
Operation type that controls entity lifecycle. |
|
|
int |
No |
1700000000 |
Unix timestamp (seconds) of first observation. |
|
|
int |
Yes |
1700000001 |
Unix timestamp (seconds) of last observation. |
|
|
int |
No (Default: 3600) |
3600 |
Entity TTL in seconds. |
Field descriptions
__entity_id__ generation rules
-
Standard format: 128-bit hexadecimal string.
-
Recommended method: Apply MD5 or double xxhash to the entity's primary key(s).
-
Fallback behavior (not recommended): Non-hex IDs are automatically converted via xxhash.
Time field management
-
__first_observed_time__: Timestamp of first discovery. Immutable after creation. -
__last_observed_time__: Timestamp of most recent observation. Update on each write. -
Entity Visible Time Range:
[__first_observed_time__, __last_observed_time__ + __keep_alive_seconds__) -
Note: If omitted during creation, EntityStore defaults
__first_observed_time__to the value of__last_observed_time__.
Custom fields
You can add any custom fields defined in the corresponding EntitySet.
{
"__domain__": "apm",
"__entity_type__": "apm.service",
"__entity_id__": "391274C9A1D369FB5222E273D02B81B8",
"__method__": "Update",
"__last_observed_time__": 1700000001,
"__keep_alive_seconds__": 3600,
"service_name": "user-service",
"version": "v1.2.3",
"cluster": "production",
"labels": {
"env": "prod",
"team": "backend"
}
}
Notes on JSON fields
⚠️ Important: Serialize JSON field keys (such as labels and annotations) in alphabetical order. Non-alphabetical ordering triggers unnecessary index rebuilds.
Entity time range and query coverage
Time range concepts
Each entity has a visibility range. The query engine returns an entity only when the query window intersects its visibility range.
Calculating entity visibility
Entity visibility is calculated as follows:
Note
Both entity visibility and query time ranges use left-closed, right-open intervals.
|
Entity status |
Visible time range |
Description |
|
Normal status |
|
Includes the keep-alive extension. |
|
Expired status (after |
|
Excludes the keep-alive extension. |
|
Deleted status |
No visible time range |
The entity is never returned by any query. |
Time intersection logic
The query engine returns an entity when its visibility range overlaps with the query time window.
An entity is returned if: QueryTimeWindow ∩ EntityVisibleTimeRange is not empty.
The intersection logic is as follows:
if (QueryEndTime >= EntityFirstObservedTime &&
QueryStartTime < EntityVisibleEndTime) {
// Return the entity
} else {
// Do not return the entity
}
Write methods
Create
Use case: Use only when you are certain a new entity is being created, such as a Pod creation event.
Behavior:
-
If the entity exists, no action is taken.
-
If the entity does not exist, creates it with the provided fields.
Example:
{
"__domain__": "k8s",
"__entity_type__": "k8s.pod",
"__entity_id__": "abc123...",
"__method__": "Create",
"__first_observed_time__": 1700000000,
"__last_observed_time__": 1700000000,
"pod_name": "web-app-123",
"namespace": "default"
}
Update
Use case: Suitable for periodic full syncs and incremental changes.
Behavior:
-
Overwrites all fields except __first_observed_time__.
-
Handling of
__first_observed_time__:-
If the entity exists, preserves its
__first_observed_time__. -
If the entity does not exist and the field is provided, uses the given value.
-
If the entity does not exist and the field is omitted, defaults to
__last_observed_time__.
-
Example:
{
"__domain__": "apm",
"__entity_type__": "apm.service",
"__entity_id__": "def456...",
"__method__": "Update",
"__last_observed_time__": 1700000100,
"service_name": "payment-service",
"status": "running",
"instance_count": 3
}
Expire
Use case: Logically delete an entity while preserving its historical record, such as on a Pod deletion event.
Behavior:
-
Sets an internal
__deleted__flag totrue. -
Updates
__last_observed_time__. -
KeepAliveSecondsis no longer counted in queries.
Time range change:
-
Before expiration:
[FirstObservedTime, LastObservedTime + KeepAliveSeconds). -
After expiration:
[FirstObservedTime, LastObservedTime)
Example:
{
"__domain__": "k8s",
"__entity_type__": "k8s.pod",
"__entity_id__": "abc123...",
"__method__": "Expire",
"__last_observed_time__": 1700000200
}
Delete (use with extreme caution)
Use case: Make an entity invisible across its entire history, such as when a feature is disabled.
Behavior:
-
Physically purges the entity record from the database.
-
Entity becomes unqueryable across all time ranges.
⚠️ Warning: This operation is irreversible. Use it only when absolutely necessary.
Revise (use with extreme caution)
Use case: Forcibly correct incorrectly written data. Often used with Delete.
Behavior:
-
Full overwrite of all fields, including
__first_observed_time__. -
Ignores the entity's previous state entirely.
Ingestion best practices
Recommended: Incremental events + periodic full syncs
Combine real-time incremental events with periodic full syncs for data reconciliation and fault tolerance.
Configuration recommendations:
-
Incremental events: Write in real time or near real time.
-
Periodic full sync: Run every hour or longer.
-
Keep-alive time: Typically 10 minutes to 1 hour, based on business needs.
-
Note: Set
__keep_alive_seconds__longer than your reporting interval. Use a reporting interval of 5 minutes or longer to avoid performance degradation.
Practical scenarios
Scenario 1: Synchronize cloud product resources
Use the incremental and full synchronization mechanism from RMC (Resource Management Center).
Handling incremental events:
-
Resource creation event: use Create.
-
Resource update event: use Update.
-
Resource deletion event: use Delete.
Handling full sync events:
-
For periodic full sync, use Update for all resources.
-
Configure
__keep_alive_seconds__based on your business needs.
// Cloud resource creation event
{
"__domain__": "acs",
"__entity_type__": "acs.ecs.instance",
"__entity_id__": "i-bp1234567890",
"__method__": "Create",
"__first_observed_time__": 1700000000,
"__last_observed_time__": 1700000000,
"__keep_alive_seconds__": 86400,
"instance_id": "i-bp1234567890",
"instance_name": "web-server-01",
"instance_type": "ecs.c6.large",
"status": "Running"
}
Scenario 2: Collect asset data with an agent
Use a collector such as LoongCollector to gather Kubernetes asset data.
Initial full collection:
-
Run a full collection on agent startup.
-
Run a full collection every 1 hour thereafter.
-
Use the method Update for all writes.
Subscribing to incremental events:
-
Subscribe to Kubernetes API events.
-
Map each event type to the corresponding write method (Create, Update, Expire, or Delete).
-
Write incremental changes in real-time.
// K8s Pod full collection data
{
"__domain__": "k8s",
"__entity_type__": "k8s.pod",
"__entity_id__": "pod-web-app-123",
"__method__": "Update",
"__last_observed_time__": 1700000400,
"__keep_alive_seconds__": 3600,
"pod_name": "web-app-123",
"namespace": "production",
"node_name": "worker-01",
"pod_ip": "10.0.1.100",
"labels": {
"app": "web-app",
"version": "v1.0"
}
}
Discouraged ingestion patterns
Event-Only Management
-
Problem: Requires querying across all time ranges, which degrades performance.
-
Use case: Only applicable when entity lifecycle is driven exclusively by events and historical accuracy is paramount.
Full Ingestion Only
-
Problem: High discovery latency and large data volumes.
-
Recommendation: If incremental updates are not feasible, use full ingestion intervals of 10 minutes or longer.
Ingestion endpoints
Write data to the ${workspace}__entity Logstore via the SLS protocol. The system automatically syncs data to the EntityStore engine.
Supported ingestion methods:
-
ELT Data Transformation
-
Scheduled SQL
-
Direct API or SDK reporting
Important considerations
-
Data consistency:
__domain__,__entity_type__, and__entity_id__must remain consistent throughout an entity's lifecycle. -
Timestamp management: Use Unix timestamps in seconds for all time fields. UTC is recommended.
-
Method selection: Choose the appropriate method for your use case. Use Delete with extreme caution.
-
Performance: Tune
__keep_alive_seconds__to balance data retention with query performance. -
JSON formatting: Serialize keys in JSON fields alphabetically to avoid unnecessary index rebuilds.
-
Entity count: Limit each
`EntitySet`to 10,000 entities and the total count to 1,000,000. Exceeding these limits degrades performance.