Skip to content

Commit

Permalink
✨ back,front: report client errors to the server (#714)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericlinagora committed Nov 11, 2024
1 parent 746eab2 commit d1d1620
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 0 deletions.
25 changes: 25 additions & 0 deletions tdrive/backend/node/src/services/user/web/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { formatCompany, getCompanyStats } from "../utils";
import { formatUser } from "../../../utils/users";
import gr from "../../global-resolver";
import config from "config";
import { getLogger } from "../../../core/platform/framework";

export class UsersCrudController
implements
Expand Down Expand Up @@ -93,6 +94,30 @@ export class UsersCrudController
};
}

/** This allows a logged in user to upload log entries */
async reportClientLog(
request: FastifyRequest<{ Body: { [key: string]: string } }>,
): Promise<object> {
const headers = { ...request.headers };
const boringOrSecretHeaders =
"cookie authorization cache-control connection pragma content-length content-type accept accept-encoding accept-language".split(
/\s+/g,
);
boringOrSecretHeaders.forEach(header => delete headers[header]);
const message =
request.body.message ||
"(missing message property in UsersCrudController.reportClientLog request body)";
delete request.body.message;
getLogger("FromBrowser").error(
{
headers,
...request.body,
},
message,
);
return {};
}

async setPreferences(
request: FastifyRequest<{ Body: User["preferences"] }>,
): Promise<User["preferences"]> {
Expand Down
10 changes: 10 additions & 0 deletions tdrive/backend/node/src/services/user/web/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
getUserSchema,
getUsersSchema,
postDevicesSchema,
sendUserClientReportSchema,
setUserPreferencesSchema,
} from "./schemas";

Expand Down Expand Up @@ -52,6 +53,15 @@ const routes: FastifyPluginCallback = (fastify: FastifyInstance, options, next)
handler: usersController.setPreferences.bind(usersController),
});

fastify.route({
method: "POST",
url: `${usersUrl}/me/reportLog`,
preHandler: accessControl,
preValidation: [fastify.authenticate],
schema: sendUserClientReportSchema,
handler: usersController.reportClientLog.bind(usersController),
});

fastify.route({
method: "POST",
url: `${usersUrl}/me`,
Expand Down
13 changes: 13 additions & 0 deletions tdrive/backend/node/src/services/user/web/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,19 @@ export const setUserPreferencesSchema = {
},
};

export const sendUserClientReportSchema = {
request: {
type: "object",
properties: {
message: { type: "string" },
},
required: ["message"],
},
response: {
"2xx": {},
},
};

export const getUsersSchema = {
type: "object",
properties: {
Expand Down
31 changes: 31 additions & 0 deletions tdrive/frontend/src/app/features/users/api/user-api-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import CurrentUser from '../../../deprecated/user/CurrentUser';
import { setUserList } from '../hooks/use-user-list';
import Logger from 'features/global/framework/logger-service';
import { UserQuota } from "features/users/types/user-quota";
import version from '../../../environment/version';

export type SearchContextType = {
scope: 'company' | 'workspace' | 'all';
Expand Down Expand Up @@ -142,6 +143,30 @@ class UserAPIClientService {
});
}

/** Send log entry to the server's logs. Try to include a `message` property please */
async reportLog(body: any | { message: string, error?: Error, err?: Error, e?: Error, }): Promise<void> {
const actualBody = {
version: version.version_detail || version.version,
...body,
} as any;
for (const [key, val] of Object.entries(actualBody)) {
const error = val as Error;
if ((error as Error).stack) {
actualBody[key] = {
message: error.message,
stack: error.stack,
error,
};
if (!actualBody.message) actualBody.message = "Error: " + error.message;
}
}
if (!actualBody.message) actualBody.message = "(missing message property in UserAPIClient.reportLog)";
return Api.post<object, {}>(
'/internal/services/users/v1/users/me/reportLog',
actualBody,
).then(result => undefined);
}

async getQuota(companyId: string, userId: string): Promise<UserQuota> {
return Api.get<UserQuota>(
`/internal/services/users/v1/users/${userId}/quota?companyId=${companyId}`,
Expand Down Expand Up @@ -255,4 +280,10 @@ class UserAPIClientService {
}
}
const UserAPIClient = new UserAPIClientService();

window.onerror = (message, url, line, col, error) => {
UserAPIClient.reportLog({ message, url, line, col, error });
return false; // don't suppress normal alert
}

export default UserAPIClient;

0 comments on commit d1d1620

Please sign in to comment.