Saat ini, hampir setiap perusahaan di dunia mengumpulkan statistik tentang tindakan pengguna pada sumber daya web. Motivasinya jelas - perusahaan ingin mengetahui bagaimana produk/situs web mereka digunakan dan lebih memahami penggunanya. Tentu saja, ada banyak sekali alat di pasaran untuk mengatasi masalah ini - mulai dari sistem analitik yang menyediakan data dalam bentuk dasbor dan grafik (misalnya
Namun kami menemukan masalah yang belum terpecahkan. Jadi lahirlah
Mengapa kita harus mengembangkan layanan kita sendiri?
Saat itu tahun sembilan puluhan, kami bertahan sebaik mungkin. Pada tahun 2019, kami mengembangkan API Platform Data Pelanggan Pertama krasa, yang memungkinkan pengumpulan data dari berbagai sumber (iklan Facebook, Stripe, Salesforce, Google play, Google Analytics, dll.) untuk analisis data yang lebih nyaman, mengidentifikasi ketergantungan, dll. Kami memperhatikan bahwa banyak pengguna menggunakan platform kami untuk analisis data khususnya Google Analytics (selanjutnya disebut GA). Kami berbicara dengan beberapa pengguna dan menemukan bahwa mereka memerlukan data analitik untuk produk yang mereka terima menggunakan GA, namun
Mereka memasang piksel javascript Segmen pada sumber daya web mereka dan data perilaku pengguna dimuat ke dalam database tertentu (misalnya Postgres). Tapi Segmen juga punya kekurangannya - harga. Misalnya, jika sumber daya web memiliki 90,000 MTU (pengguna terlacak bulanan), maka Anda harus membayar ~$1,000 per bulan ke kasir. Ada juga masalah ketiga - beberapa ekstensi browser (seperti AdBlock) memblokir pengumpulan analitik. permintaan http dari browser dikirim ke domain GA dan Segmen. Berdasarkan keinginan klien kami, kami telah menciptakan layanan analitik yang mengumpulkan kumpulan data lengkap (tanpa pengambilan sampel), gratis dan dapat bekerja pada infrastruktur kami sendiri.
Bagaimana layanan ini bekerja
Layanan ini terdiri dari tiga bagian: piksel javascript (yang kemudian kami tulis ulang dalam skrip ketikan), bagian server diimplementasikan dalam bahasa GO, dan direncanakan untuk menggunakan Redshift dan BigQuery sebagai database internal (kemudian mereka menambahkan dukungan untuk Postgres, ClickHouse dan Kepingan Salju).
Struktur acara GA dan Segmen diputuskan untuk tidak diubah. Yang diperlukan hanyalah menduplikasi semua peristiwa dari sumber daya web tempat piksel dipasang ke backend kami. Ternyata, hal ini mudah dilakukan. Piksel Javascript menggantikan metode pustaka GA asli dengan metode baru yang menduplikasi peristiwa di sistem kami.
//'ga' - ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΠΎΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ Google Analytics
if (window.ga) {
ga(tracker => {
var originalSendHitTask = tracker.get('sendHitTask');
tracker.set('sendHitTask', (model) => {
var payLoad = model.get('hitPayload');
//ΠΎΡΠΏΡΠ°Π²ΠΊΠ° ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠΎΠ±ΡΡΠΈΡ Π² GA
originalSendHitTask(model);
let jsonPayload = this.parseQuery(payLoad);
//ΠΎΡΠΏΡΠ°Π²ΠΊΠ° ΡΠΎΠ±ΡΡΠΈΡ Π² Π½Π°Ρ ΡΠ΅ΡΠ²ΠΈΡ
this.send3p('ga', jsonPayload);
});
});
}
Dengan Segmen pixel segalanya menjadi lebih sederhana; ia memiliki metode middleware, salah satunya kami gunakan.
//'analytics' - ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΠΎΠ΅ Π½Π°Π·Π²Π°Π½ΠΈΠ΅ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ Segment
if (window.analytics) {
if (window.analytics.addSourceMiddleware) {
window.analytics.addSourceMiddleware(chain => {
try {
//Π΄ΡΠ±Π»ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ Π² Π½Π°Ρ ΡΠ΅ΡΠ²ΠΈΡ
this.send3p('ajs', chain.payload);
} catch (e) {
LOG.warn('Failed to send an event', e)
}
//ΠΎΡΠΏΡΠ°Π²ΠΊΠ° ΠΎΡΠΈΠ³ΠΈΠ½Π°Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠΎΠ±ΡΡΠΈΡ Π² Segment
chain.next(chain.payload);
});
} else {
LOG.warn("Invalid interceptor state. Analytics js initialized, but not completely");
}
} else {
LOG.warn('Analytics.js listener is not set.');
}
Selain menyalin acara, kami telah menambahkan kemampuan untuk mengirim json sewenang-wenang:
//ΠΡΠΏΡΠ°Π²ΠΊΠ° ΡΠΎΠ±ΡΡΠΈΠΉ Ρ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΡΠΌ json ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠΌ
eventN.track('product_page_view', {
product_id: '1e48fb70-ef12-4ea9-ab10-fd0b910c49ce',
product_price: 399.99,
price_currency: 'USD'
product_release_start: '2020-09-25T12:38:27.763000Z'
});
Selanjutnya, mari kita bicara tentang sisi server. Backend harus menerima permintaan http, mengisinya dengan informasi tambahan, misalnya geodata (terima kasih
//Π²Ρ
ΠΎΠ΄ΡΡΠΈΠΉ json
{
"field_1": {
"sub_field_1": "text1",
"sub_field_2": 100
},
"field_2": "text2",
"field_3": {
"sub_field_1": {
"sub_sub_field_1": "2020-09-25T12:38:27.763000Z"
}
}
}
//ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ
{
"field_1_sub_field_1": "text1",
"field_1_sub_field_2": 100,
"field_2": "text2",
"field_3_sub_field_1_sub_sub_field_1": "2020-09-25T12:38:27.763000Z"
}
Namun, array saat ini hanya dikonversi menjadi string. tidak semua database relasional mendukung kolom berulang. Dimungkinkan juga untuk mengubah nama bidang atau menghapusnya menggunakan aturan pemetaan opsional. Mereka memungkinkan Anda mengubah skema data, jika perlu, atau mentransmisikan satu tipe data ke tipe data lainnya. Misalnya, jika bidang json berisi string dengan stempel waktu (bidang_3_sub_bidang_1_sub_sub_bidang_1 dari contoh di atas), maka untuk membuat field di database dengan tipe timestamp, Anda perlu menulis aturan pemetaan di konfigurasinya. Dengan kata lain, tipe data bidang ditentukan terlebih dahulu oleh nilai json, dan kemudian aturan casting tipe (jika dikonfigurasi) diterapkan. Kami telah mengidentifikasi 4 tipe data utama: STRING, FLOAT64, INT64 dan TIMESTAMP. Aturan pemetaan dan casting terlihat seperti ini:
rules:
- "/field_1/subfield_1 -> " #ΠΏΡΠ°Π²ΠΈΠ»ΠΎ ΡΠ΄Π°Π»Π΅Π½ΠΈΡ ΠΏΠΎΠ»Ρ
- "/field_2/subfield_1 -> /field_10/subfield_1" #ΠΏΡΠ°Π²ΠΈΠ»ΠΎ ΠΏΠ΅ΡΠ΅Π½ΠΎΡΠ° ΠΏΠΎΠ»Ρ
- "/field_3/subfield_1/subsubfield_1 -> (timestamp) /field_20" #ΠΏΡΠ°Π²ΠΈΠ»ΠΎ ΠΏΠ΅ΡΠ΅Π½ΠΎΡΠ° ΠΏΠΎΠ»Ρ ΠΈ ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½ΠΈΡ ΡΠΈΠΏΠ°
Algoritma untuk menentukan tipe data:
- ubah struct json menjadi struct datar
- menentukan tipe data bidang berdasarkan nilai
- menerapkan pemetaan dan mengetikkan aturan casting
Kemudian dari struktur json yang masuk:
{
"product_id": "1e48fb70-ef12-4ea9-ab10-fd0b910c49ce",
"product_price": 399.99,
"price_currency": "USD",
"product_type": "supplies",
"product_release_start": "2020-09-25T12:38:27.763000Z",
"images": {
"main": "picture1",
"sub": "picture2"
}
}
skema data akan diperoleh:
"product_id" character varying,
"product_price" numeric (38,18),
"price_currency" character varying,
"product_type" character varying,
"product_release_start" timestamp,
"images_main" character varying,
"images_sub" character varying
Kami juga berpikir bahwa pengguna harus dapat mengkonfigurasi partisi atau membagi data dalam database sesuai dengan kriteria lain dan menerapkan kemampuan untuk mengatur nama tabel dengan konstanta atau
tableName: '{{.product_type}}_{{._timestamp.Format "2006_01"}}'
Namun, struktur kejadian yang masuk dapat berubah saat runtime. Kami telah menerapkan algoritma untuk memeriksa perbedaan antara struktur tabel yang ada dan struktur peristiwa yang masuk. Jika ditemukan perbedaan, tabel akan diperbarui dengan kolom baru. Untuk melakukannya, gunakan kueri patch SQL:
#ΠΡΠΈΠΌΠ΅Ρ Π΄Π»Ρ Postgres
ALTER TABLE "schema"."table" ADD COLUMN new_column character varying
Arsitektur
Mengapa Anda perlu menulis acara ke sistem file dan tidak hanya menulisnya langsung ke database? Basis data tidak selalu bekerja dengan baik ketika berhadapan dengan sejumlah besar sisipan (
Open Source dan rencana masa depan
Pada titik tertentu, layanan ini menjadi seperti produk lengkap dan kami memutuskan untuk memasukkannya ke dalam Open Source. Saat ini, integrasi dengan Postgres, ClickHouse, BigQuery, Redshift, S3, Snowflake telah diterapkan. Semua integrasi mendukung mode pemuatan data batch dan streaming. Menambahkan dukungan untuk permintaan melalui API.
Skema integrasi saat ini terlihat seperti ini:
Meskipun layanan ini dapat digunakan secara mandiri (misalnya menggunakan Docker), kami juga memilikinya
β
β
β
Kami akan senang jika EventNative membantu Anda memecahkan masalah Anda!
Hanya pengguna terdaftar yang dapat berpartisipasi dalam survei.
Sistem pengumpulan statistik apa yang digunakan di perusahaan Anda
-
48,0%Google Analitik12
-
4,0%Segmen1
-
16,0%Lainnya (tulis di komentar) 4
-
32,0%Menerapkan layanan Anda8
25 pengguna memilih. 6 pengguna abstain.
Sumber: www.habr.com