Skip to content

Production Performance Calculations

This document describes how GET /api/v1/production-performance derives its metrics. API usage: Production Performance API.

Data sources

Source Collection / location Used for
Project structure projects Scope resolution, embedded production_stage_operation events
Tenant machines machines Machine ID guard for alarm queries
Alarm timeline alarms Net/stop duration intervals

All reads are scoped to the resolved tenant. Alarm queries additionally restrict to tenant machine IDs.

Time window

When start_time and end_time are supplied:

  • Both must be valid RFC 3339 timestamps (offsets accepted, normalized to UTC)
  • start_time must be strictly before end_time
  • The window is [effective_start_time, effective_end_time) — events at effective_end_time are excluded

When omitted:

  1. effective_end_time = current UTC time at request processing
  2. effective_start_time is resolved in order:
  3. Project start_date when present
  4. Earliest embedded operation event timestamp for the active scope
  5. Earliest alarm timestamp for the active scope and tenant machines
  6. Fallback to effective_end_time when no earlier signal exists

Scope and independent metrics

Metrics are calculated separately for each returned level:

Level Events included
Project All productions and stages under the project
Production Only the selected production
Production stage Only the selected stage

Operation events are flattened from embedded production_stage_operation arrays on matching stages. Alarm events are loaded for the scope with a tenant machine $in guard.

Duration truncation

All duration outputs are int64 seconds. Conversion uses:

text int64(duration / time.Second)

Fractional sub-second remainders are truncated toward zero. Clipped interval math applies the same rule after intersecting segments with the active window.

Operation time (total_operation_time_seconds)

Source: embedded production_stage_operation records (event_case, event_time, machine identity).

Per machine group (by machine ID, else normalized machine name):

Event case Effect
operation_start Opens an active interval when none is open
operation_break Closes the active interval
operation_end Closes the active interval

Rules:

  • Only one active interval per machine at a time; a second operation_start while already active is ignored
  • Intervals open at request time remain open until operation_break, operation_end, or the window end
  • Each closed segment is clipped to the window before summation

total_operation_time_seconds is the sum across all machine groups.

Alarm durations

Source: alarms documents (event_type, type_code, timestamp, machine identity).

Events are grouped per machine, sorted by (timestamp ASC, _id ASC). The calculator also loads the latest alarm before effective_start_time per machine to establish initial state inside the window.

State transitions

event_type Resulting state Notes
start Net operation
stop Stop type_code classifies planned / unplanned / failure
reconnecting No active state Contributes zero duration. Legacy aliases (reconnect, re-connect, re_connect, any case) normalize to this canonical value.
Other / unknown No active state

Stop classification uses normalized type_code:

Canonical type_code Bucket
planned planned_stop_time_seconds
unplanned unplanned_stop_time_seconds
failure failure_stop_time_seconds

Between consecutive in-window events (and from window start through window end), elapsed time in each state is clipped to the window and added to:

  • net_operation_time_seconds
  • stop_time_seconds (total)
  • The matching planned/unplanned/failure subset

reconnecting clears the previous start or stop interval at its own timestamp without adding time to net or stop totals.

Product metrics (product_metrics)

Source: product_operations entries attached to in-window operation events.

For each product key (prefer product_id, else product_code):

Counter Source field
successful_count success_count
revised_count revise_count
scrap_count fire_count
total_count Sum of the three counters

Negative source values are treated as zero. Results are sorted by product_code, then product_id.

When no in-window product operations exist, product_metrics is an empty array.

Zero-data behavior

When a project exists but the window contains no qualifying operation or alarm events:

  • HTTP 200
  • All duration fields return 0
  • product_metrics returns []

404 responses apply only when the project, production, or stage entity cannot be found for the tenant.

Normalization

event_type, type_code, and operation event_case values pass through the shared normalizer (internal/outbound/normalize):

  • Trim, lowercase, spaces/hyphens → underscores
  • Known aliases map to canonical snake_case forms
  • Alarm event_type canonical values are only start, stop, and reconnecting (reconnect variants map to reconnecting)

This keeps calculation and API output consistent regardless of source casing.

Alarm read performance relies on migration-managed non-unique indexes:

  • ix_alarms_machine_timestamp_id_desc
  • ix_alarms_project_production_stage_machine_timestamp_id

These are created by the migration CLI, not during API requests.