@@ -122,6 +122,206 @@ app.get('/logs', (_req: Request, res: Response) => {
122122 res . status ( 200 ) . json ( { message : 'Logs generated successfully' } ) ;
123123} ) ;
124124
125+ // Smoke test endpoint for setTraceAttributes API
126+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
127+ app . get (
128+ '/test-trace-attributes' ,
129+ async ( _req : Request , res : Response , next : NextFunction ) => {
130+ try {
131+ const tracer : Tracer = trace . getTracer ( 'trace-attributes-test' ) ;
132+ const results : { [ key : string ] : string } = { } ;
133+
134+ // Test 1: Basic attribute setting
135+ await tracer . startActiveSpan ( 'test-basic-attributes' , ( span : Span ) => {
136+ HyperDX . setTraceAttributes ( {
137+ userId : 'user-123' ,
138+ requestId : 'req-456' ,
139+ testName : 'basic-attributes' ,
140+ } ) ;
141+ pinoLogger . info ( 'Test 1: Set basic trace attributes' ) ;
142+ results . test1 = 'basic-attributes-set' ;
143+ span . end ( ) ;
144+ } ) ;
145+
146+ // Test 2: Multiple attribute types
147+ await tracer . startActiveSpan ( 'test-multiple-types' , ( span : Span ) => {
148+ HyperDX . setTraceAttributes ( {
149+ stringAttr : 'value' ,
150+ numberAttr : 42 ,
151+ booleanAttr : true ,
152+ arrayAttr : [ 'a' , 'b' , 'c' ] ,
153+ testName : 'multiple-types' ,
154+ } ) ;
155+ pinoLogger . info ( 'Test 2: Set multiple attribute types' ) ;
156+ results . test2 = 'multiple-types-set' ;
157+ span . end ( ) ;
158+ } ) ;
159+
160+ // Test 3: Nested spans with attributes
161+ await tracer . startActiveSpan ( 'test-nested-spans' , async ( parentSpan ) => {
162+ HyperDX . setTraceAttributes ( {
163+ level : 'parent' ,
164+ testName : 'nested-spans' ,
165+ } ) ;
166+ pinoLogger . info ( 'Test 3: Parent span attributes' ) ;
167+
168+ await tracer . startActiveSpan ( 'child-span' , async ( childSpan ) => {
169+ HyperDX . setTraceAttributes ( {
170+ level : 'child' ,
171+ childId : 'child-1' ,
172+ } ) ;
173+ pinoLogger . info ( 'Test 3: Child span attributes' ) ;
174+
175+ await tracer . startActiveSpan ( 'grandchild-span' , ( grandchildSpan ) => {
176+ HyperDX . setTraceAttributes ( {
177+ level : 'grandchild' ,
178+ grandchildId : 'grandchild-1' ,
179+ } ) ;
180+ pinoLogger . info ( 'Test 3: Grandchild span attributes' ) ;
181+ grandchildSpan . end ( ) ;
182+ } ) ;
183+
184+ childSpan . end ( ) ;
185+ } ) ;
186+
187+ results . test3 = 'nested-spans-set' ;
188+ parentSpan . end ( ) ;
189+ } ) ;
190+
191+ // Test 4: Setting attributes multiple times (overwrite)
192+ await tracer . startActiveSpan ( 'test-overwrite' , ( span : Span ) => {
193+ HyperDX . setTraceAttributes ( {
194+ key : 'value1' ,
195+ testName : 'overwrite' ,
196+ } ) ;
197+ HyperDX . setTraceAttributes ( {
198+ key : 'value2' , // This should overwrite the previous value
199+ additionalKey : 'additional-value' ,
200+ } ) ;
201+ pinoLogger . info ( 'Test 4: Overwrite attributes' ) ;
202+ results . test4 = 'overwrite-set' ;
203+ span . end ( ) ;
204+ } ) ;
205+
206+ // Test 5: Attributes with special characters
207+ await tracer . startActiveSpan ( 'test-special-chars' , ( span : Span ) => {
208+ HyperDX . setTraceAttributes ( {
209+ 'user.id' : 'user-123' ,
210+ 'request-id' : 'req-456' ,
211+ 'foo.bar.baz' : 'nested-key' ,
212+ 'key with spaces' : 'value with spaces' ,
213+ testName : 'special-chars' ,
214+ } ) ;
215+ pinoLogger . info ( 'Test 5: Special characters in attribute keys' ) ;
216+ results . test5 = 'special-chars-set' ;
217+ span . end ( ) ;
218+ } ) ;
219+
220+ // Test 6: Empty attributes
221+ await tracer . startActiveSpan ( 'test-empty-attributes' , ( span : Span ) => {
222+ HyperDX . setTraceAttributes ( { } ) ;
223+ pinoLogger . info ( 'Test 6: Empty attributes object' ) ;
224+ results . test6 = 'empty-attributes-set' ;
225+ span . end ( ) ;
226+ } ) ;
227+
228+ // Test 7: Large number of attributes
229+ await tracer . startActiveSpan ( 'test-many-attributes' , ( span : Span ) => {
230+ const manyAttributes : { [ key : string ] : string } = {
231+ testName : 'many-attributes' ,
232+ } ;
233+ for ( let i = 0 ; i < 50 ; i ++ ) {
234+ manyAttributes [ `attr${ i } ` ] = `value${ i } ` ;
235+ }
236+ HyperDX . setTraceAttributes ( manyAttributes ) ;
237+ pinoLogger . info ( 'Test 7: Large number of attributes (50)' ) ;
238+ results . test7 = 'many-attributes-set' ;
239+ span . end ( ) ;
240+ } ) ;
241+
242+ // Test 8: Concurrent attribute setting
243+ await Promise . all ( [
244+ tracer . startActiveSpan ( 'concurrent-1' , async ( span ) => {
245+ HyperDX . setTraceAttributes ( {
246+ spanId : '1' ,
247+ value : 'concurrent-a' ,
248+ testName : 'concurrent-1' ,
249+ } ) ;
250+ pinoLogger . info ( 'Test 8: Concurrent span 1' ) ;
251+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
252+ span . end ( ) ;
253+ } ) ,
254+ tracer . startActiveSpan ( 'concurrent-2' , async ( span ) => {
255+ HyperDX . setTraceAttributes ( {
256+ spanId : '2' ,
257+ value : 'concurrent-b' ,
258+ testName : 'concurrent-2' ,
259+ } ) ;
260+ pinoLogger . info ( 'Test 8: Concurrent span 2' ) ;
261+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
262+ span . end ( ) ;
263+ } ) ,
264+ tracer . startActiveSpan ( 'concurrent-3' , async ( span ) => {
265+ HyperDX . setTraceAttributes ( {
266+ spanId : '3' ,
267+ value : 'concurrent-c' ,
268+ testName : 'concurrent-3' ,
269+ } ) ;
270+ pinoLogger . info ( 'Test 8: Concurrent span 3' ) ;
271+ await new Promise ( ( resolve ) => setTimeout ( resolve , 10 ) ) ;
272+ span . end ( ) ;
273+ } ) ,
274+ ] ) ;
275+ results . test8 = 'concurrent-attributes-set' ;
276+
277+ // Test 9: Attributes in async operations
278+ await tracer . startActiveSpan ( 'test-async' , async ( span ) => {
279+ HyperDX . setTraceAttributes ( {
280+ stage : 'before-async' ,
281+ testName : 'async' ,
282+ } ) ;
283+ pinoLogger . info ( 'Test 9: Before async operation' ) ;
284+
285+ await new Promise ( ( resolve ) => setTimeout ( resolve , 20 ) ) ;
286+
287+ HyperDX . setTraceAttributes ( {
288+ stage : 'after-async' ,
289+ } ) ;
290+ pinoLogger . info ( 'Test 9: After async operation' ) ;
291+
292+ results . test9 = 'async-attributes-set' ;
293+ span . end ( ) ;
294+ } ) ;
295+
296+ // Test 10: Attributes with null/undefined values
297+ await tracer . startActiveSpan ( 'test-null-undefined' , ( span : Span ) => {
298+ HyperDX . setTraceAttributes ( {
299+ nullAttr : null as any ,
300+ undefinedAttr : undefined as any ,
301+ validAttr : 'valid' ,
302+ testName : 'null-undefined' ,
303+ } ) ;
304+ pinoLogger . info ( 'Test 10: Null and undefined values' ) ;
305+ results . test10 = 'null-undefined-set' ;
306+ span . end ( ) ;
307+ } ) ;
308+
309+ pinoLogger . info (
310+ { results } ,
311+ 'All setTraceAttributes smoke tests completed' ,
312+ ) ;
313+ res . status ( 200 ) . json ( {
314+ message : 'setTraceAttributes smoke tests completed successfully' ,
315+ results,
316+ testsRun : Object . keys ( results ) . length ,
317+ } ) ;
318+ } catch ( err ) {
319+ pinoLogger . error ( { err } , 'Error in setTraceAttributes smoke tests' ) ;
320+ next ( err ) ;
321+ }
322+ } ,
323+ ) ;
324+
125325function sleepy ( ) : Promise < void > {
126326 return new Promise ( ( resolve ) => {
127327 setTimeout ( ( ) => {
0 commit comments