Skip to content
This repository was archived by the owner on Jan 14, 2021. It is now read-only.
This repository was archived by the owner on Jan 14, 2021. It is now read-only.

Basic reporting capability for runtime errors in Client  #661

@albertoperdomo

Description

@albertoperdomo

Problem

When controlled errors occur in Prisma, our software control these and bubble up these to developers, so they can address them, i.e. via a helpful error message. Our software will try to handle all known errors gracefully but inevitably, there will be unexpected errors or issues we haven't yet thought of or encountered.

When these uncontrolled errors happen, our software can't offer much help to the developer. Often, these issues will cause crashes which may require restarting some or all of the Prisma runtime.
These errors can be frustrating and/or blocking for users. In order to improve our software, we need to be aware of errors and have enough context to address them.

There is a system that enables developers to submit errors when using Prisma CLI or Prisma Studio, but reporting issues that occur in Prisma Client has significant friction.

Solution

  • Improve our documentation on how to report issues (guide in docs)
  • Implement an in-memory cache to store the most recent log output (2-3h eng. work)
  • Improve the debug output for increased discoverability (2-3h eng. work)
    • better error message (see #610)
    • easier to locate the errors
    • easier to understand which excerpt of the logfile needs to be submitted
  • (Optional) Include a clickable URL pointing to GitHub interpolating the content in the URL, so that the issue form is auto-filled with the information needed (library for GH issues, libraries for making links clickable in CLI )

Example of potential error output:

##################################
##################################
# Start Prisma Error Report
prisma-client {
  prisma-client   engineConfig: {
  prisma-client     cwd: '/Users/tim/code/prisma-client-performance/prisma',
  prisma-client     debug: false,
  prisma-client     datamodelPath: '/Users/tim/code/prisma-client-performance/@prisma/client/schema.prisma',
  prisma-client     prismaPath: undefined,
  prisma-client     datasources: [ [Object] ],
  prisma-client     generator: {
  prisma-client       name: 'client',
  prisma-client       provider: 'prisma-client-js',
  prisma-client       output: null,
  prisma-client       binaryTargets: [],
  prisma-client       config: {}
  prisma-client     },
  prisma-client     showColors: false,
  prisma-client     logLevel: undefined,
  prisma-client     logQueries: undefined,
  prisma-client     env: {},
  prisma-client     flags: []
  prisma-client   }
  prisma-client } +0ms
  printStack callsite undefined +0ms
  printStack {
  printStack   introText: '\u001b[31mInvali2d \u001b[1m`prisma.user.findMany()`\u001b[22m invocation:\u001b[39m',
  printStack   prevLines: '\n',
  printStack   afterLines: '',
  printStack   lastErrorHeight: 20,
  printStack   indentValue: 0,
  printStack   stack: '\n\u001b[31mInvali2d \u001b[1m`prisma.user.findMany()`\u001b[22m invocation:\u001b[39m\n\n'
  printStack } +1ms
  printStack callsite Error:
    at Object.prismaClient [as User] (/Users/tim/code/prisma/src/packages/client/src/runtime/getPrismaClient.ts:377:28)
    at Object.acc.<computed> [as findMany] (/Users/tim/code/prisma/src/packages/client/src/runtime/getPrismaClient.ts:525:39)
    at /Users/tim/code/prisma-client-performance/main.ts:7:36
    at step (/Users/tim/code/prisma-client-performance/main.ts:33:23)
    at Object.next (/Users/tim/code/prisma-client-performance/main.ts:14:53)
    at /Users/tim/code/prisma-client-performance/main.ts:8:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/tim/code/prisma-client-performance/main.ts:4:12)
    at main (/Users/tim/code/prisma-client-performance/main.ts:41:12)
    at Object.<anonymous> (/Users/tim/code/prisma-client-performance/main.ts:32:1) +1ms
  printStack {
  printStack   introText: '\u001b[31mInvali2d \u001b[1m`client.user.findMany()`\u001b[22m invocation in\u001b[39m\n' +
  printStack     '\u001b[31m\u001b[4m/Users/tim/code/prisma-client-performance/main.ts:7:36\u001b[24m\u001b[39m',
  printStack   prevLines: '\n' +
  printStack     '\u001b[2m  \u001b[90m 3 \u001b[39m\u001b[36masync\u001b[39m \u001b[36mfunction\u001b[39m \u001b[36mmain\u001b[39m\u001b[38;2;107;139;140m(\u001b[39m\u001b[38;2;107;139;140m)\u001b[39m \u001b[38;2;107;139;140m{\u001b[39m\u001b[22m\n' +
  printStack     '\u001b[2m  \u001b[90m 4 \u001b[39m  \u001b[36mdebugger\u001b[39m\u001b[22m\n' +
  printStack     '\u001b[2m  \u001b[90m 5 \u001b[39m  \u001b[36mconst\u001b[39m client = \u001b[36mnew\u001b[39m PrismaClient\u001b[38;2;107;139;140m(\u001b[39m\u001b[38;2;107;139;140m)\u001b[39m\u001b[22m\n' +
  printStack     '\u001b[2m  \u001b[90m 6 \u001b[39m\u001b[22m\n' +
  printStack     '\u001b[31m\u001b[1m→\u001b[22m\u001b[39m \u001b[90m 7 \u001b[39m  \u001b[36mconst\u001b[39m result = \u001b[36mawait\u001b[39m client\u001b[38;2;107;139;140m.\u001b[39muser\u001b[38;2;107;139;140m.\u001b[39m\u001b[36mfindMany\u001b[39m\u001b[38;2;107;139;140m(\u001b[39m\n' +
  printStack     '\n',
  printStack   afterLines: ')',
  printStack   lastErrorHeight: 20,
  printStack   indentValue: 5,
  printStack   stack: '\n' +
  printStack     '\u001b[31mInvali2d \u001b[1m`client.user.findMany()`\u001b[22m invocation in\u001b[39m\n' +
  printStack     '\u001b[31m\u001b[4m/Users/tim/code/prisma-client-performance/main.ts:7:36\u001b[24m\u001b[39m\n' +
  printStack     '\n' +
  printStack     '\u001b[2m  \u001b[90m 3 \u001b[39m\u001b[36masync\u001b[39m \u001b[36mfunction\u001b[39m \u001b[36mmain\u001b[39m\u001b[38;2;107;139;140m(\u001b[39m\u001b[38;2;107;139;140m)\u001b[39m \u001b[38;2;107;139;140m{\u001b[39m\u001b[22m\n' +
  printStack     '\u001b[2m  \u001b[90m 4 \u001b[39m  \u001b[36mdebugger\u001b[39m\u001b[22m\n' +
  printStack     '\u001b[2m  \u001b[90m 5 \u001b[39m  \u001b[36mconst\u001b[39m client = \u001b[36mnew\u001b[39m PrismaClient\u001b[38;2;107;139;140m(\u001b[39m\u001b[38;2;107;139;140m)\u001b[39m\u001b[22m\n' +
  printStack     '\u001b[2m  \u001b[90m 6 \u001b[39m\u001b[22m\n' +
  printStack     '\u001b[31m\u001b[1m→\u001b[22m\u001b[39m \u001b[90m 7 \u001b[39m  \u001b[36mconst\u001b[39m result = \u001b[36mawait\u001b[39m client\u001b[38;2;107;139;140m.\u001b[39muser\u001b[38;2;107;139;140m.\u001b[39m\u001b[36mfindMany\u001b[39m\u001b[38;2;107;139;140m(\u001b[39m\n' +
  printStack     '\n'
  printStack } +12ms
# End Prisma Error Report
##################################
# To report this error, click [here](http://github.com).
# or create a new GitHub issue according to the template and copy and paste this excerpt.
##################################
##################################

Alternatives

Dump errors in the filesystem, piggyback on existing CLI error reporting

See #1659

Status Quo

Developers can manually report unexpected errors happening Prisma Client today by doing so manually. The process has significant friction:

  1. Developers will create a GitHub issue manually
  2. Often the Prisma team will ask for specific debug logs.
  3. Developers need to start the application again with a specific logging level (debug: *) and wait for the errors to happen again
  4. After that they need to submit a log file or an excerpt of it (usually add it to the GitHub issue).

Examples of GitHub issues for Prisma Client with debug output: #642, #605.

Additional context

Internal: https://www.notion.so/prismaio/Reporting-Errors-in-Query-Engine-2a0f2a24f2644b4c8b056bb8002b32da

Related issues: #610

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/featureA request for a new feature.tech/typescriptIssue for tech TypeScript.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions