Skip to content

Commit

Permalink
Use real upload call for "sourcemaps upload" with error handling (#69)
Browse files Browse the repository at this point in the history
* Use real upload call for "sourcemaps upload" with error handling

Tested locally, with custom headers (not in PR)
  • Loading branch information
mvirgil authored Jan 13, 2025
1 parent 49ab8cc commit aaec3d9
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 13 deletions.
36 changes: 27 additions & 9 deletions src/sourcemaps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ import { computeSourceMapId } from './computeSourceMapId';
import { injectFile } from './injectFile';
import { Logger } from '../utils/logger';
import { Spinner } from '../utils/spinner';
import { mockUploadFile } from '../utils/httpUtils';
import { uploadFile } from '../utils/httpUtils';
import { AxiosError } from 'axios';

export type SourceMapInjectOptions = {
directory: string;
Expand Down Expand Up @@ -141,22 +142,22 @@ export async function runSourcemapUpload(options: SourceMapUploadOptions, ctx: S
let success = 0;
let failed = 0;

logger.info('Upload URL: %s', `https://api.${realm}.signalfx.com/v1/sourcemap/id/{id}`);
logger.info('Upload URL: %s', getSourceMapUploadUrl(realm, '{id}'));
logger.info('Found %s source maps to upload', jsMapFilePaths.length);
spinner.start('');
for (let i = 0; i < jsMapFilePaths.length; i++) {
const filesRemaining = jsMapFilePaths.length - i;
const path = jsMapFilePaths[i];
const sourceMapId = await computeSourceMapId(path, { directory });
const url = `https://api.${realm}.signalfx.com/v1/sourcemap/id/${sourceMapId}`;
const url = getSourceMapUploadUrl(realm, sourceMapId);
const file = {
filePath: path,
fieldName: 'file'
};

const parameters = Object.fromEntries([
['appName', appName],
['appVersion', appVersion],
['sourceMapId', sourceMapId],
// eslint-disable-next-line @typescript-eslint/no-unused-vars
].filter(([_, value]) => typeof value !== 'undefined'));

Expand All @@ -167,7 +168,7 @@ export async function runSourcemapUpload(options: SourceMapUploadOptions, ctx: S

// upload a single file
try {
await mockUploadFile({
await uploadFile({
url,
file,
onProgress: ({ loaded, total }) => {
Expand All @@ -176,26 +177,43 @@ export async function runSourcemapUpload(options: SourceMapUploadOptions, ctx: S
parameters
});
success++;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {
logger.error('Upload failed for %s', path);
failed++;
spinner.stop();

const ae = e as AxiosError;
if (ae.response) {
logger.error(ae.response.status, ae.response.statusText);
logger.error(ae.response.data);
} else if (ae.request) {
logger.error(`Response from ${url} was not received`);
logger.error(ae.cause);
} else {
logger.error(`Request to ${url} could not be sent`);
logger.error(e);
}
logger.error('Upload failed for %s', path);
}
}
spinner.stop();

/*
* Print summary of results
*/
logger.info(`${success} source maps were uploaded successfully`);
logger.info(`${success} source map(s) were uploaded successfully`);
if (failed > 0) {
logger.info(`${failed} source maps could not be uploaded`);
logger.info(`${failed} source map(s) could not be uploaded`);
}
if (jsMapFilePaths.length === 0) {
logger.warn(`No source map files were found. Verify that ${directory} is the correct directory for your source map files.`);
}
}

function getSourceMapUploadUrl(realm: string, idPathParam: string): string {
const API_BASE_URL = process.env.O11Y_API_BASE_URL || `https://api.${realm}.signalfx.com`;
return `${API_BASE_URL}/v1/sourcemaps/id/${idPathParam}`;
}

function throwDirectoryReadErrorDuringInject(err: unknown, directory: string): never {
throwAsUserFriendlyErrnoException(
err,
Expand Down
2 changes: 1 addition & 1 deletion src/utils/httpUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const uploadFile = async ({ url, file, parameters, onProgress }: UploadOp

const fileSizeInBytes = fs.statSync(file.filePath).size;

await axios.post(url, formData, {
await axios.put(url, formData, {
headers: {
...formData.getHeaders(),
},
Expand Down
6 changes: 3 additions & 3 deletions test/utils/httpUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ afterEach(() => {
describe('uploadFile', () => {

test('should upload a file and report progress', async () => {
jest.spyOn(axios, 'post').mockResolvedValue({
jest.spyOn(axios, 'put').mockResolvedValue({
data: { success: true }
});

Expand Down Expand Up @@ -65,7 +65,7 @@ describe('uploadFile', () => {
});

test('should throw axios errors during upload', async () => {
jest.spyOn(axios, 'post').mockRejectedValue(new Error('Axios error during upload'));
jest.spyOn(axios, 'put').mockRejectedValue(new Error('Axios error during upload'));

await expect(uploadFile({
url: 'http://splunko11ycloud.com/upload',
Expand All @@ -85,7 +85,7 @@ describe('uploadFile', () => {
});

it('should upload a file without progress reporting when onProgress is not provided', async () => {
jest.spyOn(axios, 'post').mockResolvedValue({
jest.spyOn(axios, 'put').mockResolvedValue({
data: { success: true }
});

Expand Down

0 comments on commit aaec3d9

Please sign in to comment.