Back to Blog

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

  1. 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.
  2. 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.
  3. 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."
  4. 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.
  5. 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