diff --git a/README.md b/README.md
index db0851f5..33b94c24 100644
--- a/README.md
+++ b/README.md
@@ -98,6 +98,7 @@ Pass these options to the HoneycombWebSDK:
| enabled | optional | boolean | `true` | Where or not to enable this auto instrumentation. |
| lcp| optional| VitalOpts | `undefined` | Pass-through config options for web-vitals. See [ReportOpts](https://github.com/GoogleChrome/web-vitals?tab=readme-ov-file#reportopts).
| lcp.applyCustomAttributes| optional| function | `undefined` | A function for adding custom attributes to core web vitals spans.
+| lcp.dataAttributes| optional| `string[]` | `undefined` | An array of attribute names to filter reported as `lcp.element.data.someAttr`
`undefined` will send all `data-*` attribute-value pairs. `[]` will send none `['myAttr']` will send the value of `data-my-attr` or `''` if it's not supplied.
Note: An attribute that's defined, but that has no specified value such as `
` will be sent as `{`lcp.element.data.myAttr`: '' }` which is inline with the [dataset API]( https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset).
| cls| optional| VitalOpts | `undefined` | Pass-through config options for web-vitals. See [ReportOpts](https://github.com/GoogleChrome/web-vitals?tab=readme-ov-file#reportopts).
| cls.applyCustomAttributes| optional| function | `undefined` | A function for adding custom attributes to core web vitals spans.
| inp| optional| VitalOptsWithTimings | `undefined` | Pass-through config options for web-vitals. See [ReportOpts](https://github.com/GoogleChrome/web-vitals?tab=readme-ov-file#reportopts).
diff --git a/packages/honeycomb-opentelemetry-web/examples/hello-world-web/index.html b/packages/honeycomb-opentelemetry-web/examples/hello-world-web/index.html
index 2fe85a28..bb25f941 100644
--- a/packages/honeycomb-opentelemetry-web/examples/hello-world-web/index.html
+++ b/packages/honeycomb-opentelemetry-web/examples/hello-world-web/index.html
@@ -1,23 +1,23 @@
-
+
-
-
-
- Honeycomb OpenTelemetry Web Distro
-
-
+
+
+
+ Honeycomb OpenTelemetry Web Distro
+
+
-
-
+
+
- Get A Random Dad Joke
-
-
-
-
-
-
-
+ Get A Random Dad Joke
+
+
+
+
+
+
+
diff --git a/packages/honeycomb-opentelemetry-web/examples/hello-world-web/index.js b/packages/honeycomb-opentelemetry-web/examples/hello-world-web/index.js
index b2395b5b..fb405c0f 100644
--- a/packages/honeycomb-opentelemetry-web/examples/hello-world-web/index.js
+++ b/packages/honeycomb-opentelemetry-web/examples/hello-world-web/index.js
@@ -26,6 +26,9 @@ const main = () => {
contextManager: new ZoneContextManager(),
webVitalsInstrumentationConfig: {
vitalsToTrack: ['CLS', 'FCP', 'FID', 'INP', 'LCP', 'TTFB'],
+ lcp: {
+ dataAttributes: ['hello', 'barBiz'],
+ },
},
});
sdk.start();
diff --git a/packages/honeycomb-opentelemetry-web/examples/hello-world-web/package-lock.json b/packages/honeycomb-opentelemetry-web/examples/hello-world-web/package-lock.json
index 81a2988b..fc1b0c27 100644
--- a/packages/honeycomb-opentelemetry-web/examples/hello-world-web/package-lock.json
+++ b/packages/honeycomb-opentelemetry-web/examples/hello-world-web/package-lock.json
@@ -22,11 +22,12 @@
},
"../..": {
"name": "@honeycombio/opentelemetry-web",
- "version": "0.6.0",
+ "version": "0.7.0",
"license": "Apache-2.0",
"dependencies": {
"@babel/runtime": "^7.24.7",
"@opentelemetry/api": "~1.9.0",
+ "@opentelemetry/auto-instrumentations-web": "^0.41.0",
"@opentelemetry/core": "~1.25.1",
"@opentelemetry/exporter-trace-otlp-http": "~0.52.1",
"@opentelemetry/instrumentation": "~0.52.1",
diff --git a/packages/honeycomb-opentelemetry-web/src/web-vitals-autoinstrumentation.ts b/packages/honeycomb-opentelemetry-web/src/web-vitals-autoinstrumentation.ts
index dd0274d1..c2bec534 100644
--- a/packages/honeycomb-opentelemetry-web/src/web-vitals-autoinstrumentation.ts
+++ b/packages/honeycomb-opentelemetry-web/src/web-vitals-autoinstrumentation.ts
@@ -88,11 +88,19 @@ interface VitalOpts extends ReportOpts {
applyCustomAttributes?: ApplyCustomAttributesFn;
}
-interface VitalOptsWithTimings extends VitalOpts {
+interface LcpVitalOpts extends VitalOpts {
+ /**
+ * Will filter the values of these data attributes if provided, otherwise will send all data-* attributes an LCP entry
+ * An empty allow list, such as { dataAttributes: [] } will disable sending data-* attributes
+ */
+ dataAttributes?: string[];
+}
+
+interface InpVitalOpts extends VitalOpts {
/**
* if this is true it will create spans from the PerformanceLongAnimationFrameTiming frames
*/
- includeTimingsAsSpans: boolean;
+ includeTimingsAsSpans?: boolean;
}
// To avoid importing InstrumentationAbstract from:
@@ -210,13 +218,13 @@ export interface WebVitalsInstrumentationConfig extends InstrumentationConfig {
vitalsToTrack?: Array;
/** Config specific to LCP (Largest Contentful Paint) */
- lcp?: VitalOpts;
+ lcp?: LcpVitalOpts;
/** Config specific to CLS (Cumulative Layout Shift) */
cls?: VitalOpts;
/** Config specific to INP (Interaction to Next Paint) */
- inp?: VitalOptsWithTimings;
+ inp?: InpVitalOpts;
/** Config specific to FID (First Input Delay) */
fid?: VitalOpts;
@@ -235,9 +243,9 @@ export interface WebVitalsInstrumentationConfig extends InstrumentationConfig {
*/
export class WebVitalsInstrumentation extends InstrumentationAbstract {
readonly vitalsToTrack: Array;
- readonly lcpOpts?: VitalOpts;
+ readonly lcpOpts?: LcpVitalOpts;
readonly clsOpts?: VitalOpts;
- readonly inpOpts?: VitalOptsWithTimings;
+ readonly inpOpts?: InpVitalOpts;
readonly fidOpts?: VitalOpts;
readonly fcpOpts?: VitalOpts;
readonly ttfbOpts?: VitalOpts;
@@ -280,41 +288,37 @@ export class WebVitalsInstrumentation extends InstrumentationAbstract {
private _setupWebVitalsCallbacks() {
if (this.vitalsToTrack.includes('CLS')) {
onCLS((vital) => {
- this.onReportCLS(vital, this.clsOpts?.applyCustomAttributes);
+ this.onReportCLS(vital, this.clsOpts);
}, this.clsOpts);
}
if (this.vitalsToTrack.includes('LCP')) {
onLCP((vital) => {
- this.onReportLCP(vital, this.lcpOpts?.applyCustomAttributes);
+ this.onReportLCP(vital, this.lcpOpts);
}, this.lcpOpts);
}
if (this.vitalsToTrack.includes('INP')) {
onINP((vital) => {
- this.onReportINP(
- vital,
- this.inpOpts?.applyCustomAttributes,
- this.inpOpts?.includeTimingsAsSpans,
- );
+ this.onReportINP(vital, this.inpOpts);
}, this.inpOpts);
}
if (this.vitalsToTrack.includes('FID')) {
onFID((vital) => {
- this.onReportFID(vital, this.fidOpts?.applyCustomAttributes);
+ this.onReportFID(vital, this.fidOpts);
}, this.fidOpts);
}
if (this.vitalsToTrack.includes('TTFB')) {
onTTFB((vital) => {
- this.onReportTTFB(vital, this.ttfbOpts?.applyCustomAttributes);
+ this.onReportTTFB(vital, this.ttfbOpts);
}, this.ttfbOpts);
}
if (this.vitalsToTrack.includes('FCP')) {
onFCP((vital) => {
- this.onReportFCP(vital, this.fcpOpts?.applyCustomAttributes);
+ this.onReportFCP(vital, this.fcpOpts);
}, this.fcpOpts);
}
}
@@ -417,10 +421,8 @@ export class WebVitalsInstrumentation extends InstrumentationAbstract {
});
}
- onReportCLS = (
- cls: CLSMetricWithAttribution,
- applyCustomAttributes?: ApplyCustomAttributesFn,
- ) => {
+ onReportCLS = (cls: CLSMetricWithAttribution, clsOpts: VitalOpts = {}) => {
+ const { applyCustomAttributes } = clsOpts;
if (!this.isEnabled()) return;
const { name, attribution } = cls;
@@ -451,10 +453,8 @@ export class WebVitalsInstrumentation extends InstrumentationAbstract {
span.end();
};
- onReportLCP = (
- lcp: LCPMetricWithAttribution,
- applyCustomAttributes?: ApplyCustomAttributesFn,
- ) => {
+ onReportLCP = (lcp: LCPMetricWithAttribution, lcpOpts: LcpVitalOpts = {}) => {
+ const { applyCustomAttributes, dataAttributes } = lcpOpts;
if (!this.isEnabled()) return;
const { name, attribution } = lcp;
@@ -465,6 +465,7 @@ export class WebVitalsInstrumentation extends InstrumentationAbstract {
resourceLoadDelay,
resourceLoadDuration,
elementRenderDelay,
+ lcpEntry,
}: LCPAttribution = attribution;
const attrPrefix = this.getAttrPrefix(name);
@@ -481,6 +482,36 @@ export class WebVitalsInstrumentation extends InstrumentationAbstract {
[`${attrPrefix}.resource_load_time`]: resourceLoadDuration,
});
+ const el: HTMLElement = lcpEntry?.element as HTMLElement;
+ if (el.dataset) {
+ for (const attrName in el.dataset) {
+ const attrValue = el.dataset[attrName];
+ if (
+ // Value exists (including the empty string AND either
+ attrValue !== undefined &&
+ // dataAttributes is undefined (i.e. send all values as span attributes) OR
+ (dataAttributes === undefined ||
+ // dataAttributes is specified AND attrName is in dataAttributes (i.e attribute name is in the supplied allowList)
+ (dataAttributes && attrName in dataAttributes))
+ ) {
+ span.setAttribute(
+ `${attrPrefix}.element.data.${attrName}`,
+ attrValue,
+ );
+ }
+ }
+ }
+ if (dataAttributes)
+ dataAttributes?.forEach((attrName) => {
+ const attrValue = el.dataset[attrName];
+ if (attrValue !== undefined) {
+ span.setAttribute(
+ `${attrPrefix}.element.data.${attrName}`,
+ attrValue,
+ );
+ }
+ });
+
if (applyCustomAttributes) {
applyCustomAttributes(lcp, span);
}
@@ -490,9 +521,9 @@ export class WebVitalsInstrumentation extends InstrumentationAbstract {
onReportINP = (
inp: INPMetricWithAttribution,
- applyCustomAttributes?: ApplyCustomAttributesFn,
- includeTimingsAsSpans = false,
+ inpOpts: InpVitalOpts = { includeTimingsAsSpans: false },
) => {
+ const { applyCustomAttributes, includeTimingsAsSpans } = inpOpts;
if (!this.isEnabled()) return;
const { name, attribution } = inp;
@@ -550,10 +581,8 @@ export class WebVitalsInstrumentation extends InstrumentationAbstract {
);
};
- onReportFCP = (
- fcp: FCPMetricWithAttribution,
- applyCustomAttributes?: ApplyCustomAttributesFn,
- ) => {
+ onReportFCP = (fcp: FCPMetricWithAttribution, fcpOpts: VitalOpts = {}) => {
+ const { applyCustomAttributes } = fcpOpts;
if (!this.isEnabled()) return;
const { name, attribution } = fcp;
@@ -580,10 +609,8 @@ export class WebVitalsInstrumentation extends InstrumentationAbstract {
/**
* @deprecated this will be removed in the next major version, use INP instead.
*/
- onReportFID = (
- fid: FIDMetricWithAttribution,
- applyCustomAttributes?: ApplyCustomAttributesFn,
- ) => {
+ onReportFID = (fid: FIDMetricWithAttribution, fidOpts: VitalOpts = {}) => {
+ const { applyCustomAttributes } = fidOpts;
if (!this.isEnabled()) return;
const { name, attribution } = fid;
@@ -608,8 +635,9 @@ export class WebVitalsInstrumentation extends InstrumentationAbstract {
onReportTTFB = (
ttfb: TTFBMetricWithAttribution,
- applyCustomAttributes?: ApplyCustomAttributesFn,
+ ttfbOpts: VitalOpts = {},
) => {
+ const { applyCustomAttributes } = ttfbOpts;
if (!this.isEnabled()) return;
const { name, attribution } = ttfb;
diff --git a/packages/honeycomb-opentelemetry-web/test/web-vitals-instrumentation.test.ts b/packages/honeycomb-opentelemetry-web/test/web-vitals-instrumentation.test.ts
index 35529bf3..932c9b00 100644
--- a/packages/honeycomb-opentelemetry-web/test/web-vitals-instrumentation.test.ts
+++ b/packages/honeycomb-opentelemetry-web/test/web-vitals-instrumentation.test.ts
@@ -56,6 +56,9 @@ const CLSAttr = {
'cls.entries': '',
'cls.my_custom_attr': 'custom_attr',
};
+const div = document.createElement('div');
+div.innerHTML = `👋 Hello World
`;
+const lcpElement = div.firstElementChild;
const LCP: LCPMetricWithAttribution = {
name: 'LCP',
@@ -72,6 +75,19 @@ const LCP: LCPMetricWithAttribution = {
resourceLoadDuration: 20,
elementRenderDelay: 20,
resourceLoadDelay: 100,
+ lcpEntry: {
+ duration: 0,
+ element: lcpElement,
+ entryType: 'largest-contentful-paint',
+ id: '',
+ loadTime: 0,
+ name: '',
+ renderTime: 74.09999999403954,
+ size: 4382,
+ startTime: 74.09999999403954,
+ url: '',
+ toJSON: () => '',
+ },
},
};
@@ -303,11 +319,13 @@ describe('Web Vitals Instrumentation Tests', () => {
describe('CLS', () => {
it('should create a span when enabled', () => {
const webVitalsInstr = new WebVitalsInstrumentation();
- webVitalsInstr.onReportCLS(CLS, (cls, span) => {
- span.setAttributes({
- 'cls.entries': cls.entries.toString(),
- 'cls.my_custom_attr': 'custom_attr',
- });
+ webVitalsInstr.onReportCLS(CLS, {
+ applyCustomAttributes: (cls, span) => {
+ span.setAttributes({
+ 'cls.entries': cls.entries.toString(),
+ 'cls.my_custom_attr': 'custom_attr',
+ });
+ },
});
const span = exporter.getFinishedSpans()[0];
@@ -323,11 +341,11 @@ describe('Web Vitals Instrumentation Tests', () => {
vitalsToTrack: ['CLS'],
});
instr.disable();
- instr.onReportCLS(CLS, () => {});
+ instr.onReportCLS(CLS, { applyCustomAttributes: () => {} });
expect(exporter.getFinishedSpans().length).toEqual(0);
instr.enable();
- instr.onReportCLS(CLS, () => {});
+ instr.onReportCLS(CLS, { applyCustomAttributes: () => {} });
expect(exporter.getFinishedSpans().length).toEqual(1);
expect(exporter.getFinishedSpans()[0].name).toEqual('CLS');
@@ -337,11 +355,14 @@ describe('Web Vitals Instrumentation Tests', () => {
describe('LCP', () => {
it('should create a span when enabled', () => {
const webVitalsInstr = new WebVitalsInstrumentation();
- webVitalsInstr.onReportLCP(LCP, (lcp, span) => {
- span.setAttributes({
- 'lcp.entries': lcp.entries.toString(),
- 'lcp.my_custom_attr': 'custom_attr',
- });
+ webVitalsInstr.onReportLCP(LCP, {
+ dataAttributes: [],
+ applyCustomAttributes: (lcp, span) => {
+ span.setAttributes({
+ 'lcp.entries': lcp.entries.toString(),
+ 'lcp.my_custom_attr': 'custom_attr',
+ });
+ },
});
const span = exporter.getFinishedSpans()[0];
@@ -357,25 +378,84 @@ describe('Web Vitals Instrumentation Tests', () => {
vitalsToTrack: ['LCP'],
});
instr.disable();
- instr.onReportLCP(LCP, () => {});
+ instr.onReportLCP(LCP, { applyCustomAttributes: () => {} });
expect(exporter.getFinishedSpans().length).toEqual(0);
instr.enable();
- instr.onReportLCP(LCP, () => {});
+ instr.onReportLCP(LCP, { applyCustomAttributes: () => {} });
expect(exporter.getFinishedSpans().length).toEqual(1);
expect(exporter.getFinishedSpans()[0].name).toEqual('LCP');
});
+
+ it('should include add data-* attributes as span attributes when dataAttributes is undefined', () => {
+ const instr = new WebVitalsInstrumentation({
+ vitalsToTrack: ['LCP'],
+ });
+ instr.enable();
+ instr.onReportLCP(LCP, {
+ applyCustomAttributes: () => {},
+ dataAttributes: undefined,
+ });
+ expect(exporter.getFinishedSpans().length).toEqual(1);
+ const span = exporter.getFinishedSpans()[0];
+ expect(span.attributes).toMatchObject({
+ 'lcp.element.data.answer': '42',
+ 'lcp.element.data.famousCats': 'Mr. Mistoffelees',
+ 'lcp.element.data.hasCats': '',
+ });
+ });
+ it('should not include any data-* attributes when dataAttributes is []', () => {
+ const instr = new WebVitalsInstrumentation({
+ vitalsToTrack: ['LCP'],
+ });
+ instr.enable();
+ instr.onReportLCP(LCP, {
+ applyCustomAttributes: () => {},
+ dataAttributes: [],
+ });
+ expect(exporter.getFinishedSpans().length).toEqual(1);
+ const span = exporter.getFinishedSpans()[0];
+ expect(span.attributes).not.toMatchObject({
+ 'lcp.element.data.answer': '42',
+ 'lcp.element.data.famousCats': 'Mr. Mistoffelees',
+ 'lcp.element.data.hasCats': '',
+ });
+ });
+ it('should only include any data-* attributes that match dataAttributes array', () => {
+ const instr = new WebVitalsInstrumentation({
+ vitalsToTrack: ['LCP'],
+ });
+ instr.enable();
+ instr.onReportLCP(LCP, {
+ applyCustomAttributes: () => {},
+ dataAttributes: ['answer'],
+ });
+ expect(exporter.getFinishedSpans().length).toEqual(1);
+ const span = exporter.getFinishedSpans()[0];
+ expect(span.attributes['lcp.element.data.answer']).toEqual('42');
+ expect(span.attributes['lcp.element.famousCats']).toBeUndefined();
+ expect(span.attributes['lcp.element.hasCats']).toBeUndefined();
+ expect(span.attributes).toMatchObject({
+ 'lcp.element.data.answer': '42',
+ });
+ expect(span.attributes).not.toMatchObject({
+ 'lcp.element.data.famousCats': 'Mr. Mistoffelees',
+ 'lcp.element.data.hasCats': '',
+ });
+ });
});
describe('INP', () => {
it('should create a span when enabled', () => {
const webVitalsInstr = new WebVitalsInstrumentation();
- webVitalsInstr.onReportINP(INP, (inp, span) => {
- span.setAttributes({
- 'inp.entries': inp.entries.toString(),
- 'inp.my_custom_attr': 'custom_attr',
- });
+ webVitalsInstr.onReportINP(INP, {
+ applyCustomAttributes: (inp, span) => {
+ span.setAttributes({
+ 'inp.entries': inp.entries.toString(),
+ 'inp.my_custom_attr': 'custom_attr',
+ });
+ },
});
const span = exporter.getFinishedSpans()[0];
@@ -388,20 +468,18 @@ describe('Web Vitals Instrumentation Tests', () => {
it('should create a include timings when enabled', () => {
const webVitalsInstr = new WebVitalsInstrumentation();
- webVitalsInstr.onReportINP(
- INPWithTimings,
- (inp, span) => {
+ webVitalsInstr.onReportINP(INPWithTimings, {
+ applyCustomAttributes: (inp, span) => {
span.setAttributes({
'inp.entries': inp.entries.toString(),
'inp.my_custom_attr': 'custom_attr',
});
},
- true,
- );
+ includeTimingsAsSpans: true,
+ });
const [scriptTimingSpan, timingSpan, inpSpan] =
exporter.getFinishedSpans();
- console.log({ timingSpan });
expect(inpSpan.name).toBe('INP');
expect(inpSpan.instrumentationLibrary.name).toBe(
'@honeycombio/instrumentation-web-vitals',
@@ -433,11 +511,11 @@ describe('Web Vitals Instrumentation Tests', () => {
vitalsToTrack: ['INP'],
});
instr.disable();
- instr.onReportINP(INP, () => {});
+ instr.onReportINP(INP, { applyCustomAttributes: () => {} });
expect(exporter.getFinishedSpans().length).toEqual(0);
instr.enable();
- instr.onReportINP(INP, () => {});
+ instr.onReportINP(INP, { applyCustomAttributes: () => {} });
expect(exporter.getFinishedSpans().length).toEqual(1);
expect(exporter.getFinishedSpans()[0].name).toEqual('INP');
@@ -447,11 +525,13 @@ describe('Web Vitals Instrumentation Tests', () => {
describe('FCP', () => {
it('should create a span when enabled', () => {
const webVitalsInstr = new WebVitalsInstrumentation();
- webVitalsInstr.onReportFCP(FCP, (fcp, span) => {
- span.setAttributes({
- 'fcp.entries': fcp.entries.toString(),
- 'fcp.my_custom_attr': 'custom_attr',
- });
+ webVitalsInstr.onReportFCP(FCP, {
+ applyCustomAttributes: (fcp, span) => {
+ span.setAttributes({
+ 'fcp.entries': fcp.entries.toString(),
+ 'fcp.my_custom_attr': 'custom_attr',
+ });
+ },
});
const span = exporter.getFinishedSpans()[0];
expect(span.name).toBe('FCP');
@@ -466,11 +546,11 @@ describe('Web Vitals Instrumentation Tests', () => {
vitalsToTrack: ['FCP'],
});
instr.disable();
- instr.onReportFCP(FCP, () => {});
+ instr.onReportFCP(FCP, { applyCustomAttributes: () => {} });
expect(exporter.getFinishedSpans().length).toEqual(0);
instr.enable();
- instr.onReportFCP(FCP, () => {});
+ instr.onReportFCP(FCP, { applyCustomAttributes: () => {} });
expect(exporter.getFinishedSpans().length).toEqual(1);
expect(exporter.getFinishedSpans()[0].name).toEqual('FCP');
@@ -480,11 +560,13 @@ describe('Web Vitals Instrumentation Tests', () => {
describe('TTFB', () => {
it('should create a span when enabled', () => {
const webVitalsInstr = new WebVitalsInstrumentation();
- webVitalsInstr.onReportTTFB(TTFB, (ttfb, span) => {
- span.setAttributes({
- 'ttfb.entries': ttfb.entries.toString(),
- 'ttfb.my_custom_attr': 'custom_attr',
- });
+ webVitalsInstr.onReportTTFB(TTFB, {
+ applyCustomAttributes: (ttfb, span) => {
+ span.setAttributes({
+ 'ttfb.entries': ttfb.entries.toString(),
+ 'ttfb.my_custom_attr': 'custom_attr',
+ });
+ },
});
const span = exporter.getFinishedSpans()[0];
@@ -500,11 +582,11 @@ describe('Web Vitals Instrumentation Tests', () => {
vitalsToTrack: ['TTFB'],
});
instr.disable();
- instr.onReportTTFB(TTFB, () => {});
+ instr.onReportTTFB(TTFB, { applyCustomAttributes: () => {} });
expect(exporter.getFinishedSpans().length).toEqual(0);
instr.enable();
- instr.onReportTTFB(TTFB, () => {});
+ instr.onReportTTFB(TTFB, { applyCustomAttributes: () => {} });
expect(exporter.getFinishedSpans().length).toEqual(1);
expect(exporter.getFinishedSpans()[0].name).toEqual('TTFB');
@@ -514,11 +596,13 @@ describe('Web Vitals Instrumentation Tests', () => {
describe('FID', () => {
it('should create a span when enabled', () => {
const webVitalsInstr = new WebVitalsInstrumentation();
- webVitalsInstr.onReportFID(FID, (fid, span) => {
- span.setAttributes({
- 'fid.entries': fid.entries.toString(),
- 'fid.my_custom_attr': 'custom_attr',
- });
+ webVitalsInstr.onReportFID(FID, {
+ applyCustomAttributes: (fid, span) => {
+ span.setAttributes({
+ 'fid.entries': fid.entries.toString(),
+ 'fid.my_custom_attr': 'custom_attr',
+ });
+ },
});
const span = exporter.getFinishedSpans()[0];
@@ -534,11 +618,11 @@ describe('Web Vitals Instrumentation Tests', () => {
vitalsToTrack: ['FID'],
});
instr.disable();
- instr.onReportFID(FID, () => {});
+ instr.onReportFID(FID, { applyCustomAttributes: () => {} });
expect(exporter.getFinishedSpans().length).toEqual(0);
instr.enable();
- instr.onReportFID(FID, () => {});
+ instr.onReportFID(FID, { applyCustomAttributes: () => {} });
expect(exporter.getFinishedSpans().length).toEqual(1);
expect(exporter.getFinishedSpans()[0].name).toEqual('FID');