feat: opt-in error reporting

This commit is contained in:
alina 🌸 2023-10-03 02:49:53 +03:00
parent 00f30a6495
commit 544e5a68dc
Signed by: teidesu
SSH key fingerprint: SHA256:uNeCpw6aTSU4aIObXLvHfLkDa82HWH9EiOj9AXOIRpI
5 changed files with 46 additions and 0 deletions

View file

@ -131,6 +131,18 @@ export interface BaseTelegramClientOptions {
*/
disableUpdates?: boolean
/**
* mtcute can send all unknown RPC errors to [danog](https://github.com/danog)'s
* [error reporting service](https://rpc.pwrtelegram.xyz/).
*
* This is fully anonymous (except maybe IP) and is only used to improve the library
* and developer experience for everyone working with MTProto. This is fully opt-in,
* and if you're too paranoid, you can disable it by manually passing `enableErrorReporting: false` to the client.
*
* @default false
*/
enableErrorReporting?: boolean
/**
* If true, RPC errors will have a stack trace of the initial `.call()`
* or `.sendForResult()` call position, which drastically improves
@ -288,6 +300,7 @@ export class BaseTelegramClient extends EventEmitter {
isPremium: false,
useIpv6: Boolean(opts.useIpv6),
keepAliveAction: this._keepAliveAction.bind(this),
enableErrorReporting: opts.enableErrorReporting ?? false,
...(opts.network ?? {}),
},
this._config,

View file

@ -33,6 +33,7 @@ export interface NetworkManagerParams {
crypto: ICryptoProvider
log: Logger
enableErrorReporting: boolean
apiId: number
initConnectionOptions?: Partial<Omit<tl.RawInitConnectionRequest, 'apiId' | 'query'>>
transport?: TransportFactory
@ -156,6 +157,7 @@ export class DcConnectionManager {
isMainConnection: false,
isMainDcConnection: this.isPrimary,
inactivityTimeout: this.manager.params.inactivityTimeout ?? 60_000,
enableErrorReporting: this.manager.params.enableErrorReporting,
})
private _log = this.manager._log.create('dc-manager')

View file

@ -18,6 +18,7 @@ import {
removeFromLongArray,
} from '../utils'
import { createAesIgeForMessageOld } from '../utils/crypto/mtproto'
import { reportUnknownError } from '../utils/platform/error-reporting'
import { doAuthorization } from './authorization'
import { MtprotoSession, PendingMessage, PendingRpc } from './mtproto-session'
import { PersistentConnection, PersistentConnectionParams } from './persistent-connection'
@ -29,6 +30,7 @@ export interface SessionConnectionParams extends PersistentConnectionParams {
initConnection: tl.RawInitConnectionRequest
inactivityTimeout?: number
niceStacks?: boolean
enableErrorReporting: boolean
layer: number
disableUpdates?: boolean
withUpdates?: boolean
@ -760,6 +762,10 @@ export class SessionConnection extends PersistentConnection {
makeNiceStack(error, rpc.stack!, rpc.method)
}
if (error.unknown && this.params.enableErrorReporting) {
reportUnknownError(this.log, error, rpc.method)
}
rpc.promise.reject(error)
} else {
this.log.debug('received rpc_result (%s) for request %l (%s)', result._, reqMsgId, rpc.method)

View file

@ -0,0 +1,23 @@
import { tl } from '@mtcute/tl'
import { Logger } from '../logger'
export function reportUnknownError(log: Logger, error: tl.RpcError, method: string): void {
if (typeof fetch !== 'function') return
fetch(`https://rpc.pwrtelegram.xyz/?code=${error.code}&method=${method}&error=${error.text}`)
.then((r) => r.json())
.then((r) => {
if (r.ok) {
log.info('telerpc responded with error info for %s: %s', error.text, r.result)
} else {
log.info(
'Reported error %s to telerpc. You can disable this using `enableErrorReporting: false`',
error.text,
)
}
})
.catch((e) => {
log.debug('failed to report error %s to telerpc: %s', error.text, e)
})
}

View file

@ -8,6 +8,7 @@ class RpcError extends Error {
super(_descriptionsMap[text] || 'Unknown RPC error: [' + code + ':' + text + ']');
this.code = code;
this.text = text;
this.unknown = !_descriptionsMap[text];
}
static is(err, text) { return err.constructor === RpcError && (!text || err.text === text); }
@ -44,6 +45,7 @@ export class RpcError extends Error {
readonly code: number;
readonly text: MtErrorText;
readonly unknown: boolean;
constructor(code: number, text: MtErrorText);
is<const T extends MtErrorText>(text: T): this is RpcErrorWithArgs<T>;