All files / Scripts Errors.ts

50.74% Statements 34/67
40% Branches 22/55
33.33% Functions 3/9
41.17% Lines 21/51

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 1079x 9x 9x   9x   9x                                         18x       13x 13x 10x 6x         2x                                                                                                     16x 12x 9x 5x 2x       7x 6x 4x 2x 1x        
import { diagnostics } from "./Diag";
import { Stack } from "./stacks";
import { Strings } from "./Strings";
 
let errorArray: string[] = [];
 
export class Errors {
    public static clear(): void { errorArray = []; }
 
    public static get() { return errorArray; }
 
    public static add(eventName: string, stack: string[], suppressTracking: boolean): void {
        Iif (eventName || stack) {
            const stackString = Strings.joinArray(stack, "\n");
            errorArray.push(Strings.joinArray([eventName, stackString], "\n"));
 
            Iif (!suppressTracking) {
                diagnostics.trackEvent({ name: eventName },
                    {
                        stack: stackString,
                        source: "Errors.add"
                    });
            }
        }
    }
 
    public static isError(error: unknown): boolean {
        if (!error) return false;
 
        // We can't afford to throw while checking if we're processing an error
        // So just swallow any exception and fail.
        try {
            if (typeof (error) === "string") return false;
            if (typeof (error) === "number") return false;
            if (typeof error === "object" && "stack" in error) return true;
        } catch (e) {
            diagnostics.trackEvent({ name: "isError exception with error", properties: { error: JSON.stringify(e) } });
        }
 
        return false;
    }
 
    // error - an exception object
    // message - a string describing the error
    // suppressTracking - boolean indicating if we should suppress tracking
    public static log(error: unknown, message: string, suppressTracking?: boolean): void {
        Iif (error && !suppressTracking) {
            const event = { name: "Errors.log" };
            const props = {
                message: message,
                error: JSON.stringify(error, null, 2),
                source: "",
                stack: "",
                description: "",
                errorMessage: ""
            };
 
            if (Errors.isError(error) && (error as { exception?: unknown }).exception) {
                props.source = "Error.log Exception";
                event.name = "Exception";
            }
            else {
                props.source = "Error.log Event";
                Iif (typeof error === "object" && "description" in error) props.description = (error as { description: string }).description;
                Iif (typeof error === "object" && "message" in error) props.errorMessage = (error as { message: string }).message;
                Iif (typeof error === "object" && "stack" in error) props.stack = (error as { stack: string }).stack;
                if (typeof error === "object" && "description" in error) {
                    event.name = (error as { description: string }).description;
                } else if (typeof error === "object" && "message" in error) {
                    event.name = (error as { message: string }).message;
                } else if (props.message) {
                    event.name = props.message;
                } else {
                    event.name = "Unknown error object";
                }
            }
 
            diagnostics.trackException(event, props);
        }
 
        Stack.parse(error, message, function (eventName: string, stack: string[]): void {
            Errors.add(eventName, stack, suppressTracking ?? false);
        });
    }
 
    public static logMessage(message:string): void {
        Errors.add(message, [], true);
    }
 
    public static getErrorMessage(error: unknown): string {
        if (!error) return "";
        if (typeof (error) === "string") return error;
        if (typeof (error) === "number") return error.toString();
        if (typeof error === "object" && error !== null && "message" in error) return (error as Error).message;
        return JSON.stringify(error, null, 2);
    }
 
    public static getErrorStack(error: unknown): string {
        if (!error) return "";
        if (typeof (error) === "string") return "string thrown as error";
        if (typeof (error) === "number") return "number thrown as error";
        if (!Errors.isError(error)) return "";
        if (typeof error === "object" && error !== null && "stack" in error) return (error as Error).stack ?? "";
        return "";
    }
}