Skip to content

feat(ui): adicionar serviço de telemetria opt-in para rastreamento de uso de componentes#2756

Open
pedrodominguesp wants to merge 1 commit intomasterfrom
devin/1772743315-telemetry-service
Open

feat(ui): adicionar serviço de telemetria opt-in para rastreamento de uso de componentes#2756
pedrodominguesp wants to merge 1 commit intomasterfrom
devin/1772743315-telemetry-service

Conversation

@pedrodominguesp
Copy link
Copy Markdown
Member

feat(ui): adicionar serviço de telemetria opt-in para rastreamento de uso de componentes

Resumo

Implementação de um novo serviço de telemetria (PoTelemetryService) e módulo (PoTelemetryModule) para coleta opt-in de dados anônimos sobre uso de componentes PO UI. O serviço inclui:

  • PoTelemetryConfig — interface de configuração com suporte a endpoint, intervalo de batch, chave de consentimento e literais customizadas para o diálogo
  • PoTelemetryService — serviço que armazena eventos em buffer, envia em batch via HTTP POST, gerencia consentimento do usuário via localStorage e PoDialogService
  • PoTelemetryModule.forRoot() — método de configuração para ativação opt-in
  • PO_UI_VERSION — constante com placeholder de versão substituída durante build (similar ao padrão existente)
  • Guia de telemetria — documentação completa em docs/guides/telemetry.md
  • Testes unitários — cobertura das principais funcionalidades: consentimento, batch, retry, etc.

Telemetria é desabilitada por padrão. Requer:

  1. PoTelemetryModule.forRoot({ enabled: true, endpointUrl: '...' }) — configuração explícita pelo desenvolvedor
  2. Consentimento do usuário final via diálogo ou métodos grantConsent() / revokeConsent()

O que foi implementado (conforme especificação)

✅ Seções 1-3, 5-8 da especificação original
Seção 4 (instrumentação de componentes via decorator/classe base) não foi implementada — ficará como trabalho futuro

Checklist de Revisão e Testes

  • Executar os testes unitáriosnpm run test:ui para verificar se os testes do po-telemetry.service.spec.ts passam
  • Executar build do portalnpm run build:portal:docs para confirmar que o guia de telemetria é gerado corretamente
  • Revisar a lógica de consentimento — o diálogo é exibido no construtor do serviço (linha 63 de po-telemetry.service.ts). Isso significa que o diálogo aparece assim que o serviço é instanciado. Confirmar se esse é o comportamento desejado ou se deveria ser adiado (ex: APP_INITIALIZER).
  • Revisar tipo intervalId: any — linha 45 de po-telemetry.service.ts usa any, o que viola as diretrizes do projeto. Considerar substituir por ReturnType<typeof setInterval> | null.
  • Testar comportamento de retry HTTP — verificar se eventos são realmente mantidos no buffer em caso de falha de rede

Plano de Teste Sugerido

  1. Criar app de teste com PoTelemetryModule.forRoot({ enabled: true, endpointUrl: 'http://localhost:3000/telemetry', showConsentDialog: true })
  2. Iniciar servidor mock na porta 3000 que loga requisições POST
  3. Executar app, aceitar consentimento no diálogo
  4. Usar alguns componentes (ex: po-button, po-table)
  5. Aguardar 30 segundos (intervalo de batch padrão)
  6. Verificar se o servidor mock recebeu array de eventos com formato correto
  7. Testar cenário de falha: derrubar o servidor e verificar se eventos são retidos e reenviados

Observações

  • Arquivos do portal auto-gerados: Os arquivos guide-routing.module.ts, guide.module.ts e menu-guides.service.ts foram editados manualmente para incluir a rota de telemetria, mas esses arquivos são normalmente regenerados durante gulp build:guides. As edições são consistentes com o padrão existente (outros guias também estão commitados dessa forma), mas serão sobrescritas no próximo build do portal.
  • Versão da biblioteca: PO_UI_VERSION = '0.0.0-PLACEHOLDER' é substituída automaticamente durante o build pelo scripts/version-replace.js (padrão existente).
  • Instrumentação de componentes não implementada: A especificação original mencionava criar um decorator @PoTrackUsage() ou classe base para instrumentar componentes automaticamente. Isso foi deliberadamente deixado de fora desta PR inicial — a API de trackComponentUsage() está pronta, mas cabe ao consumidor chamá-la manualmente ou implementar o decorator em follow-up.

Link para Sessão Devin: https://totvs.devinenterprise.com/sessions/db6c7993d59d46d780ca1ad5a7973959
Solicitado por: @pedrodominguesp

@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Co-Authored-By: domingues.pedro <pehdomingues96@gmail.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adiciona um serviço/módulo de telemetria opt-in ao @po-ui/ng-components para permitir rastreamento anônimo de uso de componentes (com consentimento), além de documentação e integrações no portal de guias.

Changes:

  • Cria PoTelemetryService + PoTelemetryModule.forRoot() com configuração, consentimento via localStorage e envio em batch via HTTP.
  • Adiciona constante PO_UI_VERSION (placeholder substituído no build) para compor payload de telemetria.
  • Inclui guia de telemetria e atualiza menu/rotas do portal para expor a nova documentação.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
projects/ui/src/lib/utils/po-version.ts Adiciona constante de versão do PO UI para uso em telemetria/build.
projects/ui/src/lib/services/services.module.ts Exporta/importa PoTelemetryModule no agregador de serviços.
projects/ui/src/lib/services/po-telemetry/po-telemetry.service.ts Implementa coleta, consentimento e envio batch/retry.
projects/ui/src/lib/services/po-telemetry/po-telemetry.service.spec.ts Testes unitários de consentimento, envio em batch e retry.
projects/ui/src/lib/services/po-telemetry/po-telemetry.module.ts Disponibiliza API forRoot para ativação/configuração opt-in.
projects/ui/src/lib/services/po-telemetry/po-telemetry.injection-token.ts Injection token para configuração.
projects/ui/src/lib/services/po-telemetry/po-telemetry-config.interface.ts Contrato de configuração do serviço.
projects/ui/src/lib/services/po-telemetry/index.ts Barrel exports do pacote de telemetria.
projects/ui/src/lib/services/index.ts Reexporta telemetria no índice de services.
projects/portal/src/app/guide/menu-guides.service.ts Adiciona item “Telemetria” no menu de guias.
projects/portal/src/app/guide/guide.module.ts Registra GuideTelemetryComponent no módulo de guias.
projects/portal/src/app/guide/guide-routing.module.ts Adiciona rota guides/telemetry.
docs/guides/telemetry.md Guia de uso/configuração e política de telemetria.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +50 to +52
@Optional() @Inject(PO_TELEMETRY_CONFIG) private config: PoTelemetryConfig,
@Optional() private httpClient: HttpClient,
@Optional() private poDialogService: PoDialogService,
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Os parâmetros marcados com @Optional() (config/httpClient/poDialogService) estão tipados como obrigatórios. Com strictInjectionParameters: true, o Angular espera que injeções opcionais aceitem null/undefined (ex.: usando ? ou | null); caso contrário pode falhar na checagem de injeção/compilação. Ajuste os tipos para config?: PoTelemetryConfig (ou PoTelemetryConfig | null) e o mesmo para httpClient e poDialogService.

Suggested change
@Optional() @Inject(PO_TELEMETRY_CONFIG) private config: PoTelemetryConfig,
@Optional() private httpClient: HttpClient,
@Optional() private poDialogService: PoDialogService,
@Optional() @Inject(PO_TELEMETRY_CONFIG) private config: PoTelemetryConfig | null,
@Optional() private httpClient: HttpClient | null,
@Optional() private poDialogService: PoDialogService | null,

Copilot uses AI. Check for mistakes.
private enabled: boolean;
private showConsentDialog: boolean;
private sessionId: string;
private intervalId: any;
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intervalId está como any, o que perde type-safety e dificulta o uso correto de clearInterval. Tipar como ReturnType<typeof setInterval> | null (ou equivalente) evita casts e reduz risco de uso incorreto.

Suggested change
private intervalId: any;
private intervalId: ReturnType<typeof setInterval> | null = null;

Copilot uses AI. Check for mistakes.
Comment on lines +171 to +174
private sendEvents(): void {
if (!this.httpClient || !this.endpointUrl) {
return;
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sendEvents retorna cedo quando HttpClient não está disponível ou endpointUrl está vazio. Se o consumidor configurar enabled: true e conceder consentimento nessa condição, o buffer pode crescer indefinidamente e nunca será drenado. Considere falhar rápido ao habilitar sem capacidade de envio (tornar HttpClient não-opcional e/ou validar endpointUrl), ou pausar coleta/intervalo até haver um endpoint e HTTP disponíveis.

Copilot uses AI. Check for mistakes.
Comment on lines +9 to +13
/** Se a telemetria está habilitada (default: false — opt-in). */
enabled: boolean;

/** URL do endpoint que receberá os eventos. */
endpointUrl: string;
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Como enabled e endpointUrl são obrigatórios, não dá para usar PoTelemetryModule.forRoot({ enabled: false }) sem fornecer uma URL “dummy”. Para suportar desabilitar por config/env sem URL, considere tornar endpointUrl opcional quando enabled for false (union type) ou validar em runtime apenas quando enabled for true.

Copilot uses AI. Check for mistakes.
Comment thread docs/guides/telemetry.md
Comment on lines +12 to +15
| Campo | Descrição |
|---|---|
| `componentName` | Nome do componente utilizado (ex: `po-button`, `po-table`) |
| `libraryVersion` | Versão da biblioteca `@po-ui/ng-components` |
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As linhas de tabela estão começando com || (ex.: || Campo | ...), o que geralmente impede a renderização correta em Markdown. Trocar para a sintaxe padrão | Campo | ... | melhora a leitura no portal e no GitHub.

Copilot uses AI. Check for mistakes.
Comment thread docs/guides/telemetry.md
Comment on lines +112 to +113
- Definir `enabled: false` na configuração

Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A doc indica que é possível desabilitar definindo apenas enabled: false, mas pela tipagem atual endpointUrl é obrigatório em PoTelemetryConfig. Ajustar a doc ou o tipo evita confusão para quem quer alternar telemetria via environment/config.

Suggested change
- Definir `enabled: false` na configuração
- Definir `enabled: false` na configuração, mantendo um `endpointUrl` válido conforme a tipagem de `PoTelemetryConfig`:
```typescript
PoTelemetryModule.forRoot({
enabled: false,
endpointUrl: 'https://my-telemetry-api.example.com/events'
});

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,300 @@
import { HttpClient } from '@angular/common/http';
import { TestBed, fakeAsync, tick } from '@angular/core/testing';
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fakeAsync e tick são importados mas não são usados neste spec. Remover os imports evita warnings de lint/TS e mantém o arquivo mais enxuto.

Suggested change
import { TestBed, fakeAsync, tick } from '@angular/core/testing';
import { TestBed } from '@angular/core/testing';

Copilot uses AI. Check for mistakes.
Comment thread docs/guides/telemetry.md
Comment on lines +63 to +66
| Propriedade | Tipo | Padrão | Descrição |
|---|---|---|---|
| `enabled` | `boolean` | `false` | Habilita ou desabilita a coleta de telemetria |
| `endpointUrl` | `string` | — | URL do endpoint que receberá os eventos |
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A tabela de "Configurações disponíveis" também está usando || no início das linhas, o que costuma quebrar a renderização em Markdown. Ajustar para a sintaxe padrão com | garante que a tabela seja exibida corretamente.

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +86
};

this.buffer.push(event);
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Não há limite para o tamanho do buffer; se o endpoint ficar indisponível por muito tempo, os eventos acumulam sem bound (impacto de memória). Sugestão: adicionar maxBufferSize (configurável) e política de descarte/backoff para evitar crescimento indefinido.

Copilot uses AI. Check for mistakes.
Comment on lines +61 to +65
this.sessionId = this.generateSessionId();

this.initConsent();
this.startBatchInterval();
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initConsent() e o possível confirm() são acionados no construtor. Isso pode disparar UI (diálogo) assim que o serviço é instanciado, inclusive durante bootstrap/injeções indiretas, o que tende a ser difícil de controlar por apps consumidores. Uma alternativa mais previsível é expor um método explícito de inicialização (ou inicializar sob demanda no primeiro trackComponentUsage) e/ou usar APP_INITIALIZER/ApplicationRef.isStable para adiar o prompt.

Copilot uses AI. Check for mistakes.
@alinelariguet alinelariguet added the Teste IA PR geradas por IA label Mar 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Teste IA PR geradas por IA

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants