Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ export class ApplicationInformationAttributeProvider implements BacktraceAttribu

private generateDefaultApplicationSearchPaths() {
const possibleSourcePaths = [process.cwd()];
const potentialCommandLineStartupFile = process.argv[1];
if (potentialCommandLineStartupFile) {
const potentialCommandLineStartupFilePath = path.resolve(potentialCommandLineStartupFile);
if (fs.existsSync(potentialCommandLineStartupFilePath)) {
possibleSourcePaths.unshift(potentialCommandLineStartupFilePath);
}
}
if (require.main?.path) {
possibleSourcePaths.unshift(path.dirname(require.main.path));
}
Expand Down
18 changes: 2 additions & 16 deletions packages/sdk-core/src/model/http/BacktraceReportSubmission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,15 @@ import { BacktraceAttachment } from '../attachment';
import { BacktraceConfiguration } from '../configuration/BacktraceConfiguration';
import { BacktraceData } from '../data/BacktraceData';
import { BacktraceRequestHandler } from './BacktraceRequestHandler';
import { SubmissionUrlInformation } from './SubmissionUrlInformation';

export class BacktraceReportSubmission {
private readonly _submissionUrl: string;
constructor(options: BacktraceConfiguration, private readonly _requestHandler: BacktraceRequestHandler) {
this._submissionUrl = this.generateReportSubmissionUrl(options.url, options.token);
this._submissionUrl = SubmissionUrlInformation.toJsonReportSubmissionUrl(options.url, options.token);
}

public send(data: BacktraceData, attachments: BacktraceAttachment[]) {
return this._requestHandler.postError(this._submissionUrl, data, attachments);
}

private generateReportSubmissionUrl(url: string, token?: string) {
// if the token doesn't exist - use URL
if (!token) {
return url;
}

// if the URL has token in the URL, the user probably added a token once again
// in this case, don't do anything
if (url.indexOf(token) !== -1) {
return url;
}

return new URL(`/post?format=json&token=${token}`, url).href;
}
}
74 changes: 74 additions & 0 deletions packages/sdk-core/src/model/http/SubmissionUrlInformation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
export class SubmissionUrlInformation {
private static SUBMIT_PREFIX = 'submit.backtrace.io/';

/**
* Convert url/token from credentials to JSON submission URL
* @param url credentials URL
* @param token credentials token
* @returns JSON submissionURL
*/
public static toJsonReportSubmissionUrl(url: string, token?: string): string {
// if the token doesn't exist - use URL
if (!token) {
return url;
}

// if the url points to submit, we should always use it without any modifications
if (url.includes(this.SUBMIT_PREFIX)) {
return url;
}

// if the URL has token in the URL, the user probably added a token once again
// in this case, don't do anything
if (url.indexOf(token) !== -1) {
return url;
}

const result = new URL(`/post`, url);
result.searchParams.append('format', 'json');
result.searchParams.append('token', token);
return result.href;
}

/**
* Find the universe based on the submission URL
* @param submissionUrl submission URL
* @returns universe name
*/
public static findUniverse(submissionUrl: string): string | undefined {
const submitIndex = submissionUrl.indexOf(this.SUBMIT_PREFIX);
if (submitIndex !== -1) {
// submit format URL
// submit.backtrace.io/universe/token/format
// we can expect the universe name just after the hostname
const universeStartIndex = submitIndex + this.SUBMIT_PREFIX.length;
const endOfUniverseName = submissionUrl.indexOf('/', universeStartIndex);
return submissionUrl.substring(universeStartIndex, endOfUniverseName);
}
// the universe name should be available in the hostname
// for example abc.sp.backtrace.io or zyx.in.backtrace.io or foo.backtrace.io
const hostname = new URL(submissionUrl).hostname;
if (!hostname.endsWith('backtrace.io')) {
return undefined;
}

const endOfUniverseName = hostname.indexOf('.');
return hostname.substring(0, endOfUniverseName);
}

public static findToken(submissionUrl: string): string | null {
const submitIndex = submissionUrl.indexOf(this.SUBMIT_PREFIX);
if (submitIndex !== -1) {
const submissionUrlParts = submissionUrl.split('/');
// submit format URL
// submit.backtrace.io/universe/token/format
// by spliting the submission URL by `/` and dropping the last
// part of the URL, the last element on the list is the token.
return submissionUrlParts[submissionUrlParts.length - 2];
}

const url = new URL(submissionUrl);

return url.searchParams.get('token');
}
}
1 change: 1 addition & 0 deletions packages/sdk-core/src/model/http/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './common/ConnectionError';
export * from './model/BacktraceSubmissionResponse';
export * from './model/BacktraceSubmissionResult';
export * from './model/BacktraceSubmissionStatus';
export * from './SubmissionUrlInformation';
64 changes: 64 additions & 0 deletions packages/sdk-core/src/modules/metrics/MetricsUrlInformation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { SubmissionUrlInformation } from '../../model/http';

export class MetricsUrlInformation {
public static generateSummedEventsUrl(
hostname: string,
submissionUrl: string,
credentialsToken: string | null,
): string | undefined {
const submissionInformation = this.findSubmissionInformation(submissionUrl, credentialsToken);
if (!submissionInformation) {
return undefined;
}
return this.generateEventsServiceUrl(
hostname,
'summed-events',
submissionInformation.universe,
submissionInformation.token,
);
}

public static generateUniqueEventsUrl(
hostname: string,
submissionUrl: string,
credentialsToken: string | null,
): string | undefined {
const submissionInformation = this.findSubmissionInformation(submissionUrl, credentialsToken);
if (!submissionInformation) {
return undefined;
}

return this.generateEventsServiceUrl(
hostname,
'unique-events',
submissionInformation.universe,
submissionInformation.token,
);
}

private static generateEventsServiceUrl(
hostname: string,
eventServiceName: string,
universe: string,
token: string,
): string {
return new URL(`/api/${eventServiceName}/submit?universe=${universe}&token=${token}`, hostname).toString();
}

private static findSubmissionInformation(
submissionUrl: string,
token: string | null,
): { universe: string; token: string } | undefined {
const universe = SubmissionUrlInformation.findUniverse(submissionUrl);
if (!universe) {
return undefined;
}

token = token ?? SubmissionUrlInformation.findToken(submissionUrl);

if (!token) {
return undefined;
}
return { universe, token };
}
}
37 changes: 37 additions & 0 deletions packages/sdk-core/tests/http/submissionUrlGenerationTests.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { SubmissionUrlInformation } from '../../src/model/http';
describe('Submission Url generation tests', () => {
describe('Submit', () => {
const sampleSubmitUrl = `https://submit.backtrace.io/name/000000000000a1eb7ae344f6e002de2e20c81fbdedf6991c2f3bb45b11111111/json`;
it('Should use submit url from the configuration options', () => {
expect(SubmissionUrlInformation.toJsonReportSubmissionUrl(sampleSubmitUrl)).toBe(sampleSubmitUrl);
});

it(`Shouldnt mix token with the submission url`, () => {
expect(SubmissionUrlInformation.toJsonReportSubmissionUrl(sampleSubmitUrl, '123')).toBe(sampleSubmitUrl);
});
});

describe('Direct URL', () => {
const hostname = `https://instance.sp.backtrace.io`;
const token = `000000000000a1eb7ae344f6e002de2e20c81fbdedf6991c2f3bb45b11111111`;
const fullUrl = `${hostname}/post?format=json&token=${token}`;
it('Should use the direct url if the token is not available', () => {
expect(SubmissionUrlInformation.toJsonReportSubmissionUrl(fullUrl)).toBe(fullUrl);
});

it(`Shouldn't mix token with the submission url if the token is already there`, () => {
expect(SubmissionUrlInformation.toJsonReportSubmissionUrl(fullUrl, token)).toBe(fullUrl);
});

it(`Should generate a full url if the token and instance are passed separated`, () => {
expect(SubmissionUrlInformation.toJsonReportSubmissionUrl(hostname, token)).toBe(fullUrl);
});

it(`Should override the token in the submission url`, () => {
const testedToken = '111111110000000000001111111100000000000020c81fbdedf6991c2f3bb45b';
const expectedUrl = `${hostname}/post?format=json&token=${testedToken}`;

expect(SubmissionUrlInformation.toJsonReportSubmissionUrl(fullUrl, testedToken)).toBe(expectedUrl);
});
});
});
24 changes: 24 additions & 0 deletions packages/sdk-core/tests/http/tokenTests.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { SubmissionUrlInformation } from '../../src/model/http';

describe('Token tests', () => {
const testedToken = '000000000000a1eb7ae344f6e002de2e20c81fbdedf6991c2f3bb45b11111111';
describe('Submit', () => {
const sampleSubmitUrl = `https://submit.backtrace.io/test/${testedToken}/json`;

it('Should correctly find the universe name', () => {
expect(SubmissionUrlInformation.findToken(sampleSubmitUrl)).toBe(testedToken);
});
});

describe('Direct', () => {
it(`Should return null if the url doesn't contain the submission token`, () => {
expect(SubmissionUrlInformation.findToken(`https://foo.sp.backtrace.io`)).toBeNull();
});

it(`Should return token from the direct url`, () => {
expect(
SubmissionUrlInformation.findToken(`https://foo.sp.backtrace.io/post?format=json&token=${testedToken}`),
).toBe(testedToken);
});
});
});
26 changes: 26 additions & 0 deletions packages/sdk-core/tests/http/universeTests.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { SubmissionUrlInformation } from '../../src/model/http';
describe('Universe tests', () => {
const testedUniverseName = 'foo-bar-baz';
describe('Submit', () => {
const sampleSubmitUrl = `https://submit.backtrace.io/${testedUniverseName}/000000000000a1eb7ae344f6e002de2e20c81fbdedf6991c2f3bb45b11111111/json`;

it('Should correctly find the universe name', () => {
expect(SubmissionUrlInformation.findUniverse(sampleSubmitUrl)).toBe(testedUniverseName);
});
});

describe('Direct', () => {
const testedBacktraceDomainPrefixes = ['', '.sp', '.in'];
for (const backtracePrefix of testedBacktraceDomainPrefixes) {
it(`Should correctly find the universe name with prefix ${backtracePrefix}`, () => {
const sampleDirectUrl = `https://${testedUniverseName}${backtracePrefix}.backtrace.io`;
expect(SubmissionUrlInformation.findUniverse(sampleDirectUrl)).toBe(testedUniverseName);
});
}

it('Should correctly find the universe in the direct url with the token', () => {
const sampleDirectUrl = `https://${testedUniverseName}.sp.backtrace.io/post?format=json&token=000000000000a1eb7ae344f6e002de2e20c81fbdedf6991c2f3bb45b11111111`;
expect(SubmissionUrlInformation.findUniverse(sampleDirectUrl)).toBe(testedUniverseName);
});
});
});