Metrics as Ontology: Unifying Business KPIs and Operational Monitoring
Traditional approach: Metrics and business data are two separate worlds
CoomiaPublished on August 14, 202515 min read
Share this articleTwitter / X
Metrics as Ontology: Unifying Business KPIs and Operational Monitoring
“Series: S4 Ontology Modeling · Article 10 | Level: Intermediate | Reading Time: 18 min
#TL;DR
- Metrics are no longer a separate system — coomia-dip unifies monitoring metrics (CPU, latency, error rate) and business KPIs (revenue, conversion rate, customer satisfaction) into the Ontology model, making them first-class citizen properties of ObjectTypes.
- MetricSource defines collection, aggregation, and storage rules — each metric declares its data source (Prometheus, business database, event stream), aggregation method (SUM/AVG/P99), and time granularity (second/minute/hour/day), with the system handling collection and materialization automatically.
- A unified query interface lets users query "what's this service's P99 latency" and "what's this customer's monthly spend" in the same API call, breaking down the data silo between technical monitoring and business analytics.
#1. Why Metrics Should Be Part of the Ontology
#1.1 Data Silos in Traditional Architecture
Code
Traditional approach: Metrics and business data are two separate worlds
World 1: Technical Monitoring
Prometheus → Grafana
├── CPU utilization
├── Memory usage
├── Request latency P99
├── Error rate
└── Stored in time-series database (separate data model)
World 2: Business Analytics
MySQL/PostgreSQL → BI Dashboard
├── Daily active users
├── Order conversion rate
├── Customer lifetime value
├── Revenue growth rate
└── Stored in relational database (another data model)
Problems:
├── "When order system latency spikes, how much does conversion drop?"
│ → Requires manual correlation across two systems
├── "Which customers were affected by yesterday's outage?"
│ → Requires cross-system queries with manual matching
├── "Is there a correlation between service error rate and refund rate?"
│ → Requires exporting data to Excel for manual analysis
└── Every analysis becomes a "data archaeology" expedition
#1.2 The coomia-dip Unified Model
Code
coomia-dip approach: Metrics are ObjectType properties
ObjectType: OrderService
Regular properties:
serviceId: STRING
serviceName: STRING
version: STRING
Metric properties:
cpuUsage: METRIC(gauge, source=prometheus)
requestLatencyP99: METRIC(histogram, source=prometheus)
errorRate: METRIC(gauge, source=prometheus)
orderCount: METRIC(counter, source=business_db)
conversionRate: METRIC(gauge, source=computed)
revenue: METRIC(counter, source=business_db)
Unified query:
GET /api/v1/objects/OrderService/svc-001
{
"serviceId": "svc-001",
"serviceName": "order-service",
"cpuUsage": 67.3,
"requestLatencyP99": 245,
"errorRate": 0.02,
"orderCount": 15234,
"conversionRate": 0.034,
"revenue": 1523400.00
}
Technical monitoring and business data on the same object!
No cross-system queries needed, direct correlation analysis.
#2. MetricSource: Definition and Collection
#2.1 MetricSource Model
Code
MetricSource definition:
┌─────────────────────────────────────────────────────┐
│ MetricSource │
├─────────────────────────────────────────────────────┤
│ metricId: STRING # Unique identifier │
│ name: STRING # Human-readable name │
│ description: STRING # Description │
│ metricType: ENUM # COUNTER / GAUGE / │
│ # HISTOGRAM / SUMMARY │
│ unit: STRING # Unit (ms, %, bytes) │
│ source: MetricDataSource # Data source def │
│ aggregation: AggregationRule # Aggregation rules │
│ retention: RetentionPolicy # Data retention │
│ alertRules: List[AlertRule] # Alert rules │
└─────────────────────────────────────────────────────┘
MetricDataSource:
├── type: PROMETHEUS / DATABASE / EVENT_STREAM / COMPUTED
├── query: STRING (PromQL / SQL / Expression)
├── refreshInterval: DURATION (collection interval)
├── timeout: DURATION (collection timeout)
└── labels: Map<String, String> (label mapping)
AggregationRule:
├── function: SUM / AVG / MIN / MAX / P50 / P90 / P95 / P99 / COUNT
├── timeWindows: List[DURATION] (1m, 5m, 1h, 1d, 7d, 30d)
├── groupBy: List[STRING] (grouping dimensions)
└── fillPolicy: ZERO / NULL / PREVIOUS / LINEAR_INTERPOLATION
RetentionPolicy:
├── rawRetention: DURATION (raw data retention)
├── minuteRetention: DURATION (minute granularity retention)
├── hourRetention: DURATION (hour granularity retention)
├── dayRetention: DURATION (day granularity retention)
└── downsampleEnabled: BOOLEAN (auto-downsampling)
#2.2 Prometheus Data Source
Code
Collecting technical metrics from Prometheus:
metricSource:
metricId: "order_service_latency_p99"
name: "Order Service P99 Latency"
metricType: HISTOGRAM
unit: "ms"
source:
type: PROMETHEUS
query: |
histogram_quantile(0.99,
rate(http_request_duration_seconds_bucket{
service="order-service",
instance="{{instanceId}}"
}[5m])
) * 1000
refreshInterval: 15s
timeout: 5s
labels:
instanceId: "{{objectId}}" # Maps to ObjectType instance
aggregation:
function: P99
timeWindows: [1m, 5m, 15m, 1h, 6h, 1d]
fillPolicy: PREVIOUS
retention:
rawRetention: 7d
minuteRetention: 30d
hourRetention: 365d
dayRetention: 3y
Collection flow:
1. Execute PromQL query every 15 seconds
2. Associate results with corresponding ObjectType instances
3. Store raw values in time-series storage
4. Auto-aggregate to each time window
5. Expired data auto-downsampled
#2.3 Business Database Data Source
Code
Collecting business metrics from databases:
metricSource:
metricId: "customer_monthly_revenue"
name: "Customer Monthly Revenue"
metricType: COUNTER
unit: "USD"
source:
type: DATABASE
query: |
SELECT
customer_id,
SUM(total_amount) as monthly_revenue
FROM orders
WHERE customer_id = '{{objectId}}'
AND created_at >= DATE_TRUNC('month', CURRENT_DATE)
AND status = 'COMPLETED'
GROUP BY customer_id
refreshInterval: 5m
timeout: 30s
aggregation:
function: SUM
timeWindows: [1h, 1d, 7d, 30d]
groupBy: ["productCategory"]
fillPolicy: ZERO
retention:
rawRetention: 30d
hourRetention: 365d
dayRetention: 5y
#2.4 Computed Data Source
Code
Derived metrics computed from other metrics:
metricSource:
metricId: "order_conversion_rate"
name: "Order Conversion Rate"
metricType: GAUGE
unit: "%"
source:
type: COMPUTED
expression: |
(metric("completed_orders", window="1h") /
metric("page_views", window="1h")) * 100
refreshInterval: 1m
dependencies:
- "completed_orders"
- "page_views"
aggregation:
function: AVG
timeWindows: [5m, 15m, 1h, 1d]
fillPolicy: LINEAR_INTERPOLATION
Note: Difference between computed metrics and derived properties
├── Derived properties: computed from object attributes, return single value
├── Computed metrics: computed from time-series data, return time series
├── Derived property: SUM(LineItem.lineTotal) → one number
└── Computed metric: completedOrders/pageViews → one data point per minute
#3. Time-Series Storage
#3.1 Multi-Granularity Storage Architecture
Code
Layered storage for time-series data:
┌─────────────────────────────────────────────────┐
│ Time-Series Storage Architecture │
│ │
│ Hot Storage (last 24h) │
│ ├── Raw granularity (15s sampling interval) │
│ ├── Storage: Memory + SSD │
│ └── Query latency: < 10ms │
│ │
│ Warm Storage (1d ~ 30d) │
│ ├── Minute granularity (1m aggregation) │
│ ├── Storage: SSD │
│ └── Query latency: < 100ms │
│ │
│ Cold Storage (30d ~ 1y) │
│ ├── Hour granularity (1h aggregation) │
│ ├── Storage: HDD / Object Storage │
│ └── Query latency: < 1s │
│ │
│ Archive Storage (> 1y) │
│ ├── Day granularity (1d aggregation) │
│ ├── Storage: Object Storage (S3/MinIO) │
│ └── Query latency: < 10s │
└─────────────────────────────────────────────────┘
Auto downsampling:
Raw → Minute: take AVG/MIN/MAX/P99 per minute
Minute → Hour: take AVG/MIN/MAX/P99 per hour
Hour → Day: take AVG/MIN/MAX/P99 per day
Downsampling preserves multiple aggregation values for different queries:
"Average CPU over last hour" → use minute granularity AVG
"Peak CPU over last hour" → use minute granularity MAX
"P99 latency trend over 30 days" → use hour granularity P99
#3.2 Time-Series Data Model
Code
TimeSeriesPoint:
┌─────────────────────────────────────────────────┐
│ TimeSeriesPoint │
├─────────────────────────────────────────────────┤
│ metricId: STRING # Metric identifier │
│ objectId: STRING # Associated instance │
│ timestamp: TIMESTAMP # Timestamp │
│ value: DOUBLE # Metric value │
│ labels: Map # Additional labels │
│ granularity: ENUM # RAW/MIN/HOUR/DAY │
│ aggregations: Map # Aggregated values │
│ avg: DOUBLE │
│ min: DOUBLE │
│ max: DOUBLE │
│ p50: DOUBLE │
│ p99: DOUBLE │
│ count: LONG │
│ sum: DOUBLE │
└─────────────────────────────────────────────────┘
Storage example:
metricId: "cpu_usage"
objectId: "server-001"
timestamp: "2025-01-15T10:30:00Z"
granularity: MINUTE
aggregations:
avg: 67.3
min: 45.2
max: 89.1
p99: 87.5
count: 4 # 4 raw data points in 1 minute
sum: 269.2
#4. Unified Query Interface
#4.1 Single Object Metric Query
Code
API: GET /api/v1/objects/{objectTypeId}/{objectId}/metrics
Query parameters:
metrics: cpu_usage,request_latency_p99,error_rate
from: 2025-01-15T00:00:00Z
to: 2025-01-15T12:00:00Z
granularity: 1h
aggregation: avg
Response:
{
"objectId": "svc-001",
"objectType": "OrderService",
"timeRange": {
"from": "2025-01-15T00:00:00Z",
"to": "2025-01-15T12:00:00Z"
},
"granularity": "1h",
"metrics": {
"cpu_usage": {
"unit": "percent",
"dataPoints": [
{"timestamp": "2025-01-15T00:00:00Z", "value": 23.5},
{"timestamp": "2025-01-15T01:00:00Z", "value": 21.8},
{"timestamp": "2025-01-15T02:00:00Z", "value": 19.2},
...
]
},
"request_latency_p99": {
"unit": "ms",
"dataPoints": [
{"timestamp": "2025-01-15T00:00:00Z", "value": 145.3},
{"timestamp": "2025-01-15T01:00:00Z", "value": 132.7},
...
]
},
"error_rate": {
"unit": "percent",
"dataPoints": [
{"timestamp": "2025-01-15T00:00:00Z", "value": 0.01},
{"timestamp": "2025-01-15T01:00:00Z", "value": 0.02},
...
]
}
}
}
#4.2 Cross-Object Metric Aggregation
Code
API: POST /api/v1/objects/{objectTypeId}/metrics/aggregate
Request:
{
"filter": {
"region": "us-east-1",
"environment": "production"
},
"metrics": ["cpu_usage", "request_latency_p99"],
"aggregation": "avg",
"groupBy": ["serviceTeam"],
"from": "2025-01-15T00:00:00Z",
"to": "2025-01-15T12:00:00Z",
"granularity": "1h"
}
Response:
{
"groups": [
{
"key": {"serviceTeam": "payment-team"},
"metrics": {
"cpu_usage": {
"avg": 45.2,
"dataPoints": [...]
},
"request_latency_p99": {
"avg": 234.5,
"dataPoints": [...]
}
}
},
{
"key": {"serviceTeam": "order-team"},
"metrics": {
"cpu_usage": {
"avg": 67.8,
"dataPoints": [...]
},
"request_latency_p99": {
"avg": 189.3,
"dataPoints": [...]
}
}
}
]
}
#4.3 Hybrid Query (Properties + Metrics)
Code
API: POST /api/v1/objects/{objectTypeId}/query
Request:
{
"select": ["serviceName", "version", "cpu_usage", "revenue"],
"filter": {
"cpu_usage.avg(1h)": {">": 80},
"environment": "production"
},
"timeRange": {
"from": "2025-01-15T00:00:00Z",
"to": "2025-01-15T12:00:00Z"
},
"orderBy": [{"cpu_usage.avg(1h)": "DESC"}],
"limit": 10
}
Response:
{
"results": [
{
"objectId": "svc-003",
"serviceName": "payment-service",
"version": "2.1.0",
"cpu_usage": {"avg_1h": 92.3, "current": 88.7},
"revenue": {"sum_24h": 234567.89}
},
{
"objectId": "svc-001",
"serviceName": "order-service",
"version": "3.0.1",
"cpu_usage": {"avg_1h": 85.1, "current": 82.4},
"revenue": {"sum_24h": 523456.12}
}
]
}
This query means:
"Find production services with CPU usage above 80%, show their revenue"
→ One query gets both technical metrics and business data
→ No cross-system correlation needed
#5. Alert Rules and Ontology Integration
#5.1 Metric-Based Alerts
Code
Alert rule definition:
alertRule:
ruleId: "alert-cpu-high"
name: "High CPU Usage"
metric: "cpu_usage"
condition:
operator: ">"
threshold: 85
duration: 5m # Trigger after 5 minutes
aggregation: avg
severity: WARNING
actions:
- type: NOTIFY
channels: ["slack:#ops-alerts", "email:oncall@company.com"]
- type: CREATE_ACTION
actionType: "ScaleUpService"
parameters:
targetReplicas: "{{current_replicas + 2}}"
Alert + Ontology integration:
Traditional alert: CPU > 85% → send notification
coomia-dip alert: CPU > 85% → send notification
+ Query the service's related ObjectTypes
+ Find affected business processes
+ Assess business impact (estimated revenue loss)
+ Auto-trigger scale-up Action
Alert context example:
┌────────────────────────────────────────────────────┐
│ ALERT: High CPU Usage │
│ │
│ Service: order-service (svc-001) │
│ CPU: 92.3% (avg over 5min) │
│ Duration: 7 minutes │
│ │
│ Business Impact (via Ontology): │
│ ├── Request Latency P99: 450ms (normal: 150ms) │
│ ├── Error Rate: 3.2% (normal: 0.1%) │
│ ├── Affected Orders: ~1,200 in last 5 min │
│ ├── Estimated Revenue Impact: $6,000/hour │
│ ├── Affected Customers: 340 (12 VIP) │
│ └── Related Downstream: payment-service, sms-svc │
│ │
│ Auto Action: ScaleUpService triggered │
│ Target: 3 → 5 replicas │
└────────────────────────────────────────────────────┘
#5.2 Business Metric Alerts
Code
Not just technical metrics — business KPIs can have alerts too:
alertRule:
ruleId: "alert-conversion-drop"
name: "Conversion Rate Anomaly Drop"
metric: "conversion_rate"
condition:
type: ANOMALY_DETECTION
baseline: "same_hour_last_week"
deviationThreshold: -30% # 30% lower than same time last week
duration: 15m
severity: CRITICAL
actions:
- type: NOTIFY
channels: ["slack:#business-alerts"]
- type: CORRELATE
correlateWith: ["error_rate", "latency_p99", "deployment_events"]
timeWindow: 1h
Automatic correlation analysis for business alerts:
Conversion rate drops 30%
→ Auto-query technical metrics for the same period
→ Discover error_rate rose from 0.1% to 3.2%
→ Discover a deployment occurred 30 minutes ago
→ Auto-generate correlation report
Correlation report:
"Conversion rate drop likely related to order-service v3.0.1 deployment
30 minutes ago. Error rate increased 32x post-deployment.
Recommend rollback to v3.0.0."
#6. Metric-Driven Derived Properties
#6.1 Derived Properties Based on Metrics
Code
Metrics can participate in derived property computation:
ObjectType: Service
metrics:
cpuUsage: METRIC(gauge)
memoryUsage: METRIC(gauge)
errorRate: METRIC(gauge)
latencyP99: METRIC(histogram)
derivedProperties:
healthScore: DERIVED
expression: |
100
- (IF(metric("cpuUsage", "avg", "5m") > 80, 20, 0))
- (IF(metric("memoryUsage", "avg", "5m") > 85, 20, 0))
- (IF(metric("errorRate", "avg", "5m") > 1, 30, 0))
- (IF(metric("latencyP99", "avg", "5m") > 500, 30, 0))
evaluationMode: REALTIME
refreshInterval: 1m
riskLevel: DERIVED
expression: |
CASE
WHEN healthScore >= 80 THEN "LOW"
WHEN healthScore >= 50 THEN "MEDIUM"
WHEN healthScore >= 20 THEN "HIGH"
ELSE "CRITICAL"
END
Effect:
Service healthScore auto-recomputed every minute
Real-time health assessment across 4 dimensions
riskLevel auto-updates with healthScore
All consumers see a unified health view
#6.2 Cross-Object Metric Aggregation Derived Properties
Code
Higher-level objects aggregate lower-level object metrics:
ObjectType: ServiceCluster
derivedProperties:
avgCpuUsage: DERIVED
reducer: AVG
sourceObjectType: Service
sourceMetric: cpuUsage
aggregation: avg
timeWindow: 5m
maxLatencyP99: DERIVED
reducer: MAX
sourceObjectType: Service
sourceMetric: latencyP99
aggregation: p99
timeWindow: 5m
totalErrorCount: DERIVED
reducer: SUM
sourceObjectType: Service
sourceMetric: errorCount
aggregation: sum
timeWindow: 1h
clusterHealthScore: DERIVED
expression: |
100
- (IF(avgCpuUsage > 75, 15, 0))
- (IF(maxLatencyP99 > 300, 25, 0))
- (IF(totalErrorCount > 100, 30, 0))
- (IF(unhealthyServiceCount > 0, 30, 0))
Hierarchy:
Company
└── ServiceCluster (aggregates Service metrics)
└── Service (aggregates Instance metrics)
└── Instance (raw metrics)
Each level shows aggregated health:
CEO sees Company level: one number
CTO sees Cluster level: health per cluster
SRE sees Service level: service details
Ops sees Instance level: instance details
#7. Metrics Access Control
#7.1 Metric-Level Permissions
Code
Different roles see different metrics:
Permission matrix:
┌──────────────────┬──────────┬──────────┬──────────┬──────────┐
│ Role │ Tech │ Business │ Finance │ User │
│ │ Metrics │ KPIs │ Metrics │ Metrics │
├──────────────────┼──────────┼──────────┼──────────┼──────────┤
│ SRE/Ops │ Full │ Read │ None │ None │
│ Product Manager │ Summary │ Full │ Read │ Agg only │
│ Data Analyst │ Read │ Full │ Full │ Agg only │
│ Executive │ Summary │ Summary │ Full │ Summary │
│ External Partner │ None │ Limited │ None │ None │
└──────────────────┴──────────┴──────────┴──────────┴──────────┘
Permission control granularity:
├── Metric visibility (can you see this metric exists)
├── Time range (last 7 days only vs full history)
├── Granularity (hour granularity only vs raw)
├── Aggregation (aggregated values only vs detail)
└── Object scope (own team's only vs all)
#8. Metrics and Action Integration
#8.1 Metrics Triggering Actions
Code
Metric changes automatically trigger Ontology Actions:
Scenario 1: Auto scale-up
metric: cpuUsage > 80% for 5m
→ Action: ScaleUpService(replicas += 2)
Scenario 2: Auto circuit-breaker
metric: errorRate > 5% for 2m
→ Action: EnableCircuitBreaker(service=order-service)
→ Action: NotifyOnCall(severity=P1)
Scenario 3: Business response
metric: conversionRate < baseline * 0.7 for 15m
→ Action: CreateIncident(type=BUSINESS_ANOMALY)
→ Action: TriggerRCA(correlateMetrics=[errorRate, latency, deployments])
Scenario 4: Cost optimization
metric: cpuUsage < 20% for 24h
→ Action: ScaleDownService(replicas -= 1)
→ Action: NotifyOwner("Consider downsizing this service")
All defined through Ontology ActionTypes,
inheriting all ActionType capabilities:
├── Approval workflows
├── Pre-checks (Guards)
├── Audit logging
├── Rollback mechanisms
└── Access control
#9. Practical Example: Building a Unified Monitoring Model
#9.1 E-Commerce Platform Monitoring Model
Code
E-commerce platform unified Ontology monitoring model:
ObjectType: EcommerceService
Properties:
serviceId, serviceName, team, environment
Technical metrics:
cpuUsage, memoryUsage, diskUsage
requestCount, requestLatency, errorRate
connectionPoolUsage, threadPoolUsage
gcPauseTime, heapUsage
Business metrics:
orderCount, orderValue, conversionRate
cartAbandonRate, paymentSuccessRate
avgOrderValue, returnRate
Derived properties:
healthScore (based on technical metrics)
businessImpactScore (based on business metrics)
overallScore = healthScore * 0.6 + businessImpactScore * 0.4
ObjectType: EcommerceCluster
Derived metrics (aggregated from Services):
totalOrderValue = SUM(Service.orderValue)
avgHealthScore = AVG(Service.healthScore)
worstLatency = MAX(Service.requestLatency)
totalErrorCount = SUM(Service.errorCount)
ObjectType: EcommercePlatform (top-level singleton)
Derived metrics (aggregated from Clusters):
platformGMV = SUM(Cluster.totalOrderValue)
platformHealthScore = AVG(Cluster.avgHealthScore)
platformAvailability = 1 - (Cluster.totalErrorCount / Cluster.totalRequestCount)
Three-layer model value:
Platform → "What's today's platform GMV? Overall health?"
Cluster → "Which cluster has issues? How many orders affected?"
Service → "Which service has high CPU? Why is latency high?"
#9.2 Auto-Generated Metric Dashboards
Code
Auto-generate Grafana Dashboard from Ontology model:
API: POST /api/v1/ontology/metrics/dashboard/generate
Request:
{
"objectTypeId": "EcommerceService",
"objectId": "svc-001",
"layout": "standard",
"includeMetrics": ["*"],
"includeRelated": true
}
Auto-generated Dashboard structure:
┌─────────────────────────────────────────────────┐
│ EcommerceService: order-service │
├─────────────────────────────────────────────────┤
│ Overview Row: │
│ [Health Score] [Risk Level] [Uptime] │
│ │
│ Technical Metrics Row: │
│ [CPU] [Memory] [Disk] [GC Pause] │
│ │
│ Request Metrics Row: │
│ [Request Rate] [Latency P99] [Error Rate] │
│ │
│ Business Metrics Row: │
│ [Order Count] [Conversion Rate] [Revenue] │
│ │
│ Related Services Row: │
│ [payment-svc health] [inventory-svc health] │
│ │
│ Alerts Row: │
│ [Active Alerts] [Recent Incidents] │
└─────────────────────────────────────────────────┘
Dashboard stays in sync with Ontology model:
├── ObjectType adds metric → Dashboard adds panel automatically
├── ObjectType removes metric → Dashboard removes panel automatically
├── New Service instance → Instance dashboard auto-generated
└── Relation changes → Related Services panel auto-updated
#10. Comparison with Traditional Approaches
Code
Metrics-as-Ontology vs traditional monitoring:
┌──────────────┬─────────────────────┬──────────────────────┐
│ Feature │ coomia-dip │ Prometheus + Grafana │
├──────────────┼─────────────────────┼──────────────────────┤
│ Tech monitor │ Built-in │ Core capability │
│ Business KPI │ Unified model │ Separate system │
│ Correlation │ Auto (Ontology) │ Manual │
│ Alert context│ Business impact │ Pure technical │
│ Access ctrl │ Property-level │ Dashboard-level │
│ Auto Action │ ActionType-driven │ Needs AlertManager │
│ History │ Versioned │ Overwrite │
│ Governance │ Ontology governance │ None │
│ Dashboards │ Auto-generated │ Manual config │
│ Learning │ Medium (Ontology) │ Low (PromQL) │
└──────────────┴─────────────────────┴──────────────────────┘
coomia-dip does not replace Prometheus:
├── Prometheus remains the best tool for collection and storage
├── coomia-dip builds an Ontology model on top of Prometheus
├── Unifies technical metrics and business data in one query interface
├── Uses Ontology relations and derived properties for auto-correlation
└── Elevates "monitoring" from a purely technical view to a business view
#Key Takeaways
- Metrics in the Ontology breaks the silo between tech monitoring and business analytics — a single ObjectType has both regular properties and metric properties, one query retrieves "service latency" and "business revenue" together, no cross-system correlation needed.
- MetricSource unifies metric definition and collection — whether data comes from Prometheus, business databases, or computed expressions, all use the same model definition and same query API. Consumers never need to know the data source.
- Metric-Ontology integration creates new value — alerts are no longer isolated "CPU is high" messages but come with full business context: "CPU is high, affecting 1,200 orders, estimated loss $6,000/hour."
- Multi-layer aggregation serves different roles — Instance to Service to Cluster to Platform, each layer auto-aggregates child metrics. CEO sees global health, SRE sees specific instances.
- Metrics triggering Actions creates closed-loop automation — not just seeing problems (alerts) but auto-handling them (scale up, circuit break, create incident), leveraging ActionType mechanisms for approval, audit, and rollback.
#Next Article
The next article S4-11 Data Onboarding discusses how to map external data sources into the Ontology model — CSV files, database tables, API endpoints, message queues — how to define mapping rules, handle data quality issues, and implement incremental synchronization.
#ontology #metrics #monitoring #time-series #kpi #alerting #observability #business-metrics #unified-model