New Relic for Java (agente versão 3.37 ou superior) inclui uma API para instrumento de atividade assíncrona. Para frameworks suportados, o agente normalmente instrumento assíncrono funciona automaticamente. No entanto, a API assíncrona ainda pode ser útil para adicionar detalhes. Este documento fornece exemplos de uso de token e segmentos para instrumentar seu aplicativo.
Para obter mais informações sobre como o instrumento e as telas assíncronas do New Relic funcionam na interface
: tokens são passados entre threads para vincular unidade de trabalho assíncrona a uma transação específica. Eles não executam nenhuma cronometragem diretamente.
: os segmentos são usados para medir uma parte arbitrária do código de aplicativo assíncrono, não necessariamente associado a um método ou thread. Os segmentos normalmente são usados para rastrear chamadas externas que são concluídas por um mecanismo de retorno de chamada.
Token: conecta threads assíncronos
Use token para vincular unidades de trabalho arbitrárias que estejam em threads separados. Esta seção descreve como usar as chamadas relacionadas ao token em conjunto para o trabalho assíncrono do instrumento. Para obter informações detalhadas sobre classes e métodos, consulte o Javadoc.
Para usar tokens, primeiro você precisa criar o token e depois vincular outra chamada à transação de origem. Você deve vincular o token o mais rápido possível na outra chamada. Se você não vincular o token imediatamente, corre o risco de perder quaisquer métodos que contenham um @Trace abaixo da chamada que você está tentando vincular. Você também pode expirar o token na chamada original. O agente Java vinculará o trabalho na interface do New Relic. Estes exemplos ilustram como usar as chamadas relacionadas ao token juntas:
Considere o método parallelStream() no trecho de código abaixo. Como algumas das chamadas para requestItemAsync() ocorrerão em um encadeamento separado, um token é criado e transmitido para vincular esse trabalho assíncrono de volta ao encadeamento solicitante.
/**
* Example showing multi-threaded implementation of requesting data using a parallel {@link Stream}.
.map(id ->requestItemAsync(id, token))// requestItemAsync represents an example of work being passed to another thread. The token is passed along to allow linking the work on the new thread back to the thread that the token was originally created on.
@Trace(dispatcher = true): diz ao agente para iniciar uma transação. Para obter mais informações sobre esse método, consulte o Javadoc.
getToken(): Cria o token que vinculará o trabalho. Para obter mais informações sobre esse método, consulte o Javadoc.
token.expire(): Expira o token. Isso permite que a transação termine. Para obter mais informações sobre esse método, consulte o Javadoc.
O exemplo de código a seguir mostra requestItemAsync, que pode ser executado em um thread separado do thread solicitante. Por esse motivo, o token que foi criado no exemplo de código anterior está vinculado à transação em requestItemAsync. Observe que requestItemAsync() possui a anotação @Trace(async=true), que informa ao agente para trace esse método se ele estiver vinculado a uma transação existente.
Depois que parallelStream() coletar todos os resultados, o token expirará. Isso é importante porque garante que a transação não permaneça aberta após a conclusão de parallelStream() .
@Trace(async =true)
privateItemrequestItemAsync(long id,Token token){
token.link();
returnrequestItem(id);
}
As chamadas de API do agente neste exemplo são:
@Trace(async = true): inicia uma transação. Para obter mais informações sobre esse método, consulte o Javadoc.
token.link(): Vincula o trabalho que está sendo realizado em requestItemAsync() (que está sendo executado em um thread diferente) ao thread solicitante. Para obter mais informações sobre esse método, consulte o Javadoc.
Para visualizar detalhes do rastreamento da transação, acesse: one.newrelic.com APM & services > (select an app) > Transactions > Transaction trace > Trace details.
A atividade assíncrono é mostrada na visualização em cascata trace por segmentos que se sobrepõem horizontalmente, na dimensão de tempo.
Não é necessário vincular métodos que estejam no mesmo thread, mas isso não terá efeito negativo. Muitas vezes acontece que um único token pode ser compartilhado, como no exemplo parallelStream() .
Dica
Por padrão, uma transação pode criar no máximo 3.000 tokens e cada token tem um tempo limite padrão de 180s. Você pode alterar o limite anterior com a opção de configuração token_limit e o último com a opção de configuração token_timeout . trace para transação que exceda token_limit conterá um atributo token_clamp . Aumentar qualquer uma das opções de configuração pode aumentar o uso de memória do agente.
Segmentos: atividade assíncrona arbitrária de tempo
Segmentos são usados para medir uma parte arbitrária de código de aplicativo assíncrono, não necessariamente associado a um método ou thread. Isso é mais comumente usado para cronometrar conexões com serviços externos. Use segmentos se quiser:
Código de tempo que é concluído por meio de um retorno de chamada
Cronometre uma chamada assíncrono que abrange vários métodos
Meça o tempo entre a criação e a execução do trabalho (por exemplo, em um pool de threads)
O método abaixo faz uma chamada para um serviço externo (neste caso um banco de dados) usando o método storeItem():
/**
* Example showing single threaded implementation of inserting data into a datasource.
O objetivo, neste caso, é descobrir quanto tempo o Callable na instrução Lambda está aguardando no pool de threads antes de ser executado, em vez de determinar quanto tempo storeItem() é executado. Por esse motivo, um segmento é usado em vez de um token e @Trace(async = true) não é necessário como era para um token.
A chamada da API do agente neste exemplo é:
@Trace(dispatcher = true): inicia uma transação. Para obter mais informações sobre esse método, consulte o Javadoc.
O exemplo de código a seguir mostra um segmento começando no método storeItem para medir quanto tempo a instrução Lambda está aguardando no pool de threads. Para parar de cronometrar o segmento, você deve chamar .end() ou .ignore(). Se você don't desejar relatar o segmento como parte de sua transação pai, chame .ignore(). Caso contrário, para relatar o segmento como parte de sua transação pai, chame .end().
startSegment(...): inicia o segmento que cronometrará o código. Para obter mais informações sobre esse método, consulte o Javadoc.
reportAsExternal(DatastoreParameters()): Associa a hora a uma chamada externa do armazenamento de dados. Isso aparecerá no APM com dados do armazenamento de dados. Para obter mais informações, consulte API reportAsExternal.
segment.end(): Interrompe a cronometragem deste segmento. Para obter mais informações sobre esse método, consulte o Javadoc.
Quando o método é concluído, o APM exibe um trace da transação com uma chamada externa.
Dica
Por padrão, o agente pode rastrear no máximo 1.000 segmentos durante uma determinada transação. Você pode alterar esse limite com a opção de configuração segment_timeout . rastreamento de transação que exceda esse limite conterá um atributo segment_clamp . Aumentar esse limite pode aumentar o uso de memória do agente.