---
title: "Telemetria com o Application Insights"
description: "Telemetria opcional do Bulk Signer com o Azure Application Insights: como habilitar, o que é coletado e excluído, e consultas KQL para achar gargalos."
canonical: "https://docs.lacunasoftware.com/articles/bulk-signer/telemetry"
locale: "pt-BR"
product: "Bulk Signer"
last_updated: "2026-10-12"
---

# Telemetria com o Application Insights

Telemetria opcional do Azure Application Insights sobre o pipeline de assinatura — como habilitá-la, o
que é coletado, o que é intencionalmente excluído e as consultas KQL para encontrar gargalos.

> **Observação**
>
> A telemetria vem **desligada por padrão**. Com ela desabilitada, o serviço não tem dependência do
> Application Insights e não faz conexões de saída em nome dele. Tudo nesta página descreve uma
> funcionalidade opcional.

## Em resumo

| Pergunta | Resposta |
|----------|----------|
| Como habilitar? | Defina `Telemetry:Enabled = true` **e** forneça uma connection string (`Telemetry:ConnectionString` ou a variável de ambiente `APPLICATIONINSIGHTS_CONNECTION_STRING`). |
| Estado padrão? | **Desligado.** |
| Qual é o SDK? | A **distro do Azure Monitor OpenTelemetry** — activities e meters padrão do OpenTelemetry, não o SDK clássico do Application Insights. |
| O que é coletado? | Um trace correlacionado por job, os passos do ciclo de vida como span events, chamadas do PKI SDK como dependências, métricas de duração de assinatura e de processamento total, e exceções de processamento. |
| O que é excluído? | Logs (logs estruturados não são encaminhados), segredos (mascarados), conteúdo de arquivos, material de certificado e o caminho remoto do Lacuna Signer. |
| Quais tabelas do Application Insights? | Spans → `dependencies`; métricas → `customMetrics`; exceções → `exceptions`; requisições web coletadas automaticamente → `requests`. **Não há `customEvents`** — veja [abaixo](https://docs.lacunasoftware.com/articles/bulk-signer/telemetry#por-que-não-há-customevents). |

Escopo: esta página cobre a **assinatura local**. O fluxo remoto do Lacuna Signer é apenas parcialmente
rastreado — veja [O que é intencionalmente excluído](https://docs.lacunasoftware.com/articles/bulk-signer/telemetry#o-que-é-intencionalmente-excluído).

## Habilitando o Application Insights

### 1. Crie o recurso e copie a connection string

Crie um recurso do Application Insights no portal do Azure e copie sua **connection string** (painel
*Overview* → *Connection String*). Ela tem este formato:

```text
InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://<region>.in.applicationinsights.azure.com/;LiveEndpoint=https://<region>.livediagnostics.monitor.azure.com/
```

### 2. Configure o Bulk Signer

A connection string carrega a instrumentation key e é tratada como um **segredo** — nunca faça commit dela.
Prefira a variável de ambiente.

**Opção A — variável de ambiente (recomendada):**

```bash
# Linux / Docker
export Telemetry__Enabled=true
export APPLICATIONINSIGHTS_CONNECTION_STRING="InstrumentationKey=...;IngestionEndpoint=https://.../"
```

```powershell
# Windows
[Environment]::SetEnvironmentVariable("Telemetry__Enabled", "true", "Machine")
[Environment]::SetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING", "InstrumentationKey=...;IngestionEndpoint=https://.../", "Machine")
```

**Opção B — arquivo de configuração do operador** (por exemplo, `appsettings.Production.json`):

```json
{
  "Telemetry": {
    "Enabled": true,
    "ConnectionString": "InstrumentationKey=...;IngestionEndpoint=https://.../",
    "RoleName": "Lacuna.BulkSigner"
  }
}
```

| Chave | Tipo | Padrão | Override por env | Observações |
|-------|------|--------|------------------|-------------|
| `Telemetry:Enabled` | bool | `false` | `Telemetry__Enabled` | Chave mestra. Quando `true`, uma connection string é **obrigatória** — o serviço se recusa a iniciar sem ela. |
| `Telemetry:ConnectionString` | string | `""` | `Telemetry__ConnectionString` | **SECRET.** Deixe vazia para usar a variável de ambiente padrão abaixo. |
| _(variável de ambiente padrão)_ | string | _(não definida)_ | `APPLICATIONINSIGHTS_CONNECTION_STRING` | Lida diretamente pela distro e respeitada pelo validador de inicialização. Use-a para manter o segredo fora dos arquivos de configuração. |
| `Telemetry:RoleName` | string | `Lacuna.BulkSigner` | `Telemetry__RoleName` | Informado como `cloud_RoleName`, para que vários serviços no mesmo recurso continuem distinguíveis. |

### 3. Reinicie e verifique

Reinicie o serviço. Um ou dois minutos depois de processar um job, você deve ver entradas no recurso do
Application Insights: uma linha em `dependencies` chamada `signing.job` por job, dependências filhas
`Lacuna.Pki …` e linhas em `customMetrics` para `bulksigner.signing.duration` e
`bulksigner.job.duration`.

## O que é coletado

### Traces — span por job mais eventos de ciclo de vida

Cada job abre um span raiz (`signing.job`, tipo `Internal`, que aparece no Application Insights como
`dependencies`) no momento da captura, com as tags `job.id`, `signing.profile`, `signing.method` e
`signing.format`. Cada passo abaixo é registrado como um **span event** nesse span, de modo que todos
compartilham o mesmo `operation_Id` para correlação:

| Evento | Quando |
|--------|--------|
| `JobCreated` | No enfileiramento (um trace `signing.job.created` independente — o span do worker ainda não existe) |
| `JobPickedForProcessing` | O worker reivindica o job |
| `SigningStarted` / `SigningCompleted` | Em torno da chamada de assinatura local |
| `VerificationStarted` / `VerificationCompleted` | Em torno da chamada de verificação (somente quando o perfil tem `Verify = true`) |
| `OutputFileCreated` | Artefato assinado promovido para `output/` |
| `JobCompleted` | Sucesso terminal (status do span `Ok`) |
| `JobFailed` | Falha terminal (status do span `Error`) |
| `JobCanceled` | Cancelamento pelo operador (um trace `signing.job.canceled` independente) |
| `DispatchedToSigner` | Job entregue ao Lacuna Signer (caminho remoto — cobertura parcial) |
| `Cnab240PaymentDateCheckSkipped` | Uma remessa CNAB240 cuja data de pagamento mais antiga já havia passado foi liberada em vez de recusada, porque a verificação da data de pagamento do perfil (ou a verificação de CNAB240) está desligada — uma decisão, não uma assinatura |

### Dependências — chamadas do PKI SDK

As chamadas de assinatura e verificação do Lacuna PKI SDK são encapsuladas em spans filhos do tipo
`Client`, chamados `Lacuna.Pki SignAsync` e `Lacuna.Pki VerifyAsync`, que aparecem como `dependencies`.
Cada um tem sua própria duração e uma flag de sucesso; uma chamada que falhou é marcada como `Error`,
com uma mensagem mascarada, para que chamadas externas com problema fiquem visíveis com contexto de
diagnóstico.

### Métricas — `customMetrics`

| Métrica | Unidade | Dimensões |
|---------|---------|-----------|
| `bulksigner.signing.duration` | ms | `signing.method`, `signing.profile`, `signing.format`, `job.status` (`Success` / `Failed`) |
| `bulksigner.job.duration` | ms | `job.status` (`Success` / `Failed`), `signing.profile`, `signing.method` |

O `bulksigner.signing.duration` é o tempo decorrido da própria operação de assinatura; o
`bulksigner.job.duration` é o total, da criação do job até o estado terminal.

### Exceções — `exceptions`

Exceções de processamento tratadas e não tratadas são registradas no span do job com o id do job, o
perfil, o método de assinatura e o **passo de processamento** em que o erro ocorreu. Mensagens e stack
traces são mascarados antes de deixarem o processo.

## O que é intencionalmente excluído

- **Segredos.** A licença do PKI, senhas de certificado e de PFX, o PIN do PKCS#11, o client secret do
  Azure Key Vault, chaves de API, a senha de criptografia e connection strings são mascarados em todo
  valor anexado à telemetria — inclusive mensagens de exceção e stack traces. Veja
  [Segurança](https://docs.lacunasoftware.com/articles/bulk-signer/security#mascaramento-de-logs--duas-camadas).
- **Conteúdo de arquivos e material de certificado.** Nunca são anexados a nenhum span, evento ou métrica.
- **Logs da aplicação.** Logs estruturados **não** são encaminhados ao Application Insights. Somente
  spans, métricas e exceções explicitamente registradas são enviados; os logs permanecem nos destinos de
  arquivo e de console.
- **O id do job como dimensão de métrica.** Mantido fora dos histogramas para limitar a cardinalidade; a
  medição de tempo por job fica nos spans correlacionados.
- **O caminho remoto do Lacuna Signer.** A cobertura prioriza a assinatura local. Um job remoto emite
  apenas um span da captura até o despacho; a espera pelo assinante e a conclusão remota não são
  rastreadas.

## Consultas de exemplo (KQL)

Execute estas consultas no recurso do Application Insights (painel *Logs*). Ajuste o intervalo de tempo conforme
necessário.

**Tempo médio de assinatura (local), últimas 24 h:**

```kusto
customMetrics
| where name == "bulksigner.signing.duration"
| where timestamp > ago(24h)
| summarize avg(value), percentiles(value, 50, 95) by tostring(customDimensions["signing.profile"])
```

**Jobs de assinatura mais lentos:**

```kusto
dependencies
| where name == "signing.job"
| where timestamp > ago(24h)
| project timestamp, jobId = tostring(customDimensions["job.id"]),
          profile = tostring(customDimensions["signing.profile"]), duration, success
| top 20 by duration desc
```

**Falhas de assinatura por método de assinatura:**

```kusto
customMetrics
| where name == "bulksigner.signing.duration"
| where tostring(customDimensions["job.status"]) == "Failed"
| summarize failures = count() by method = tostring(customDimensions["signing.method"])
```

**Tempo médio total de processamento:**

```kusto
customMetrics
| where name == "bulksigner.job.duration"
| where tostring(customDimensions["job.status"]) == "Success"
| summarize avg(value), percentiles(value, 50, 95)
```

**Chamadas do PKI SDK que falharam (diagnóstico de chamadas externas):**

```kusto
dependencies
| where name startswith "Lacuna.Pki"
| where success == false
| project timestamp, name, jobId = tostring(customDimensions["job.id"]),
          operation = tostring(customDimensions["pki.operation"]), resultCode
| order by timestamp desc
```

**Exceções de processamento por passo:**

```kusto
exceptions
| where timestamp > ago(24h)
| summarize count() by step = tostring(customDimensions["processing.step"]), type
| order by count_ desc
```

## Por que não há `customEvents`

O Bulk Signer usa a **distro do Azure Monitor OpenTelemetry**, que não tem equivalente ao `TrackEvent` —
o OpenTelemetry não tem uma primitiva de "evento personalizado". Por isso, os passos do ciclo de vida são
modelados como **span events** no span por job e consultados pela tabela `dependencies` e seu
`customDimensions`, e não por `customEvents`. Consultas escritas para uma aplicação com o SDK clássico
precisarão ser adaptadas.

## Relacionados

- [Estatísticas de jobs](https://docs.lacunasoftware.com/articles/bulk-signer/statistics) — os tempos por etapa do dashboard, mantidos no banco de dados
  operacional e lidos no escopo de toda a implantação.
- [API REST](https://docs.lacunasoftware.com/articles/bulk-signer/rest-api) — o endpoint Prometheus `/api/metrics`, o registro durável, baseado em coleta (scrape).
- [Configuração](https://docs.lacunasoftware.com/articles/bulk-signer/configuration) — cada chave de configuração.
- [Segurança](https://docs.lacunasoftware.com/articles/bulk-signer/security) — tratamento de segredos e o mascaramento de logs em duas camadas.

---

**A seguir:** [API REST](https://docs.lacunasoftware.com/articles/bulk-signer/rest-api) — endpoints, autenticação e o envelope de erro.
**Anterior:** [Estatísticas de jobs](https://docs.lacunasoftware.com/articles/bulk-signer/statistics).
