> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appsignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Instrumentação personalizada para Ruby

export const Compatibility = ({versions = [], label = "Available in"}) => {
  if (!Array.isArray(versions) || versions.length === 0) {
    return null;
  }
  const defaultPillStyle = {
    borderColor: "#d4d4d8",
    background: "#f4f4f5",
    color: "#3f3f46"
  };
  const pillStyles = {
    "AppSignal for Elixir": {
      background: "#f3e8ff",
      borderColor: "#d8b4fe",
      color: "#6b21a8"
    },
    "AppSignal for Front-end": {
      background: "#fef9c3",
      borderColor: "#fde047",
      color: "#854d0e"
    },
    "AppSignal for Go": {
      background: "#ccfbf1",
      borderColor: "#5eead4",
      color: "#115e59"
    },
    "AppSignal for JavaScript": {
      background: "#fef9c3",
      borderColor: "#fde047",
      color: "#854d0e"
    },
    "AppSignal for Node.js": {
      background: "#dcfce7",
      borderColor: "#86efac",
      color: "#166534"
    },
    "AppSignal for Python": {
      background: "#dbeafe",
      borderColor: "#93c5fd",
      color: "#1e40af"
    },
    "AppSignal for Ruby": {
      background: "#fee2e2",
      borderColor: "#fca5a5",
      color: "#991b1b"
    },
    "AppSignal for Rust": {
      background: "#ffedd5",
      borderColor: "#fdba74",
      color: "#9a3412"
    }
  };
  const getPillStyle = name => ({
    ...defaultPillStyle,
    ...pillStyles[name] || ({})
  });
  return <div className="not-prose my-4 rounded-lg border border-zinc-200 bg-zinc-50 px-4 py-3 text-sm dark:border-white/10 dark:bg-white/5">
      <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
        <span className="font-semibold text-zinc-700 dark:text-zinc-200">
          {label}:
        </span>
        {versions.map((v, i) => <span key={`${v.name}-${v.version}-${i}`} className="inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium" style={getPillStyle(v.name)}>
            <span>{v.name}</span>
            <span className="opacity-70">
              {v.version}
              {v.exact ? "" : "+"}
            </span>
          </span>)}
      </div>
    </div>;
};

Para descobrir quais trechos específicos de código estão causando problemas de desempenho, é útil adicionar instrumentação personalizada à sua aplicação. Isso nos permite criar detalhamentos melhores sobre qual código roda mais lentamente e em que tipo de action mais tempo foi gasto.

Quando você visualizar amostras salvas de requisições lentas no AppSignal, poderá ver toda a instrumentação que sua aplicação usa internamente. Renderização de templates, queries do ActiveRecord e caching são instrumentados e serão mostrados na amostra.

<img src="https://mintcdn.com/appsignal-715f5a51/nF8c1Rwq1cS7b5hg/assets/images/screenshots/app_performance_sample_timeline_1.png?fit=max&auto=format&n=nF8c1Rwq1cS7b5hg&q=85&s=5d66c763209a2fa1e9e04252e792d566" alt="Default event tree" width="555" height="245" data-path="assets/images/screenshots/app_performance_sample_timeline_1.png" />

Isso já é muito útil, mas não seria ótimo se pudéssemos ver
medições de trechos específicos de código que você suspeita que possam influenciar o
desempenho? Bem, você pode!

Ao adicionar instrumentação personalizada, podemos criar detalhamentos mais detalhados de uma requisição e background job. Existem duas formas de instrumentar seu código. Com os helpers de instrumentação do AppSignal ou com a instrumentação do ActiveSupport Notifications, como é usada pelo Rails.

<Tip>
  **Nota**: Certifique-se de ter [integrado o
  AppSignal](/ruby/instrumentation/integrating-appsignal) antes de adicionar
  instrumentação personalizada à sua aplicação, se ela não for automaticamente
  integrada por uma das nossas [integrações](/ruby/integrations) suportadas.
  Siga nosso [guia de instrumentação para scripts e background
  jobs](/ruby/instrumentation/background-jobs) para aplicações que
  não instrumentamos automaticamente.
</Tip>

<Tip>
  **Nota**: Esta página descreve apenas como adicionar instrumentação de desempenho
  ao seu código. Para rastrear erros, leia nosso guia de [tratamento de
  exceções](/ruby/instrumentation/exception-handling).
</Tip>

## Helpers de instrumentação

<Compatibility versions={[{ name: "AppSignal for Ruby", version: "1.3.0" }]} />

Quando você adiciona instrumentação personalizada ao seu código, poderá receber ainda
mais insights sobre sua aplicação. Por exemplo, você precisa trabalhar com uma
API externa que busca artigos para sua página inicial:

<CodeGroup>
  ```ruby Ruby theme={null}
  class ArticleFetcher
    def self.fetch(category)
      Appsignal.instrument('fetch.article_fetcher') do
        # Download and process the articles
      end
    end
  end

  ArticleFetcher.fetch('Latest news')
  ```
</CodeGroup>

Uma vez que você adiciona instrumentações personalizadas como essa, o AppSignal começará a captá-las
e mostrará quanto tempo tanto um grupo de eventos (`article_fetcher` neste
caso) quanto eventos individuais levaram.

<img src="https://mintcdn.com/appsignal-715f5a51/nF8c1Rwq1cS7b5hg/assets/images/screenshots/app_performance_sample_timeline_2.png?fit=max&auto=format&n=nF8c1Rwq1cS7b5hg&q=85&s=d32f6f6efe5cce3991168d0fe9f06a77" alt="Event tree with fetcher" width="555" height="282" data-path="assets/images/screenshots/app_performance_sample_timeline_2.png" />

Neste caso, você notará que essa chamada de API tem uma grande influência no
desempenho da nossa página inicial, o que estava oculto antes. Podemos querer considerar
fazer cache dos artigos.

<Tip>
  **Nota**: O nome do evento que você está instrumentando é importante para nosso
  processador. Leia mais sobre [nomenclatura de eventos](/api/event-names).
</Tip>

### Aninhando instrumentação

Você pode usar quantas instrumentações quiser, em qualquer combinação. Você pode
aninhar chamadas de instrument, e o AppSignal lidará com o aninhamento e as agregações das
medições de forma adequada. Você só precisa manter o segmento final (após o último
ponto) da chave consistente.

<CodeGroup>
  ```ruby Ruby theme={null}
  Appsignal.instrument('fetch.article_fetcher') do
    10.times do
      Appsignal.instrument('fetch_single_article.article_fetcher') do
        # Fetch single article
      end
    end
  end
  ```
</CodeGroup>

### Coletando mais dados por evento

Por padrão, o AppSignal coletará a duração de um evento e a enviará para nossos
servidores. Como a instrumentação personalizada não está conectada a nenhum interno de framework,
você pode precisar passar mais dados se quiser que os detalhes do evento
apareçam no AppSignal. Pode ser um título descritivo ou informações mais específicas
como a query de uma chamada de banco de dados. Já fazemos isso para
ActiveRecord, Sequel, Redis, MongoDB, Sinatra, Grape,
[e mais](/ruby/integrations).

Existem dois helpers para permitir que você instrumente seu código com o AppSignal.

<CodeGroup>
  ```ruby Ruby theme={null}
  Appsignal.instrument(name, title = nil, body = nil, body_format = Appsignal::EventFormatter::DEFAULT, &block)
  # and
  Appsignal.instrument_sql(name, title = nil, body = nil, &block)
  ```
</CodeGroup>

#### Argumento `name`

O nome do evento que aparecerá na árvore de eventos no AppSignal.
Leia mais sobre [nomenclatura de chaves de eventos](/api/event-names).

#### Argumento `title`

Um título mais descritivo de um evento, como `"Fetch current user"` ou `"Fetch blog post comments"`. Ele aparecerá ao lado do nome do evento na árvore de eventos
na página de amostra de desempenho para fornecer um pouco mais de contexto sobre o que está
acontecendo.

<CodeGroup>
  ```ruby Ruby theme={null}
  Appsignal.instrument('fetch.custom_database', 'Fetch current user') do
    # ...
  end
  ```
</CodeGroup>

#### Argumento `body`

Mais detalhes, como uma query de banco de dados usada pelo evento.

<CodeGroup>
  ```ruby Ruby theme={null}
  sql = 'SELECT * FROM posts ORDER BY created_at DESC LIMIT 1'
  Appsignal.instrument('fetch.custom_database', 'Fetch latest post', sql) do
    # ...
  end
  ```
</CodeGroup>

<Warning>
  **Aviso**: Por favor, certifique-se de que os payloads do body estão sanitizados
  (dados sensíveis/dinâmicos foram removidos). Eventos com body não sanitizados serão
  descartados se atingirem um certo limite.
</Warning>

Bom:

<CodeGroup>
  ```ruby Ruby theme={null}
  Appsignal.instrument('custom.instrument', 'Instrument stuff', 'command/dynamic/?') do
    # ...
  end
  Appsignal.instrument('custom.instrument', 'Instrument stuff', 'command/dynamic/?') do
    # ...
  end
  ```
</CodeGroup>

Ruim:

<CodeGroup>
  ```ruby Ruby theme={null}
  Appsignal.instrument('custom.instrument', 'Instrument stuff', 'command/dynamic/123') do
    # ...
  end
  Appsignal.instrument('custom.instrument', 'Instrument stuff', 'command/dynamic/234') do
    # ...
  end
  ```
</CodeGroup>

Ao passar uma query SQL como body, você pode usar `body_format = Appsignal::EventFormatter::SQL_BODY_FORMAT` para isso.

#### Argumento `body_format`

O formato do body suporta formatadores para sanitizar os dados fornecidos no argumento `body`
para remover quaisquer dados sensíveis do valor. Atualmente, há dois valores suportados
para o argumento `body_format`.

##### Valor `Appsignal::EventFormatter::DEFAULT`

O `Appsignal::EventFormatter::DEFAULT` é o valor padrão deste
argumento. Por padrão, o AppSignal deixará o valor intacto e não sanitizará nenhum
dado dele.

##### Valor `Appsignal::EventFormatter::SQL_BODY_FORMAT`

O valor `Appsignal::EventFormatter::SQL_BODY_FORMAT` passará seus dados
pelo sanitizador de SQL e sanitizará quaisquer valores em queries SQL.

Recomendamos que você use o helper `Appsignal.instrument_sql` para isso.

<CodeGroup>
  ```sql SQL theme={null}
  SELECT * FROM users WHERE email = 'hector@appsignal.com' AND password = 'iamabot'
  -- becomes
  SELECT * FROM users WHERE email = ? AND password = ?
  ```
</CodeGroup>

## ActiveSupport::Notifications

<Tip>
  Em versões mais antigas da gem do AppSignal (1.2 e anteriores), o
  `Appsignal.instrument` não está disponível. Se você não puder atualizar, ainda é
  possível usar `ActiveSupport::Notifications` em vez disso. Se você não quiser
  usar o helper `Appsignal.instrument`, mas sim usar
  `ActiveSupport::Notifications`, você ainda pode fazê-lo na gem AppSignal para Ruby
  1.3 e versões superiores.
</Tip>

O método para instrumentar seu código usando `ActiveSupport::Notifications`
é muito semelhante a como o AppSignal faz isso. Usando o exemplo do article fetcher
novamente, você pode ver que as diferenças são bastante pequenas.

Veja também nossa documentação sobre [formatadores de eventos](/ruby/instrumentation/event-formatters) do AppSignal ao usar `ActiveSupport::Notifications`.
Para mais informações sobre a instrumentação ActiveSupport::Notifications, consulte a documentação oficial do Rails [`ActiveSupport::Notifications`](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html).

<CodeGroup>
  ```ruby Ruby theme={null}
  require "active_support"

  class ArticleFetcher
    def self.fetch(category)
      ActiveSupport::Notifications.instrument("fetch.article_fetcher") do
        # Download and process the articles
      end
    end
  end

  ArticleFetcher.fetch("Latest news")
  ```
</CodeGroup>

Funciona para chamadas de instrumentação aninhadas também.

<CodeGroup>
  ```ruby Ruby theme={null}
  require "active_support"

  ActiveSupport::Notifications.instrument("fetch.article_fetcher") do
    10.times do
      ActiveSupport::Notifications.instrument("fetch_single_article.article_fetcher") do
        # Fetch single article
      end
    end
  end
  ```
</CodeGroup>

`ActiveSupport::Notifications` é altamente flexível, você pode instrumentar seu código
da maneira que quiser. Mais informações sobre `ActiveSupport::Notifications` podem ser
encontradas na
[documentação da API do Rails](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html).

<Warning>
  **Aviso**: Não rastreamos eventos privados do `ActiveSupport::Notifications`
  que começam com um ponto de exclamação (`!`). Esses eventos incluem principalmente eventos privados
  gerados pelo Rails.
</Warning>
