@@ -102,10 +102,10 @@ function getExecContext(span: Span) {
102102}
103103
104104/**
105- * Extracts URL path for debugging purposes (especially useful for Azure)
105+ * Extracts URL attributes for debugging purposes (especially useful for Azure)
106106 * @param fullUrl The complete URL of the request
107107 * @param baseUrl The base URL of the client
108- * @returns Object containing URL path for debugging
108+ * @returns Object containing URL attributes for debugging
109109 */
110110function getUrlAttributes (
111111 fullUrl : string ,
@@ -116,38 +116,67 @@ function getUrlAttributes(
116116 try {
117117 const url = new URL ( fullUrl ) ;
118118
119- // Extract URL components for debugging (path and api_version only)
119+ // Always include the full URL for complete debugging context
120+ attributes [ "url.full" ] = fullUrl ;
120121
121- // Extract the path (URL - baseURL) as requested: path = full - base_url
122+ // Extract the path component
122123 if ( baseUrl ) {
123124 try {
124125 const baseUrlObj = new URL ( baseUrl ) ;
125126 const fullUrlObj = new URL ( fullUrl ) ;
126127
127128 // If the hosts match, calculate the path difference
128129 if ( baseUrlObj . hostname === fullUrlObj . hostname ) {
129- // Calculate the relative path by removing the base path from the full path
130- const basePath = baseUrlObj . pathname . replace ( / \/ $ / , "" ) ;
130+ // For Azure OpenAI, we want to reconstruct the deployment path
131+ // baseUrl example: "https://example.openai.azure.com/openai/deployments/gpt-4"
132+ // fullUrl example: "https://example.openai.azure.com/chat/completions"
133+ // We want to extract the deployment info from baseUrl and combine with the endpoint
134+
135+ const basePath = baseUrlObj . pathname ;
131136 const fullPath = fullUrlObj . pathname ;
132137
133- if ( fullPath . startsWith ( basePath ) ) {
134- // Remove base path to get the relative path
135- const relativePath = fullPath . substring ( basePath . length ) || "/" ;
136- attributes [ "url.path" ] = relativePath ;
138+ // Extract deployment information from the base URL
139+ if ( basePath . includes ( "/deployments/" ) ) {
140+ // Extract the deployment part: "deployments/model-name"
141+ const deploymentMatch = basePath . match ( / \/ d e p l o y m e n t s \/ ( [ ^ / ] + ) / ) ;
142+ if ( deploymentMatch ) {
143+ const deploymentName = deploymentMatch [ 1 ] ;
144+ const endpoint = fullPath . startsWith ( "/" )
145+ ? fullPath . substring ( 1 )
146+ : fullPath ;
147+ attributes [ "url.path" ] =
148+ `deployments/${ deploymentName } /${ endpoint } ` ;
149+ } else {
150+ // Fallback to just the endpoint
151+ attributes [ "url.path" ] = fullPath . startsWith ( "/" )
152+ ? fullPath . substring ( 1 )
153+ : fullPath ;
154+ }
137155 } else {
138- // If paths don't align, use the full path
139- attributes [ "url.path" ] = fullPath ;
156+ // Not a deployment URL, use the full path
157+ attributes [ "url.path" ] = fullPath . startsWith ( "/" )
158+ ? fullPath . substring ( 1 )
159+ : fullPath ;
140160 }
141161 } else {
142- // Different hosts, use pathname
143- attributes [ "url.path" ] = url . pathname ;
162+ // Different hosts, use pathname without leading slash
163+ const pathname = url . pathname . startsWith ( "/" )
164+ ? url . pathname . substring ( 1 )
165+ : url . pathname ;
166+ attributes [ "url.path" ] = pathname || "/" ;
144167 }
145168 } catch {
146169 // If URL parsing fails, use the pathname
147- attributes [ "url.path" ] = url . pathname ;
170+ const pathname = url . pathname . startsWith ( "/" )
171+ ? url . pathname . substring ( 1 )
172+ : url . pathname ;
173+ attributes [ "url.path" ] = pathname || "/" ;
148174 }
149175 } else {
150- attributes [ "url.path" ] = url . pathname ;
176+ const pathname = url . pathname . startsWith ( "/" )
177+ ? url . pathname . substring ( 1 )
178+ : url . pathname ;
179+ attributes [ "url.path" ] = pathname || "/" ;
151180 }
152181
153182 // Safely extract api_version query parameter for Azure
@@ -390,7 +419,20 @@ export class OpenAIInstrumentation extends InstrumentationBase<typeof openai> {
390419 }
391420
392421 if ( baseUrl ) {
393- const fullUrl = new URL ( path , baseUrl ) . toString ( ) ;
422+ // Construct the full URL with query parameters if available
423+ let fullUrl = new URL ( path , baseUrl ) . toString ( ) ;
424+
425+ // Add query parameters if they exist in options
426+ if ( options ?. query && typeof options . query === "object" ) {
427+ const url = new URL ( fullUrl ) ;
428+ Object . entries ( options . query ) . forEach ( ( [ key , value ] ) => {
429+ if ( value !== undefined && value !== null ) {
430+ url . searchParams . set ( key , String ( value ) ) ;
431+ }
432+ } ) ;
433+ fullUrl = url . toString ( ) ;
434+ }
435+
394436 // Store URL info using the current active span context
395437 const activeSpan = trace . getActiveSpan ( ) ;
396438 if ( activeSpan ) {
0 commit comments