Exportación a almacenamiento de objetos
Un objeto JSON por objetivo cumplido, en un bucket de su propiedad. Es la vía hacia cualquier almacén de datos que no sea BigQuery.
1. La necesidad que cubre
Hasta ahora había una sola vía de MousePlayer a un almacén de datos y llevaba a Google. Para Snowflake, Redshift o ClickHouse no había ninguna, aunque los tres leen almacenamiento de objetos sin problemas.
Por eso el puente escribe en almacenamiento de objetos en lugar de hacerlo en cada almacén por separado. Snowflake importa de S3, Redshift importa de S3, ClickHouse importa de S3 y BigQuery importa de Google Cloud Storage. Una exportación llega a todos.
| Destino | Cómo se accede |
|---|---|
| Amazon S3 | Signature Version 4, con el bucket en el host |
| Cloudflare R2 | Signature Version 4 contra el endpoint de su cuenta |
| Google Cloud Storage | mediante su API compatible con S3, con una clave HMAC |
| MinIO, Wasabi, Backblaze B2 y otros | Signature Version 4 contra su endpoint |
| Azure Blob Storage | un enlace SAS de contenedor, sin firma de nuestro lado |
2. Por qué Azure es distinto y por qué es mejor
Azure Blob no utiliza Signature Version 4, sino SharedKey. Podríamos haber creado otro sistema de firma. En su lugar, el puente acepta un enlace SAS de contenedor - una URL generada en su propia cuenta de almacenamiento con la firma ya incluida.
Esto requiere menos código de nuestra parte y menos confianza de la suya. Nunca vemos una clave de cuenta: nos entrega un permiso que usted mismo limita a un contenedor, con la caducidad elegida y revocable en cualquier momento sin afectar al resto.
Conviene aplicar la misma restricción a S3: autorice a la clave de acceso a escribir únicamente en este prefijo concreto y nada más. Una clave que solo puede añadir a mouseplayer/goals/ no puede leer sus otros buckets aunque se filtre.
3. Un objeto por objetivo y una clave basada en la fecha
El almacenamiento de objetos no permite añadir al final. Un archivo diario tendría que reescribirse entero cada vez y dos objetivos simultáneos se sobrescribirían. Por eso cada objetivo cumplido se convierte en un objeto independiente.
El coste es tener muchos objetos pequeños; la organización de las claves lo hace viable:
prefix/YYYY/MM/DD/channel/session-goal.json
Un almacén lee un día como una partición, y completar datos históricos consiste en recorrer un prefijo en lugar de realizar una consulta. Si quiere particionar por proyecto en vez de por fecha, añada el ID de canal al prefijo.
Cada objeto es una línea JSON
Sin sangría deliberadamente, para leer un prefijo completo como NDJSON sin abrir objetos uno a uno. Marca de tiempo, proyecto, sesión, ID de cliente, objetivo, valor, moneda y enlace de reproducción.
Un valor vacío es null, no cero
Un objetivo sin valor monetario escribe null. En un almacén, un cero entraría en una suma para producir un total que nunca existió: la diferencia entre «ningún importe acordado» y «un importe de cero» se conserva en la exportación.
4. Si responde 403, lea primero esto
Una solicitud S3 rechazada apenas explica nada, y hay un motivo por el que nuestro registro informa más que S3: la región forma parte de la firma. Una región incorrecta y una clave incorrecta producen el mismo 403; sospechar de la clave solo acierta la mitad de las veces.
Compruebe tres cosas, en este orden:
- La región, exactamente como la indica el bucket. R2 y Google Cloud Storage aceptan
autoy no la comprueban; los demás sí. - El permiso sobre el prefijo. Una clave limitada a
mouseplayer/no puede escribir enmouseplayer-goals/- la barra final importa en un ARN de recurso. - El endpoint, para R2 y almacenamientos compatibles con S3. Pegue el host sin
https://; lo quitamos de todos modos, pero añadirle una ruta supone otro bucket.
El ID de clave de acceso se guarda en claro deliberadamente. Por diseño viaja en cada solicitud firmada; cifrarlo añadiría trabajo sin protección. El secreto se cifra, nunca vuelve a mostrarse y no entra en la cola interna que transporta la tarea.
Todas las marcas mencionadas pertenecen a sus respectivos propietarios. MousePlayer no mantiene ninguna relación comercial con estos proveedores.