All Products
Search
Document Center

Cloud Monitor:Entity data model and ingestion

Last Updated:Aug 27, 2026

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.

Note

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

__domain__

string

Yes

apm, k8s, acs

Domain for data isolation and categorization.

__entity_type__

string

Yes

apm.service, k8s.pod

Entity classification.

__entity_id__

string

Yes

391274C9A1D369FB5222E273D02B81B8

Unique identifier. 128-bit hex string.

__method__

string

No (Default: Update)

Create, Update, Expire, Delete, Revise

Operation type that controls entity lifecycle.

__first_observed_time__

int

No

1700000000

Unix timestamp (seconds) of first observation.

__last_observed_time__

int

Yes

1700000001

Unix timestamp (seconds) of last observation.

__keep_alive_seconds__

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

Note
Both entity visibility and query time ranges use left-closed, right-open intervals.

Entity status

Visible time range

Description

Normal status

[FirstObservedTime, LastObservedTime + KeepAliveSeconds)

Includes the keep-alive extension.

Expired status (after [FirstObservedTime, LastObservedTime) is called)

[FirstObservedTime, LastObservedTime)

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 to true.

  • Updates __last_observed_time__.

  • KeepAliveSeconds is 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:

  1. ELT Data Transformation

  2. Scheduled SQL

  3. Direct API or SDK reporting

Important considerations

  1. Data consistency: __domain__, __entity_type__, and __entity_id__ must remain consistent throughout an entity's lifecycle.

  2. Timestamp management: Use Unix timestamps in seconds for all time fields. UTC is recommended.

  3. Method selection: Choose the appropriate method for your use case. Use Delete with extreme caution.

  4. Performance: Tune __keep_alive_seconds__ to balance data retention with query performance.

  5. JSON formatting: Serialize keys in JSON fields alphabetically to avoid unnecessary index rebuilds.

  6. Entity count: Limit each `EntitySet` to 10,000 entities and the total count to 1,000,000. Exceeding these limits degrades performance.