Skip to content

runtime-profile.json

runtime-profile.json captures runtime evidence from the legacy system. While static analysis reveals structure, runtime profiling reveals behavior — which code paths are actually used, which database queries are slow, and which functions are never called in production.

{
"collection": {
"collector": "opentelemetry",
"environment": "production",
"period": {
"start": "2026-01-01",
"end": "2026-01-31"
},
"evidenceTier": "production-apm"
},
"hotPaths": [
{
"endpoint": "/api/invoices",
"method": "GET",
"callCount": 48200,
"latency": {
"p50": 45,
"p95": 320,
"p99": 890
},
"context": "Invoicing"
},
{
"endpoint": "/api/accounts/balance",
"method": "GET",
"callCount": 31500,
"latency": {
"p50": 12,
"p95": 85,
"p99": 210
},
"context": "Accounts"
},
{
"endpoint": "/api/tax/calculate",
"method": "POST",
"callCount": 15800,
"latency": {
"p50": 120,
"p95": 780,
"p99": 2100
},
"context": "Tax"
}
],
"databasePatterns": {
"totalQueries": 2450000,
"nPlusOneDetected": [
{
"endpoint": "/api/invoices",
"pattern": "SELECT invoice; then N x SELECT line_items WHERE invoice_id = ?",
"occurrences": 48200,
"context": "Invoicing"
}
],
"slowQueries": [
{
"query": "SELECT * FROM gl_entries WHERE posting_date BETWEEN ? AND ? ORDER BY posting_date",
"avgDuration": 1200,
"callCount": 3200,
"context": "Accounts"
}
],
"queriesPerContext": {
"Invoicing": 890000,
"Accounts": 720000,
"Tax": 340000,
"Stock": 280000,
"HR": 120000,
"Assets": 100000
}
},
"deadCode": {
"unreachedEndpoints": [
{
"endpoint": "/api/legacy/import-csv",
"method": "POST",
"lastCalled": null,
"context": "Invoicing"
},
{
"endpoint": "/api/reports/quarterly-old",
"method": "GET",
"lastCalled": "2024-03-15",
"context": "Accounts"
}
],
"unreachedFunctions": [
{
"function": "recalculate_all_balances",
"file": "accounts/utils.py",
"lastCalled": null
},
{
"function": "export_to_tally",
"file": "integrations/tally.py",
"lastCalled": "2023-11-01"
}
],
"totalDeadLoc": 4200
},
"resourceUsage": {
"memory": {
"avgMb": 512,
"peakMb": 1840,
"peakEndpoint": "/api/reports/annual-summary"
},
"cpu": {
"avgPercent": 35,
"peakPercent": 92,
"peakEndpoint": "/api/tax/year-end-reconciliation"
}
}
}

Metadata about how and when the runtime data was collected.

FieldTypeRequiredDescription
collectorstringYesTool used: "opentelemetry", "datadog", "newrelic", "custom", "log-analysis"
environmentstringYesWhere data was collected: "production", "staging", "development"
periodobjectYesCollection time window
period.startstringYesISO 8601 date. Start of collection period.
period.endstringYesISO 8601 date. End of collection period.
evidenceTierstringYesConfidence level of the data. See Evidence Tiers.

Endpoints ranked by usage. Each entry represents a frequently called code path.

FieldTypeRequiredDescription
endpointstringYesURL path of the endpoint
methodstringYesHTTP method: "GET", "POST", "PUT", "DELETE", "PATCH"
callCountnumberYesTotal invocations during the collection period
latencyobjectYesResponse time percentiles in milliseconds
latency.p50numberYesMedian response time (ms)
latency.p95numberYes95th percentile response time (ms)
latency.p99numberYes99th percentile response time (ms)
contextstringNoBounded context this endpoint belongs to (matches domains.json)

Database query analysis from the collection period.

FieldTypeRequiredDescription
totalQueriesnumberYesTotal database queries during the collection period
nPlusOneDetectedarrayNoDetected N+1 query patterns
slowQueriesarrayNoQueries exceeding a threshold (default: 500ms)
queriesPerContextobjectNoQuery count grouped by bounded context
FieldTypeRequiredDescription
endpointstringYesEndpoint triggering the N+1 pattern
patternstringYesHuman-readable description of the query pattern
occurrencesnumberYesHow many times this pattern was triggered
contextstringNoBounded context
FieldTypeRequiredDescription
querystringYesSQL query (parameterized, no actual values)
avgDurationnumberYesAverage execution time in milliseconds
callCountnumberYesTotal executions during the collection period
contextstringNoBounded context

Code paths with zero or negligible usage in the collection period.

FieldTypeRequiredDescription
unreachedEndpointsarrayNoEndpoints with no calls during the collection period
unreachedFunctionsarrayNoFunctions with no invocations
totalDeadLocnumberNoEstimated lines of code in dead paths
FieldTypeRequiredDescription
endpointstringYesURL path
methodstringYesHTTP method
lastCalledstring | nullNoISO 8601 date of last known call, or null if never called
contextstringNoBounded context
FieldTypeRequiredDescription
functionstringYesFunction name
filestringYesFile path relative to project root
lastCalledstring | nullNoISO 8601 date of last known call, or null if never called

System resource consumption during the collection period.

FieldTypeRequiredDescription
memoryobjectNoMemory usage metrics
memory.avgMbnumberYesAverage memory usage in MB
memory.peakMbnumberYesPeak memory usage in MB
memory.peakEndpointstringNoEndpoint that triggered peak memory
cpuobjectNoCPU usage metrics
cpu.avgPercentnumberYesAverage CPU utilization (0-100)
cpu.peakPercentnumberYesPeak CPU utilization (0-100)
cpu.peakEndpointstringNoEndpoint that triggered peak CPU

Not all runtime data carries the same confidence. Data from production APM is more reliable than estimates from static analysis. The evidenceTier field communicates this.

TierConfidenceSourceUse Case
production-apmHighestAPM running in production for 30+ daysGold standard. Reflects actual user behavior.
staging-load-testHighLoad testing in staging environmentSimulated traffic. Good for latency and resource usage.
dev-profilingMediumDeveloper profiling sessionsLimited scenarios. Useful for identifying slow queries.
static-analysisLowestInferred from code structure (no runtime data)Fallback when no runtime access. Call counts are estimates.

When consuming runtime data, agents and tools should weight decisions based on the tier. A production-apm hot path ranking carries more authority than a static-analysis estimate.

Runtime profile data influences other spec files:

Source DataFeeds IntoHow
Hot pathscomplexity.jsonHotspot rankings incorporate actual usage, not just LOC or cyclomatic complexity
Dead codeextraction-plan.jsonDead endpoints deprioritized or skipped entirely
N+1 queriescomplexity.jsonDatabase anti-patterns increase complexity scores
Call countsparity-tests.jsonHigh-traffic paths get higher parity test coverage
Resource usageextraction-plan.jsonResource-heavy endpoints flagged for performance improvement during extraction

The recommended approach. Add the OpenTelemetry SDK to the legacy system and export traces to a collector.

Terminal window
# Example: Python legacy app with OTEL auto-instrumentation
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-instrument --traces_exporter otlp python app.py

Export traces as JSON files to the Modernizer’s profiling/traces/ directory, then process:

Terminal window
npx modernizespec profile --traces-dir ./profiling/traces/ --period 30d

When an AI agent discovers runtime-profile.json:

  1. Read the evidenceTier to understand data confidence
  2. Use hotPaths to prioritize which bounded contexts to work on first
  3. Check deadCode before extracting — dead endpoints can be skipped
  4. Review databasePatterns for N+1 queries that should be fixed during extraction
  5. Cross-reference with parity-tests.json to ensure hot paths have adequate test coverage