11import { URL } from 'node:url' ;
22
33import { encode } from '@datadog/pprof' ;
4- import axios , { AxiosBasicCredentials , AxiosError } from 'axios' ;
5- import FormData , { Headers } from 'form-data' ;
64import { Profile } from 'pprof-format' ;
75import { ProfileExport , ProfileExporter } from './profile-exporter.js' ;
86import { dateToUnixTimestamp } from './utils/date-to-unix-timestamp.js' ;
@@ -58,15 +56,22 @@ export class PyroscopeApiExporter implements ProfileExporter {
5856 return endpointUrl ;
5957 }
6058
61- private buildRequestHeaders ( formData : FormData ) : Headers {
62- const headers : Headers = formData . getHeaders ( ) ;
59+ private buildRequestHeaders ( ) : Headers {
60+ const headers : Headers = new Headers ( ) ;
6361
6462 if ( this . authToken !== undefined ) {
65- headers [ 'authorization' ] = `Bearer ${ this . authToken } ` ;
63+ headers . set ( 'authorization' , `Bearer ${ this . authToken } ` ) ;
64+ } else if ( this . config . basicAuthUser && this . config . basicAuthPassword ) {
65+ headers . set (
66+ 'authorization' ,
67+ Buffer . from (
68+ `${ this . config . basicAuthUser } :${ this . config . basicAuthPassword } `
69+ ) . toString ( 'base64' )
70+ ) ;
6671 }
6772
6873 if ( this . config . tenantID ) {
69- headers [ 'X-Scope-OrgID' ] = this . config . tenantID ;
74+ headers . set ( 'X-Scope-OrgID' , this . config . tenantID ) ;
7075 }
7176
7277 return headers ;
@@ -81,54 +86,36 @@ export class PyroscopeApiExporter implements ProfileExporter {
8186
8287 const formData : FormData = new FormData ( ) ;
8388
84- formData . append ( 'profile' , profileBuffer , {
85- contentType : 'text/json' ,
86- filename : 'profile' ,
87- knownLength : profileBuffer . byteLength ,
88- } ) ;
89+ formData . append ( 'profile' , new Blob ( [ profileBuffer ] ) , 'profile' ) ;
8990
9091 return formData ;
9192 }
9293
93- private handleAxiosError ( error : AxiosError ) : void {
94- if ( error . response !== undefined ) {
95- // The request was made and the server responded with a status code
96- // that falls out of the range of 2xx
97- log ( 'Pyroscope received error while ingesting data to server' ) ;
98- log ( error . response . data ) ;
99- } else if ( error . request !== undefined ) {
100- // The request was made but no response was received
101- // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
102- // http.ClientRequest in node.js
103- log ( 'Error when ingesting data to server:' , error . message ) ;
104- } else {
105- // Something happened in setting up the request that triggered an Error
106- log ( 'Error' , error . message ) ;
107- }
108- }
109-
11094 private async uploadProfile ( profileExport : ProfileExport ) : Promise < void > {
11195 const formData : FormData = await this . buildUploadProfileFormData (
11296 profileExport . profile
11397 ) ;
11498
115- const auth : AxiosBasicCredentials | undefined =
116- this . config . basicAuthUser && this . config . basicAuthPassword
117- ? {
118- username : this . config . basicAuthUser ,
119- password : this . config . basicAuthPassword ,
120- }
121- : undefined ;
122-
12399 try {
124- await axios ( this . buildEndpointUrl ( profileExport ) . toString ( ) , {
125- data : formData ,
126- headers : this . buildRequestHeaders ( formData ) ,
127- method : 'POST' ,
128- auth : auth ,
129- } ) ;
100+ const response = await fetch (
101+ this . buildEndpointUrl ( profileExport ) . toString ( ) ,
102+ {
103+ body : formData ,
104+ headers : this . buildRequestHeaders ( ) ,
105+ method : 'POST' ,
106+ }
107+ ) ;
108+
109+ if ( ! response . ok ) {
110+ log ( 'Server rejected data ingest: HTTP %d' , response . status ) ;
111+ log ( await response . text ( ) ) ;
112+ }
130113 } catch ( error : unknown ) {
131- this . handleAxiosError ( error as AxiosError ) ;
114+ if ( error instanceof Error ) {
115+ log ( 'Error sending data ingest: %s' , error . message ) ;
116+ } else {
117+ log ( 'Unknown error sending data ingest' ) ;
118+ }
132119 }
133120 }
134121}
0 commit comments