Sentry-javascript: Retornar uma promessa dos métodos principais de captura* da API

Criado em 3 mai. 2019  ·  16Comentários  ·  Fonte: getsentry/sentry-javascript

Isso é garantido para relatar a exceção ao Sentinela?

try {
  // code
} catch (e) {
  const eventId = Sentry.captureException(e);
  console.log('sentry event', eventId);
  process.exit(1);
}

A documentação não é clara se o ID do evento é gerado local ou remotamente. A drenagem é relevante? https://docs.sentry.io/error-reporting/configuration/draining/?platform=node

Breaking Documentation Improvement

Comentários muito úteis

Estou tendo alguns problemas com o Sentry desde que atualizamos para @sentry/node , provavelmente voltaremos para raven-node até que haja uma solução melhor.

Ter que drenar filas em tempos limite arbitrários no final de cada execução sem servidor definitivamente parece mais um hack, e não uma solução. 🤔

Todos 16 comentários

Obrigado por destacar isso, para deixar claro que não é totalmente síncrono, o "transporte" está sendo executado em segundo plano. Então, estritamente falando, não é garantido que o evento atinja o Sentry.

O eventId é gerado no SDK localmente e será usado para ingerir o evento no servidor.

Atualizaremos nossos documentos para deixar isso claro.

Ok, apenas para esclarecer, é realmente necessário implementar o que está descrito aqui: https://docs.sentry.io/error-reporting/configuration/draining/?platform=node

Isso está correto, @HazAT?

@rhyek Corrent , se você quiser garantir que tudo seja enviado, aguarde a liberação para garantir que tudo seja enviado.

Não seria melhor apenas expor a promessa dos métodos capture* ? A API seria mais clara, pois o retorno de uma promessa informa aos usuários que eles precisam await para ter certeza de que o evento é enviado ou apenas disparar e esquecer esperando que seja enviado. Tanto close quanto flush são métodos de utilidade ambígua que tentam tornar síncrono algo que foi pensado como assíncrono. Além disso, ambos os métodos estão totalmente quebrados: na verdade, existem algumas peculiaridades (eu diria que é um bug, mas provavelmente isso depende do POV da pessoa que está olhando para eles):

  • o propósito do timeout passado para flush é nulo porque não é respeitado pelo transporte ao interromper o envio das requisições. Ele apenas resolve a promessa retornada para false quando o cronômetro expira. Ainda estou me perguntando a utilidade de tal código e comportamento ...
  • o método flush retorna uma nova promessa toda vez que é chamado que é resolvido assim que o timeout é alcançado. Existem dois problemas: todo o código executado por setInterval é extremamente lento, pelo menos nos meus testes no console do navegador, e a promessa foi resolvida muitos segundos após o tempo limite expirar. O segundo e mais importante problema é que o código da função _isClientProcessing limpa o tempo limite toda vez que é chamada, então se alguém estiver fazendo algo como Promise.all([fush(), flush()]) (não sei porque ele deveria fazer mas como a API retorna uma nova promessa toda vez que ele for tentado a fazê-lo), essa promessa nunca será resolvida.

Corrent, se você quiser ter certeza de que tudo foi enviado, você pode aguardar o flush para garantir que tudo seja enviado.

Incorreto, veja meus pontos acima para entender porque mesmo aguardando flush você não pode ter certeza de que tudo foi enviado. Eu diria que esse design de API está totalmente quebrado e não consigo entender porque não deixar para o usuário a escolha de aguardar as promessas que representam o envio de um evento em vez de tentar construir uma API de desligamento que não pode nem funcionar para todos idiomas em que a API unificada deve funcionar

Acho que ter acesso a uma promessa que resolve quando o evento é finalmente
enviado além dos outros métodos descritos neste tópico faz um
muito sentido.

No sábado, 11 de maio de 2019, 12h29 Stefano Arlandini [email protected]
escreveu:

Não seria melhor apenas expor a promessa da captura*
métodos? API seria mais clara, pois o retorno de uma promessa permite que os usuários saibam que
eles têm que esperar para ter certeza de que o evento é enviado ou apenas
atire e esqueça esperando que seja enviado. Ambos close e flush são métodos de
utilitário ambíguo que tenta tornar síncrono algo que foi
pense ser assíncrono. Além disso, ambos os métodos estão totalmente quebrados: em
na verdade, existem algumas peculiaridades (eu diria que é um bug, mas
provavelmente isso depende do POV da pessoa que está olhando para eles):

  • o objetivo do tempo limite passado para liberar é nulo porque não é
    respeitado pelo transporte, interrompendo o envio dos pedidos. Isto
    apenas resolve a promessa retornada para false quando o temporizador expira.
    Ainda estou me perguntando a utilidade de tal código e comportamento ...
  • o método flush retorna uma nova promessa toda vez que é chamado assim
    é resolvido assim que o tempo limite é atingido. Existem dois problemas:
    todo o código executado por setInterval é extremamente lento, pelo menos em
    meus testes no console do navegador, e a promessa resolveu muitos
    segundos após o tempo limite expirar. O segundo e mais importante problema é
    que o código da função _isClientProcessing limpa o tempo limite
    toda vez que é chamado, então se alguém estiver fazendo algo como Promise.all([fush(),
    flush()]) (não sei por que ele deveria fazer isso, mas como a API retorna
    uma nova promessa toda vez que ele for tentado a fazê-lo), então tal promessa será
    nunca ser resolvido.

Corrent, se quiser ter certeza de que tudo é enviado, pode aguardar flush
para garantir que tudo seja enviado.

Incorreto, veja meus pontos acima para entender porque mesmo aguardando flush você
não pode ter certeza de que tudo foi enviado. Eu diria que esse design de API é
totalmente quebrado e não consigo entender porque não deixar para o usuário o
escolha de aguardar as promessas que representa o envio de um evento
em vez de tentar construir uma API de desligamento que não pode funcionar para todos
idiomas em que a API unificada deve funcionar


Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/getsentry/sentry-javascript/issues/2049#issuecomment-491533914 ,
ou silenciar o thread
https://github.com/notifications/unsubscribe-auth/AAFLTSVSICZ7Y26UHCSMKWLPU4GATANCNFSM4HKUJ5ZQ
.

Eu também diria que não espero que um método que retorne um resultado execute algo em segundo plano, pois isso é fonte de confusão para os usuários (e a principal questão dessa questão, é claro). Em vez disso, se uma promessa for retornada, fica claro que é apenas um espaço reservado para algo que virá no futuro e que ainda não está pronto. A escolha de esperar por ele ou apenas disparar e esquecê-lo para o usuário, obviamente. Além disso, como o ID do evento é gerado localmente (não vejo nenhum motivo para fazê-lo), você pode usar algo (porque é retornado imediatamente) que não é válido porque por algum motivo o transporte falhou ao enviar o evento e você não nem sabe disso

Estou tendo alguns problemas com o Sentry desde que atualizamos para @sentry/node , provavelmente voltaremos para raven-node até que haja uma solução melhor.

Ter que drenar filas em tempos limite arbitrários no final de cada execução sem servidor definitivamente parece mais um hack, e não uma solução. 🤔

Para aqueles que procuram mais exemplos do que pode funcionar - eu encontrei algumas das soluções em # 1449 úteis sobre a descarga e tal, eles discutem muito sobre esse problema também.

(Eles estão focados em lambdas e sem servidor, mas os mesmos conceitos provavelmente funcionariam em outros ambientes também, pois é a abordagem de liberação).

Definitivamente ansioso para que haja uma maneira melhor em algum momento que não envolva lavar todas as vezes.

Concordo completamente com o que é dito neste tópico, IMO é realmente confuso ter um método síncrono que oculta a assincronia em segundo plano.
Talvez a equipe sentinela tenha um bom motivo para fazer isso dessa maneira, de qualquer forma uma atualização na documentação seria muito apreciada.

@cibergarri Acho que o motivo disso é que o eventId pode ser retornado imediatamente sem bloquear o código do userland em uma chamada de rede potencialmente lenta para apis sentry. Concordo que é confuso retornar um valor de uma API assíncrona e potencialmente leva à perda silenciosa de erros em contextos de execução sem servidor que não permanecem tempo suficiente para as chamadas da camada de transporte assíncrona. Uma solução seria dividir a função em duas para que um usuário precise optar pelo comportamento assíncrono, por exemplo

Sentry.captureException() // -> returns eventId after successful submission to sentry
Sentry.captureExceptionAsync() // -> returns promise

Ou como parâmetro, por exemplo

Sentry.captureException(ex, {async: false}) // ->  default, returns eventId after successful submission to sentry
Sentry.captureException(ex, {async: true}) // -> returns promise

O ID do evento é sempre gerado no cliente, portanto, a API assíncrona ou de sincronização não importa e, consequentemente, não é um bom indicador se um evento foi enviado ou não de verdade (outro problema). Também propus há muito tempo para o PHP SDK uma solução semelhante que envolvia métodos síncronos e assíncronos para cada método capture* , mas foi rejeitado. Eu não entendi completamente a verdadeira razão pela qual a API Unificada quer esconder a assincronia e os desenvolvedores não querem expor uma promessa, mas me pareceu que eles não estavam muito abertos para mudar isso.

Infelizmente, esse problema me fez mudar do Sentry, pois tornava os erros de rastreamento em ambientes sem servidor muito propensos a erros. (Oh A ironia.)

capture*Async métodos

Podemos obter uma atualização sobre isso?

@marcospgp o que você gostaria de saber exatamente? Tudo o que Daniel escreveu ainda permanece verdadeiro até hoje.

Eu acho que a documentação à parte, é bastante claro pelas reações aos comentários e comentários que os usuários gostariam de ter acesso às promessas, e não há uma boa razão para não permitir isso imho

Infelizmente, isso não acontecerá antes do lançamento da v6, pois está quebrando as alterações em nossas principais APIs e exigiria muitas alterações. Vou adicionar isso ao roteiro para manter isso anotado.

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