Search code examples
javascriptnode.jsjsontypescriptsentry

Convert JSON (from Sentry) to HTML with TypeScript


I want to learn TypeScript.

I have a JSON dictionary returned by the sentry method event_from_exception() (Python).

I would like to format it as nice HTML with expandable local variables and pre_ and post_context. The result should look roughly like this:

traceback-in-django-debug-view

Here is an example json:

{
  "exception": {
    "values": [
      {
        "stacktrace": {
          "frames": [
            {
              "function": "main", 
              "abs_path": "/home/modlink_cok_d/src/sentry-json.py", 
              "pre_context": [
                "from sentry_sdk.utils import event_from_exception", 
                "", 
                "def main():", 
                "    local_var = 1", 
                "    try:"
              ], 
              "lineno": 9, 
              "vars": {
                "exc": "ValueError()", 
                "local_var": "1"
              }, 
              "context_line": "        raise ValueError()", 
              "post_context": [
                "    except Exception as exc:", 
                "        event, info = event_from_exception(sys.exc_info(), with_locals=True)", 
                "        print(json.dumps(event, indent=2))", 
                "", 
                "main()"
              ], 
              "module": "__main__", 
              "filename": "sentry-json.py"
            }
          ]
        }, 
        "type": "ValueError", 
        "value": "", 
        "module": "exceptions", 
        "mechanism": null
      }
    ]
  }, 
  "level": "error"
}

How could this be done with TypeScript?


Solution

    1. Create the schema for your data. This will help you on working with TypeScript and IDE.

    You can use https://app.quicktype.io which give you.

    export interface Welcome {
        exception: Exception;
        level:     string;
    }
    
    export interface Exception {
        values: Value[];
    }
    
    export interface Value {
        stacktrace: Stacktrace;
        type:       string;
        value:      string;
        module:     string;
        mechanism:  null;
    }
    
    export interface Stacktrace {
        frames: Frame[];
    }
    
    export interface Frame {
        function:     string;
        abs_path:     string;
        pre_context:  string[];
        lineno:       number;
        vars:         Vars;
        context_line: string;
        post_context: string[];
        module:       string;
        filename:     string;
    }
    
    export interface Vars {
        exc:       string;
        local_var: string;
    }
    
    1. Render HTML from your data.

    You can use template literal if you do not have prefer web framework (React, Vue).

    const data = JSON.parse(json);
    const html = `
        <div>${data.exception.values.map(value => `
            <div>${value.stacktrace.frames.map(frame => `
                <div>
                    <pre>${frame.abs_path} in ${frame.function}</pre>
                    <div style="margin-left:2rem">
                        ${frame.pre_context.map((line, i) =>`
                            <pre>${frame.lineno + i - frame.pre_context.length}. ${line}</pre>
                        `).join("")}
    
                        <pre><strong>${frame.lineno}. ${frame.context_line}</strong></pre>
                        ${frame.post_context.map((line, i) => `
                            <pre>${frame.lineno + i + 1}. ${line}</pre>
                        `).join("")}
                    </div>
                </div>
            `).join("")}</div>
        `).join("")}</div>
    `;
    document.body.innerHTML = html;
    

    For example: https://codesandbox.io/s/52x8r17zo4