Sentry-javascript: Registrar automaticamente todos os erros lançados?

Criado em 10 fev. 2013  ·  31Comentários  ·  Fonte: getsentry/sentry-javascript

Existe uma maneira de fazer com que o Raven registre todos os erros lançados? Por alguma razão, ele registra algumas chamadas throw , mas não outras. Descobri que ele tende a não registrar o comportamento aninhado mais abaixo na pilha de chamadas.

Comentários muito úteis

Aqui está:

var __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

window.Error = (function(_super) {

  __extends(_Class, _super);

  function _Class() {
    var error;
    error = _Class.__super__.constructor.apply(this, arguments);
    Raven.captureException(error);
    return error;
  }

  return _Class;

})(Error);

Todos 31 comentários

haha, o tratamento de erros em Javascript é realmente terrível. Você pode me fornecer um exemplo de como você está lançando os erros?

Por exemplo, lançar uma string não nos permite obter nenhuma informação, exceto a mensagem que foi enviada. Com um objeto Error real, podemos (tentar) obter uma pilha.

Então, quanto mais informações, melhor para isso.

De fato.

Estou lançando um erro assim:

throw new Error("Error");

Às vezes ele loga no sentry e às vezes não.

Isso está em uma página que eu possa dar uma olhada em algum lugar? Ou pode colocar em algum lugar? Honestamente, isso não é apenas informação suficiente. Existem cerca de 10 fatores que podem explicar por que um erro não é registrado, e a maioria deles está fora de nossas mãos. :) Então, se eu puder ver o contexto completo, posso dar uma sugestão para ajudar o navegador.

Na verdade, o aplicativo é escrito em CoffeeScript que é compilado para JavaScript usando require.js. O ponto de entrada principal se parece com isso:

Raven.config('http://[email protected]');
Raven.context(function() {
  define(['cs!csmain']);
});

Eu tentei sem o wrapper context também e isso não pareceu mudar nada. Ele ainda registrou throw chamadas que foram feitas mais acima na pilha de chamadas enquanto ignorava aquelas abaixo.

Você está correndo Raven.install()

E para require.js, se você quisesse explicitamente encapsular os módulos, faria:

define(['module'], Raven.wrap(function(module) {
  // insert cool stuff here
}));

Esqueci no snippet, mas estou chamando install() depois config()

Eu não tentei envolver os módulos, mas imaginei que se já funciona em alguns lugares, por que não em outros?

Tudo depende realmente da pilha de chamadas. Quando as coisas começam a entrar em terreno assíncrono, fica difícil. Por exemplo, isso não faria como esperado:

Raven.context(function() {
  setTimeout(function() {
    throw new Error('crap');
  }, 1);
});

A função interna é executada em seu próprio contexto fora do contexto principal. O Node.js resolve isso com uma coisa chamada "domínios", mas, infelizmente, eles não existem no mundo dos navegadores.

Portanto, se um erro não for detectado e borbulhar até o topo, geralmente é rejeitado porque é 100% inútil nesse ponto.

Ah, eu vejo. Talvez haja uma maneira de utilizar window.onerror ?

FWIW, se possível, a maneira mais confiável de capturar uma exceção é usar explicitamente Raven.captureException . Eu entendo que isso nem sempre é viável, mas apenas um FYI.

Portanto, um bloco try...except explícito é o mais confiável:

try {
  throw new Error('something');
} catch(e) {
  Raven.captureException(e);
}

Certo. Claro que seria ótimo capturar erros automaticamente, mas JavaScript não o torna um jogo fácil de jogar...

@pheuter Não. :) E essa é a parte divertida. Uma vez que um erro chega a window.onerror, ele não é mais um objeto Error real. Ele se reduz a apenas uma corda inútil. E também impõe problemas de segurança entre domínios. Então, basicamente, quando um erro atinge window.onerror , geralmente é descartado, pois a única informação que temos pode ser: "Script error." .

É uma merda. Opa, adorei o esclarecimento!

Não, Javascript não. É realmente terrível, na verdade. :) Estou pesquisando e explorando ativamente maneiras de explorar o navegador para nos fornecer melhores informações. Até passou pela minha cabeça a ideia de fazer um patch de macaco Function.prototype.call . Mas isso é provavelmente uma notícia muito ruim.

Totalmente! Se você tiver alguma recomendação ou sugestão para esclarecer a documentação, entre em contato. Estou sempre procurando essas coisas.

Vai fazer, os documentos de configuração e uso foram bastante diretos e fáceis de seguir.

Gostaria de saber se há uma maneira de estender Error para fazer isso funcionar.

@mattrobenolt , esta é a abordagem que estamos adotando usando CoffeeScript.

window.Error = class extends Error
  constructor: ->
    error = super
    Raven.captureException error
    return error

Depois é só usar throw new Error "Test Error"

Comentário atualizado acima para esclarecimento.

Hmm. Vou brincar com isso no fim de semana. A última vez que tentei, ele não me deixou patch over window.Error. Vou tentar novamente em mais navegadores e ver o que é possível.

Obrigado pelo alerta!

Além disso, você pode me dar isso em Javascript normal? Tenho certeza do que está fazendo, só quero verificar novamente. Eu não escrevo Coffeescript.

Aqui está:

var __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

window.Error = (function(_super) {

  __extends(_Class, _super);

  function _Class() {
    var error;
    error = _Class.__super__.constructor.apply(this, arguments);
    Raven.captureException(error);
    return error;
  }

  return _Class;

})(Error);

Agora que penso nisso, esta é uma abordagem falha. Apenas substituir o construtor fará com que o Raven capture todos os objetos de erro, sejam eles lançados ou não. :)

FYI, errorception encontrou uma maneira de lidar com isso. Seria legal se raven-js pudesse fazer o mesmo.

@dmcquay Você pode fornecer um exemplo que o Errorception captura? Eu provavelmente posso fazer engenharia reversa.

Na verdade, presumo que todos os manipuladores de erros JS sejam 50% raven.js;)

:cocô:

@BYK , alguma ideia?

Eu não tenho nenhum conhecimento interno sobre errorception. Estou usando o serviço e parece funcionar como anunciado. Isso é tudo que eu sei.

Eu inspecionei como eles funcionam e parece que eles simplesmente se anexam a window.onerror e não se importam com o rastreamento de pilha. Pelo menos para esse tipo de coisa.

Seqüestrar o objeto Error funciona para o Firefox, mas o ponto de @mattrobenolt sobre capturar todos eles, mesmo os que não são lançados, é uma preocupação válida.

Uma solução suja para isso pode ser armazenar instâncias Error criadas sequestrando o construtor global e também ouvir onerror e comparar message , fileName e lineNo argumentos com as propriedades dos objetos Error armazenados. Se uma correspondência for encontrada, remova-a da fila e relate.

Ao avaliar todos os serviços de notificação de erros, notei que alguns serviços específicos de Javascript (como https://qbaka.com/) rastreiam o rastreamento de pilha e exibem a ação do usuário que levou a um erro específico. Uma pena que a errorception não faça isso, pois parece superior em todos os outros aspectos.

Estaremos usando o Sentry para nosso código Django, e me deparei com esse problema enquanto procurava informações sobre como o Sentry funciona para Javascript. A implementação atual do raven-js requer que o código capture explicitamente todos os erros JS e os reporte ao Sentry?

@adityar7 Não. Raven.js tenta o melhor para corrigir e interceptar as coisas, se puder. Em alguns casos mais extremos, pode ser necessário encapsular explicitamente, mas nos esforçamos muito para que as coisas aconteçam automaticamente.

@mattrobenolt Consegui funcionar corrigindo alguma sintaxe. Obrigado!

Esta página foi útil?
0 / 5 - 0 avaliações