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.

DestinoForma de acesso
Amazon S3Signature Version 4, bucket no nome do host
Cloudflare R2Signature Version 4 no endpoint da sua conta
Google Cloud Storagepela API compatível com S3, com uma chave HMAC
MinIO, Wasabi, Backblaze B2 e outrosSignature Version 4 no seu endpoint
Azure Blob Storageum 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 auto e não verificam esse valor; os demais verificam.
  • A permissão do prefixo. Uma chave limitada a mouseplayer/ não pode gravar em mouseplayer-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.