# `nupp.profile.trace`
Stable identities shared by static trace checking and the opt-in runtime
collector.
The recorder's strings are presentation, not API. A trace event is first
interpreted under the exact VM profile that emitted it, then mapped to one of
the identities here. Static checks use those same records, which is what keeps a
bytecode finding, an `@jit` contract error and an observed abort from acquiring
three explanations.
```nupp
local trace = nupp.profile.trace
local reason = trace.forOpcode("FNEW")
print(reason.id, reason.repair)
```
See [LuaJIT trace checking](../../../../learn/performance/jit-trace-checking/index.html) for the static side of this, and
`nupp.profile` for the collector that reports the runtime side.
## Types
### `Profile` _type_
```nupp
type trace.Profile = {
id: string,
luajitRevision: string,
luajitVersion: integer,
architecture: string,
operatingSystem: string,
enabledRecorderFeatures: {string},
bytecodeSchema: string,
supported: boolean
}
```
The recorder a trace event has to be interpreted under.
Reasons are mapped from VM text and bytecode numbering, and both move between
builds, so an event is only comparable to another taken under the same `id`.
### `Reason` _type_
```nupp
type trace.Reason = {
id: string,
class: 'blocker' | 'risk' | 'stop',
opcodes: {[string]: boolean}?,
source: {[string]: boolean}?,
runtime: {string}?,
explanation: string?,
repair: string?,
lint: string?,
contractSeverity: string?
}
```
One stable reason the JIT declined to record, however it was observed.
`class` is what the reason is worth acting on: a `blocker` cannot record at
all, a `risk` may or may not sit on a hot path, and a `stop` is trace formation
working as designed. The three index fields are the routes to it, from a
bytecode name, from a static finding, and from the VM's own runtime text.
## Functions
### `trace.forOpcode` _function_
```nupp
function trace.forOpcode(opcode: string): trace.Reason?
```
Answers the record for a bytecode LuaJIT has no recorder for.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `opcode` | `string` | the bytecode's name, as `opcodeName` renders it |
#### Returns
| Type | Description |
| --- | --- |
| `trace.Reason?` | the record, or nil when that bytecode records |
### `trace.forSource` _function_
```nupp
function trace.forSource(source: string): trace.Reason?
```
Answers the record a static finding maps to.
This is what keeps a checker finding and an observed abort from explaining the
same thing two different ways.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `source` | `string` | the static finding's name |
#### Returns
| Type | Description |
| --- | --- |
| `trace.Reason?` | the record, or nil when the finding has no runtime counterpart |
### `trace.opcodeName` _function_
```nupp
function trace.opcodeName(opcode: integer): string
```
Renders a bytecode number as the name LuaJIT knows it by.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `opcode` | `integer` | the number the VM reported |
#### Returns
| Type | Description |
| --- | --- |
| `string` | the trimmed name |
### `trace.profile` _function_
```nupp
function trace.profile(): trace.Profile
```
Describes the recorder this process is running.
#### Returns
| Type | Description |
| --- | --- |
| `trace.Profile` | the profile every event from this process is interpreted under |
### `trace.reason` _function_
```nupp
function trace.reason(id: string): trace.Reason?
```
Answers the record filed under one stable identity.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `id` | `string` | the identity, as a report or a diagnostic carries it |
#### Returns
| Type | Description |
| --- | --- |
| `trace.Reason?` | the record, or nil when nothing is filed under it |
### `trace.records` _function_
```nupp
function trace.records(): {trace.Reason}
```
Answers every record, in registry order.
The list is a copy, so a caller sorting or filtering it cannot disturb the
registry the checker reads.
#### Returns
| Type | Description |
| --- | --- |
| `{trace.Reason}` | one entry per known reason |
### `trace.runtime` _function_
```nupp
function trace.runtime(errorCode: integer?, errorArg: number | string | nil): trace.Reason, string
```
Interprets one raw abort the VM reported.
An abort naming an unrecordable bytecode is routed by that opcode rather than
by its text, so it lands on the same record a static check would have found.
Anything unrecognized answers `jit/runtime-unknown` rather than nothing.
#### Arguments
| Name | Type | Description |
| --- | --- | --- |
| `errorCode` | `integer?` | the VM's trace error number, or nil |
| `errorArg` | `number | string | nil` | whatever the VM passed beside it |
#### Returns
| Type | Description |
| --- | --- |
| `trace.Reason` | the record it maps to |
| `string` | the rendered text, for display |