Skip to content

Commit 500c409

Browse files
xnanodaxniieaniyojenkins
authored
feat: update reporting functions to include a partial context in the error (#28)
* feat: update report error and warning fn * update tests * add transition to draft to active reporting options * address code review comments * update second arg to reporting function * remove ts expect and switch to cast * feat: update report error and warning fn * update tests * add transition to draft to active reporting options * address code review comments * update second arg to reporting function * fix: improvements to error reporting and warning Co-authored-by: Cynthia Ma <[email protected]> * test: partially update test * test: update failing tests * Update src/v3/TraceManager.ts Co-authored-by: Evan Jenkins <[email protected]> --------- Co-authored-by: Bazyli Brzoska <[email protected]> Co-authored-by: Evan Jenkins <[email protected]>
1 parent b9d5394 commit 500c409

File tree

6 files changed

+582
-353
lines changed

6 files changed

+582
-353
lines changed

src/stories/mockComponentsv3/traceManager.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ export const traceManager = new TraceManager({
1010
},
1111
// eslint-disable-next-line no-magic-numbers
1212
generateId: () => Math.random().toString(36).slice(2),
13-
reportErrorFn: (error) => {
13+
reportErrorFn: (error, currentTraceContext) => {
1414
// eslint-disable-next-line no-console
15-
console.error(error)
15+
console.error(error, currentTraceContext)
1616
},
1717
})
1818

src/v3/Trace.ts

+72-5
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,14 @@ import type {
2727
CompleteTraceDefinition,
2828
DraftTraceContext,
2929
RelationSchemasBase,
30+
ReportErrorFn,
3031
TraceContext,
3132
TraceDefinitionModifications,
3233
TraceInterruptionReason,
3334
TraceInterruptionReasonForInvalidTraces,
3435
TraceManagerUtilities,
3536
TraceModifications,
37+
TransitionDraftOptions,
3638
} from './types'
3739
import { INVALID_TRACE_INTERRUPTION_REASONS } from './types'
3840
import type {
@@ -932,8 +934,12 @@ export class Trace<
932934
VariantsT
933935
> {
934936
if (!this.input.relatedTo) {
935-
throw new Error(
936-
"Tried to access trace's activeInput, but the trace was never provided a 'relatedTo' input value",
937+
this.traceUtilities.reportErrorFn(
938+
new Error(
939+
"Tried to access trace's activeInput, but the trace was never provided a 'relatedTo' input value",
940+
),
941+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
942+
this as Trace<any, RelationSchemasT, any>,
937943
)
938944
}
939945
return this.input as ActiveTraceConfig<
@@ -1074,6 +1080,8 @@ export class Trace<
10741080
input.variant
10751081
}. Must be one of: ${Object.keys(definition.variants).join(', ')}`,
10761082
),
1083+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1084+
this as Trace<any, RelationSchemasT, any>,
10771085
)
10781086
}
10791087

@@ -1224,21 +1232,76 @@ export class Trace<
12241232
RelationSchemasT,
12251233
VariantsT
12261234
>,
1227-
) {
1235+
{
1236+
previouslyActivatedBehavior = 'warn-and-continue',
1237+
invalidRelatedToBehavior = 'warn-and-continue',
1238+
}: TransitionDraftOptions = {},
1239+
): void {
1240+
const { isDraft } = this
1241+
let reportPreviouslyActivated: ReportErrorFn<RelationSchemasT>
1242+
let overwriteDraft = true
1243+
switch (previouslyActivatedBehavior) {
1244+
case 'error':
1245+
reportPreviouslyActivated = this.traceUtilities.reportErrorFn
1246+
overwriteDraft = false
1247+
break
1248+
case 'error-and-continue':
1249+
reportPreviouslyActivated = this.traceUtilities.reportErrorFn
1250+
break
1251+
default:
1252+
reportPreviouslyActivated = this.traceUtilities.reportWarningFn
1253+
break
1254+
}
1255+
1256+
// this is an already initialized active trace, do nothing:
1257+
if (!isDraft) {
1258+
reportPreviouslyActivated(
1259+
new Error(
1260+
`You are trying to activate a trace that has already been activated before (${this.definition.name}).`,
1261+
),
1262+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1263+
this as Trace<any, RelationSchemasT, any>,
1264+
)
1265+
if (!overwriteDraft) {
1266+
return
1267+
}
1268+
}
1269+
1270+
let reportValidationError: ReportErrorFn<RelationSchemasT>
1271+
let useInvalidRelatedTo = true
1272+
switch (invalidRelatedToBehavior) {
1273+
case 'error':
1274+
reportValidationError = this.traceUtilities.reportErrorFn
1275+
useInvalidRelatedTo = false
1276+
break
1277+
case 'error-and-continue':
1278+
reportValidationError = this.traceUtilities.reportErrorFn
1279+
break
1280+
default:
1281+
reportValidationError = this.traceUtilities.reportWarningFn
1282+
break
1283+
}
1284+
12281285
const { attributes } = this.input
12291286

12301287
const { relatedTo, errors } = validateAndCoerceRelatedToAgainstSchema(
12311288
inputAndDefinitionModifications.relatedTo,
12321289
this.definition.relationSchema,
12331290
)
1291+
12341292
if (errors.length > 0) {
1235-
this.traceUtilities.reportWarningFn(
1293+
reportValidationError(
12361294
new Error(
12371295
`Invalid relatedTo value: ${JSON.stringify(
12381296
inputAndDefinitionModifications.relatedTo,
12391297
)}. ${errors.join(', ')}`,
12401298
),
1299+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1300+
this as Trace<any, RelationSchemasT, any>,
12411301
)
1302+
if (!useInvalidRelatedTo) {
1303+
return
1304+
}
12421305
}
12431306

12441307
this.activeInput = {
@@ -1253,7 +1316,11 @@ export class Trace<
12531316
this.applyDefinitionModifications(inputAndDefinitionModifications)
12541317

12551318
this.wasActivated = true
1256-
this.stateMachine.emit('onMakeActive', undefined)
1319+
1320+
if (isDraft) {
1321+
// we might already be active in which case we would have issued a warning earlier in this method
1322+
this.stateMachine.emit('onMakeActive', undefined)
1323+
}
12571324
}
12581325

12591326
/**

src/v3/TraceManager.ts

+20-8
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ import type {
1212
AllPossibleTraceContexts,
1313
CompleteTraceDefinition,
1414
ComputedValueDefinitionInput,
15+
DraftTraceContext,
1516
RelationSchemasBase,
17+
ReportErrorFn,
1618
SpanDeduplicationStrategy,
1719
TraceDefinition,
1820
TraceManagerConfig,
@@ -40,7 +42,7 @@ export class TraceManager<
4042
configInput: Omit<
4143
TraceManagerConfig<RelationSchemasT>,
4244
'reportWarningFn'
43-
> & { reportWarningFn?: (warning: Error) => void },
45+
> & { reportWarningFn?: ReportErrorFn<RelationSchemasT> },
4446
) {
4547
this.utilities = {
4648
// by default noop for warnings
@@ -95,12 +97,6 @@ export class TraceManager<
9597
VariantsT
9698
>(traceDefinition.requiredSpans)
9799

98-
if (!requiredSpans) {
99-
throw new Error(
100-
'requiredSpans must be defined, as a trace will never end otherwise',
101-
)
102-
}
103-
104100
const labelMatching = traceDefinition.labelMatching
105101
? convertLabelMatchersToFns(traceDefinition.labelMatching)
106102
: undefined
@@ -180,7 +176,11 @@ export class TraceManager<
180176
VariantsT
181177
> = {
182178
...traceDefinition,
183-
requiredSpans,
179+
requiredSpans:
180+
requiredSpans ??
181+
[
182+
// lack of requiredSpan is invalid, but we warn about it below
183+
],
184184
debounceOnSpans,
185185
interruptOnSpans,
186186
suppressErrorStatusPropagationOnSpans,
@@ -191,6 +191,18 @@ export class TraceManager<
191191
this.utilities.relationSchemas[traceDefinition.relationSchemaName],
192192
}
193193

194+
if (!requiredSpans) {
195+
this.utilities.reportErrorFn(
196+
new Error(
197+
'requiredSpans must be defined along with the trace, as a trace can only end in an interrupted state otherwise',
198+
),
199+
{ definition: completeTraceDefinition } as Partial<
200+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
201+
DraftTraceContext<any, RelationSchemasT, any>
202+
>,
203+
)
204+
}
205+
194206
return new Tracer(completeTraceDefinition, this.utilities)
195207
}
196208

0 commit comments

Comments
 (0)