Exportação para armazenamento de objetos
Um objeto JSON por meta atingida, em um bucket que pertence a você. Este é o caminho para qualquer data warehouse além do BigQuery.
1. A lacuna que esta integração preenche
Até agora, havia exatamente um caminho do MousePlayer para um data warehouse, e ele levava ao Google. Quem usava Snowflake, Redshift ou ClickHouse não tinha opção, embora os três leiam de armazenamento de objetos sem dificuldade.
Por isso, a ponte grava no armazenamento de objetos, em vez de atender cada data warehouse separadamente. Snowflake, Redshift e ClickHouse importam do S3; BigQuery importa do Google Cloud Storage. Uma única exportação atende a todos.
| Destino | Forma de acesso |
|---|---|
| Amazon S3 | Signature Version 4, bucket no nome do host |
| Cloudflare R2 | Signature Version 4 no endpoint da sua conta |
| Google Cloud Storage | pela API compatível com S3, com uma chave HMAC |
| MinIO, Wasabi, Backblaze B2 e outros | Signature Version 4 no seu endpoint |
| Azure Blob Storage | um link SAS do contêiner — sem assinatura do nosso lado |
2. Por que o Azure é diferente e por que isso é melhor
O Azure Blob não usa Signature Version 4; ele assina com SharedKey. Poderíamos ter criado um segundo esquema de assinatura. Em vez disso, a ponte recebe um link SAS do contêiner : uma URL que você gera na própria conta de armazenamento, já com a assinatura incluída.
Isso exige menos código do nosso lado e menos confiança do seu. Nunca vemos uma chave da conta: você fornece uma permissão que delimitou por conta própria, para um único contêiner, com uma validade escolhida por você e revogável a qualquer momento sem afetar mais nada.
Vale aplicar a mesma restrição ao S3: dê à chave de acesso permissão para gravar apenas neste prefixo . Uma chave que só pode adicionar objetos em mouseplayer/goals/ não consegue ler seus outros buckets, mesmo se vazar.
3. Um objeto por meta, com uma chave baseada na data
O armazenamento de objetos não permite acrescentar dados a um objeto existente. Um arquivo diário teria de ser regravado por inteiro a cada vez, e duas metas recebidas ao mesmo tempo sobrescreveriam uma à outra. Por isso, cada meta atingida se torna um objeto separado.
O custo são muitos objetos pequenos; a estrutura das chaves torna isso viável:
prefix/YYYY/MM/DD/channel/session-goal.json
O data warehouse lê cada dia como uma partição, e o preenchimento retroativo exige uma varredura de prefixo, em vez de uma consulta. Se quiser particionar por projeto em vez de por data, inclua o ID do canal no prefixo.
Cada objeto é uma linha de JSON
Sem indentação, de propósito, para que um prefixo inteiro possa ser lido como NDJSON sem abrir os objetos um por um. Carimbo de data e hora, projeto, sessão, ID do cliente, meta, valor, moeda e o link para reproduzir a gravação.
Um valor vazio é null, e não zero
Uma meta sem valor monetário grava null. No data warehouse, um zero entraria na soma de um total que nunca existiu. A distinção entre “nenhum valor acordado” e “um valor de zero” é preservada na exportação.
4. Se a resposta for 403, leia isto primeiro
Uma solicitação S3 rejeitada quase não informa nada. Há um motivo para a mensagem de erro em nosso registro dizer mais do que o próprio S3: a região faz parte da assinatura. Uma região incorreta e uma chave incorreta produzem o mesmo 403, então a suspeita óbvia — a chave — só está certa em metade dos casos.
Verifique três coisas, nesta ordem:
- A região, exatamente como informada pelo bucket. R2 e Google Cloud Storage aceitam
autoe não verificam esse valor; os demais verificam. - A permissão do prefixo. Uma chave limitada a
mouseplayer/não pode gravar emmouseplayer-goals/: a barra final faz diferença em um ARN de recurso. - O endpoint, para R2 e armazenamentos compatíveis com S3. Cole o host sem
https://. Removemos esse trecho em qualquer caso, mas um caminho acrescentado ao host aponta para outro bucket.
O ID da chave de acesso é armazenado em texto simples de propósito. Ele é enviado em toda solicitação assinada por definição, então criptografá-lo daria trabalho sem acrescentar proteção. O segredo é criptografado, nunca exibido novamente e nunca entra na fila interna que transporta a tarefa.
Todas as marcas comerciais citadas pertencem aos respectivos proprietários. O MousePlayer não mantém relação comercial com esses fornecedores.