Runtime sources
This page lists exactly what a traces Source and a newrelic Source read and keep.
Trace fields
Section titled “Trace fields”Vellum reads a trace export as a stream of JSON tokens. For each span it holds these values in memory until the end of the read, and no other value:
| Value | OTLP and Tempo | Jaeger |
|---|---|---|
| Trace ID, span ID | traceId, spanId |
traceID, spanID |
| Parent | parentSpanId |
parentSpanID, or a CHILD_OF reference |
| Links | links[].traceId, links[].spanId |
FOLLOWS_FROM references |
| Service | resource attribute service.name |
processes[].serviceName or process.serviceName |
| Operation | name |
operationName |
| Span kind | kind (number or SPAN_KIND_*) |
tag span.kind |
| Peer | attribute peer.service, else server.address |
tag peer.service, else server.address |
| Status | status.code is error |
tag error is true, or otel.status_code is ERROR |
| Time | startTimeUnixNano, endTimeUnixNano |
startTime, duration |
Vellum drops everything else: every other span attribute and tag, every event and log, the status message, every other resource attribute, the scope, and the span IDs themselves once the edges are derived. It keeps no raw span. The uploaded file is not written anywhere.
A service, operation or peer name with a control character, an e-mail address or the shape of a credential is not kept. A span whose service name is not kept is dropped; the header counts them as spansDropped. An operation name that is not kept is counted as operationsRedacted. A name is cut at 200 characters.
The derived document
Section titled “The derived document”The only file of a runtime Snapshot is a document that Vellum writes: one JSON object per line.
- Line 1 is the header:
format(vellum.runtime.v1),complete,kind, and for tracesfile,exportFormat,spansandwindow; for New Relicaccount,region,entitiesandrelationships. - Then one line per service, ordered by key:
typeservice,key,name,truthLabeland its attributes. A New Relicdomain,typeorentityTypethat is not an upper-case word is written asunknown. - Then one line per edge, ordered by key:
typeinteraction,key,from,to,label,truthLabeland its attributes.
A citation names the line of its fact. The Snapshot ID is the SHA-256 of the lines after the header. The same services and edges give the same Snapshot ID, whatever the format of the export and whatever the file name.
| Fact | Key | External key |
|---|---|---|
| Trace service | service:<name> |
the key |
| Trace call edge | call:<from>-><to> |
— |
| Trace messaging edge | messaging:<from>-><to> |
— |
| New Relic entity | its GUID | the GUID |
| New Relic relationship | <TYPE>:<source GUID>-><target GUID> |
— |
Bounds of a trace upload
Section titled “Bounds of a trace upload”| Bound | Value | On reaching it |
|---|---|---|
| File size | 256 MiB | 413 trace_too_large |
| Spans | 1,000,000 | 413 trace_too_many_spans |
| Services | 2,000 | 413 trace_too_many_services |
| Edges | 10,000 | 413 trace_too_many_edges |
| One JSON value | 1 MiB | 413 trace_token_too_large |
| Nesting depth | 64 | 400 trace_malformed |
| Links or references of one span | 128 | 413 trace_too_many_links |
| Operations of one edge | 50 | the rest are counted in sample.operationsLeftOut |
Every span counts toward the span bound as it is read, with or without an ID. A file name with a control character, an e-mail address or the shape of a credential is refused with 400; rename the file. A malformed file, including a string that is not valid UTF-8, gives 400 trace_malformed, a file of no known shape 400 trace_format_unknown, and a file with no span 400 trace_empty. A refused file stores nothing.
NerdGraph queries
Section titled “NerdGraph queries”A New Relic Source sends these queries to https://api.newrelic.com/graphql (US) or https://api.eu.newrelic.com/graphql (EU), with the key in the API-Key header. No setting and no request names another address. It sends no mutation.
The entity search, paged with nextCursor. The search text is accountId = <id> AND domainType IN ('APM-APPLICATION', 'EXT-SERVICE', 'BROWSER-APPLICATION', 'MOBILE-APPLICATION'):
query($query: String!, $cursor: String) { actor { entitySearch(query: $query) { results(cursor: $cursor) { nextCursor entities { guid name domain type entityType } } } }}The relationships of 25 entities at a time:
query($guids: [EntityGuid]!) { actor { entities(guids: $guids) { guid relatedEntities { nextCursor results { type source { entity { guid name domain type entityType } } target { entity { guid name domain type entityType } } } } } }}Each further page of one entity’s relationships uses entity(guid: $guid) { relatedEntities(cursor: $cursor) { … } } with the same fields. Test connection sends actor { account(id: $accountId) { id name } }.
| Bound | Value |
|---|---|
| Entities | 500 |
| Relationships of one entity | 500 |
| Relationships in all | 20,000 |
| Entity search pages | 10 |
| Further pages of related entities | 200 |
A cursor that comes back, or a page that adds nothing while it names a next cursor, ends the paging with the note limit:pages.
A read that reaches a bound, or that gets an answer with both data and errors, is partial. A partial read marks nothing stale.
| Answer | Result |
|---|---|
401 or 403, or an UNAUTHORIZED, FORBIDDEN or ACCESS_DENIED error |
The scan fails with newrelic_unauthorized. |
429, or a TOO_MANY_REQUESTS error |
The scan waits until Retry-After, or one minute. |
| No connection or a timeout | The scan fails with newrelic_unavailable. A resume tries again. |
5xx |
The scan fails with newrelic_error. A resume tries again. |