@@ -8,10 +8,12 @@ import { URL } from 'node:url'
88import { setTimeout } from 'node:timers/promises'
99import { test } from 'tap'
1010import FakeTimers from '@sinonjs/fake-timers'
11+ import { Transport } from '@elastic/transport'
1112import { buildServer , connection } from '../utils'
1213import { Client , errors , SniffingTransport } from '../..'
1314import * as symbols from '@elastic/transport/lib/symbols'
1415import { BaseConnectionPool , CloudConnectionPool , WeightedConnectionPool , HttpConnection } from '@elastic/transport'
16+ import { BasicTracerProvider , InMemorySpanExporter , SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base'
1517
1618let clientVersion : string = require ( '../../package.json' ) . version // eslint-disable-line
1719if ( clientVersion . includes ( '-' ) ) {
@@ -124,7 +126,7 @@ test('Basic auth', async t => {
124126 t . plan ( 1 )
125127
126128 const Connection = connection . buildMockConnection ( {
127- onRequest ( opts ) {
129+ onRequest ( opts ) {
128130 t . match ( opts . headers , { authorization : 'Basic aGVsbG86d29ybGQ=' } )
129131 return {
130132 statusCode : 200 ,
@@ -149,7 +151,7 @@ test('Basic auth via url', async t => {
149151 t . plan ( 1 )
150152
151153 const Connection = connection . buildMockConnection ( {
152- onRequest ( opts ) {
154+ onRequest ( opts ) {
153155 t . match ( opts . headers , { authorization : 'Basic aGVsbG86d29ybGQ=' } )
154156 return {
155157 statusCode : 200 ,
@@ -170,7 +172,7 @@ test('ApiKey as string', async t => {
170172 t . plan ( 1 )
171173
172174 const Connection = connection . buildMockConnection ( {
173- onRequest ( opts ) {
175+ onRequest ( opts ) {
174176 t . match ( opts . headers , { authorization : 'ApiKey foobar' } )
175177 return {
176178 statusCode : 200 ,
@@ -194,7 +196,7 @@ test('ApiKey as object', async t => {
194196 t . plan ( 1 )
195197
196198 const Connection = connection . buildMockConnection ( {
197- onRequest ( opts ) {
199+ onRequest ( opts ) {
198200 t . match ( opts . headers , { authorization : 'ApiKey Zm9vOmJhcg==' } )
199201 return {
200202 statusCode : 200 ,
@@ -221,7 +223,7 @@ test('Bearer auth', async t => {
221223 t . plan ( 1 )
222224
223225 const Connection = connection . buildMockConnection ( {
224- onRequest ( opts ) {
226+ onRequest ( opts ) {
225227 t . match ( opts . headers , { authorization : 'Bearer token' } )
226228 return {
227229 statusCode : 200 ,
@@ -245,7 +247,7 @@ test('Override authentication per request', async t => {
245247 t . plan ( 1 )
246248
247249 const Connection = connection . buildMockConnection ( {
248- onRequest ( opts ) {
250+ onRequest ( opts ) {
249251 t . match ( opts . headers , { authorization : 'Basic foobar' } )
250252 return {
251253 statusCode : 200 ,
@@ -273,7 +275,7 @@ test('Custom headers per request', async t => {
273275 t . plan ( 1 )
274276
275277 const Connection = connection . buildMockConnection ( {
276- onRequest ( opts ) {
278+ onRequest ( opts ) {
277279 t . match ( opts . headers , {
278280 foo : 'bar' ,
279281 faz : 'bar'
@@ -301,7 +303,7 @@ test('Close the client', async t => {
301303 t . plan ( 1 )
302304
303305 class MyConnectionPool extends BaseConnectionPool {
304- async empty ( ) : Promise < void > {
306+ async empty ( ) : Promise < void > {
305307 t . pass ( 'called' )
306308 }
307309 }
@@ -336,10 +338,10 @@ test('Elastic Cloud config', t => {
336338
337339 t . test ( 'Invalid Cloud ID will throw ConfigurationError' , t => {
338340 t . throws ( ( ) => new Client ( {
339- cloud : {
340- id : 'invalidCloudIdThatIsNotBase64'
341+ cloud : {
342+ id : 'invalidCloudIdThatIsNotBase64'
341343 } ,
342- auth : {
344+ auth : {
343345 username : 'elastic' ,
344346 password : 'changeme'
345347 }
@@ -414,7 +416,7 @@ test('Meta header enabled by default', async t => {
414416 t . plan ( 1 )
415417
416418 const Connection = connection . buildMockConnection ( {
417- onRequest ( opts ) {
419+ onRequest ( opts ) {
418420 t . match ( opts . headers , { 'x-elastic-client-meta' : `es=${ clientVersion } ,js=${ nodeVersion } ,t=${ transportVersion } ,hc=${ nodeVersion } ` } )
419421 return {
420422 statusCode : 200 ,
@@ -435,7 +437,7 @@ test('Meta header disabled', async t => {
435437 t . plan ( 1 )
436438
437439 const Connection = connection . buildMockConnection ( {
438- onRequest ( opts ) {
440+ onRequest ( opts ) {
439441 t . notOk ( opts . headers ?. [ 'x-elastic-client-meta' ] )
440442 return {
441443 statusCode : 200 ,
@@ -456,39 +458,39 @@ test('Meta header disabled', async t => {
456458test ( 'Meta header indicates when UndiciConnection is used' , async t => {
457459 t . plan ( 1 )
458460
459- function handler ( req : http . IncomingMessage , res : http . ServerResponse ) {
461+ function handler ( req : http . IncomingMessage , res : http . ServerResponse ) {
460462 t . equal ( req . headers [ 'x-elastic-client-meta' ] , `es=${ clientVersion } ,js=${ nodeVersion } ,t=${ transportVersion } ,un=${ nodeVersion } ` )
461463 res . end ( 'ok' )
462464 }
463465
464466 const [ { port } , server ] = await buildServer ( handler )
467+ t . after ( ( ) => server . stop ( ) )
465468
466469 const client = new Client ( {
467470 node : `http://localhost:${ port } ` ,
468471 // Connection: UndiciConnection is the default
469472 } )
470473
471474 await client . transport . request ( { method : 'GET' , path : '/' } )
472- server . stop ( )
473475} )
474476
475477test ( 'Meta header indicates when HttpConnection is used' , async t => {
476478 t . plan ( 1 )
477479
478- function handler ( req : http . IncomingMessage , res : http . ServerResponse ) {
480+ function handler ( req : http . IncomingMessage , res : http . ServerResponse ) {
479481 t . equal ( req . headers [ 'x-elastic-client-meta' ] , `es=${ clientVersion } ,js=${ nodeVersion } ,t=${ transportVersion } ,hc=${ nodeVersion } ` )
480482 res . end ( 'ok' )
481483 }
482484
483485 const [ { port } , server ] = await buildServer ( handler )
486+ t . after ( ( ) => server . stop ( ) )
484487
485488 const client = new Client ( {
486489 node : `http://localhost:${ port } ` ,
487490 Connection : HttpConnection ,
488491 } )
489492
490493 await client . transport . request ( { method : 'GET' , path : '/' } )
491- server . stop ( )
492494} )
493495
494496test ( 'caFingerprint' , t => {
@@ -503,19 +505,19 @@ test('caFingerprint', t => {
503505
504506test ( 'caFingerprint can\'t be configured over http / 1' , t => {
505507 t . throws ( ( ) => new Client ( {
506- node : 'http://localhost:9200' ,
507- caFingerprint : 'FO:OB:AR'
508- } ) ,
508+ node : 'http://localhost:9200' ,
509+ caFingerprint : 'FO:OB:AR'
510+ } ) ,
509511 errors . ConfigurationError
510512 )
511513 t . end ( )
512514} )
513515
514516test ( 'caFingerprint can\'t be configured over http / 2' , t => {
515517 t . throws ( ( ) => new Client ( {
516- nodes : [ 'http://localhost:9200' ] ,
517- caFingerprint : 'FO:OB:AR'
518- } ) ,
518+ nodes : [ 'http://localhost:9200' ] ,
519+ caFingerprint : 'FO:OB:AR'
520+ } ) ,
519521 errors . ConfigurationError
520522 )
521523 t . end ( )
@@ -551,7 +553,7 @@ test('Ensure new client does not time out if requestTimeout is not set', async t
551553 const clock = FakeTimers . install ( { toFake : [ 'setTimeout' ] } )
552554 t . teardown ( ( ) => clock . uninstall ( ) )
553555
554- function handler ( _req : http . IncomingMessage , res : http . ServerResponse ) {
556+ function handler ( _req : http . IncomingMessage , res : http . ServerResponse ) {
555557 setTimeout ( 1000 * 60 * 60 ) . then ( ( ) => {
556558 t . ok ( 'timeout ended' )
557559 res . setHeader ( 'content-type' , 'application/json' )
@@ -660,7 +662,7 @@ test('serverless defaults', t => {
660662 t . plan ( 1 )
661663
662664 const Connection = connection . buildMockConnection ( {
663- onRequest ( opts ) {
665+ onRequest ( opts ) {
664666 t . equal ( opts . headers ?. [ 'elastic-api-version' ] , '2023-10-31' )
665667 return {
666668 statusCode : 200 ,
@@ -686,3 +688,112 @@ test('serverless defaults', t => {
686688
687689 t . end ( )
688690} )
691+
692+ test ( 'custom transport: class' , async t => {
693+ t . plan ( 3 )
694+
695+ class MyTransport extends Transport {
696+ async request ( params , options ) : Promise < any > {
697+ t . ok ( true , 'custom Transport request function should be called' )
698+ return super . request ( params , options )
699+ }
700+ }
701+
702+ function handler ( _req : http . IncomingMessage , res : http . ServerResponse ) {
703+ t . ok ( true , 'handler should be called' )
704+ res . end ( 'ok' )
705+ }
706+
707+ const [ { port } , server ] = await buildServer ( handler )
708+ t . after ( ( ) => server . stop ( ) )
709+
710+ const client = new Client ( {
711+ node : `http://localhost:${ port } ` ,
712+ Transport : MyTransport
713+ } )
714+
715+ t . ok ( client . transport instanceof MyTransport , 'Custom transport should be used' )
716+
717+ client . transport . request ( { method : 'GET' , path : '/' } )
718+ } )
719+
720+ test ( 'custom transport: disable otel via options' , async t => {
721+ const exporter = new InMemorySpanExporter ( )
722+ const processor = new SimpleSpanProcessor ( exporter )
723+ const provider = new BasicTracerProvider ( {
724+ spanProcessors : [ processor ]
725+ } )
726+ provider . register ( )
727+
728+ t . after ( async ( ) => {
729+ await provider . forceFlush ( )
730+ exporter . reset ( )
731+ await provider . shutdown ( )
732+ } )
733+
734+ class MyTransport extends Transport {
735+ async request ( params , options = { } ) : Promise < any > {
736+ // @ts -expect-error
737+ options . openTelemetry = { enabled : false }
738+ return super . request ( params , options )
739+ }
740+ }
741+
742+ function handler ( _req : http . IncomingMessage , res : http . ServerResponse ) {
743+ res . end ( 'ok' )
744+ }
745+
746+ const [ { port } , server ] = await buildServer ( handler )
747+ t . after ( ( ) => server . stop ( ) )
748+
749+ const client = new Client ( {
750+ node : `http://localhost:${ port } ` ,
751+ Transport : MyTransport
752+ } )
753+
754+ await client . transport . request ( {
755+ path : '/hello' ,
756+ method : 'GET' ,
757+ meta : { name : 'hello' } ,
758+ } )
759+
760+ t . equal ( exporter . getFinishedSpans ( ) . length , 0 )
761+ t . end ( )
762+ } )
763+
764+ test ( 'custom transport: disable otel via env var' , async t => {
765+ const exporter = new InMemorySpanExporter ( )
766+ const processor = new SimpleSpanProcessor ( exporter )
767+ const provider = new BasicTracerProvider ( {
768+ spanProcessors : [ processor ]
769+ } )
770+ provider . register ( )
771+
772+ t . after ( async ( ) => {
773+ await provider . forceFlush ( )
774+ exporter . reset ( )
775+ await provider . shutdown ( )
776+ } )
777+
778+ function handler ( _req : http . IncomingMessage , res : http . ServerResponse ) {
779+ res . end ( 'ok' )
780+ }
781+
782+ const [ { port } , server ] = await buildServer ( handler )
783+ t . after ( ( ) => server . stop ( ) )
784+
785+ const client = new Client ( {
786+ node : `http://localhost:${ port } ` ,
787+ } )
788+
789+ process . env . OTEL_ELASTICSEARCH_ENABLED = 'false'
790+
791+ await client . transport . request ( {
792+ path : '/hello' ,
793+ method : 'GET' ,
794+ meta : { name : 'hello' } ,
795+ } )
796+
797+ t . equal ( exporter . getFinishedSpans ( ) . length , 0 )
798+ t . end ( )
799+ } )
0 commit comments