Sejarah sumber terbuka kami: cara kami membuat perkhidmatan analitis dalam Go dan menjadikannya tersedia secara terbuka

Pada masa ini, hampir setiap syarikat di dunia mengumpul statistik tentang tindakan pengguna pada sumber web. Motivasinya jelas - syarikat ingin mengetahui cara produk/laman web mereka digunakan dan lebih memahami pengguna mereka. Sudah tentu, terdapat sejumlah besar alat di pasaran untuk menyelesaikan masalah ini - daripada sistem analitik yang menyediakan data dalam bentuk papan pemuka dan graf (contohnya google Analytics) kepada Platform Data Pelanggan, yang membolehkan anda mengumpul dan mengagregat data daripada sumber yang berbeza dalam mana-mana gudang (contohnya Segmen).

Tetapi kami menemui masalah yang belum diselesaikan. Maka lahirlah EventNative β€” perkhidmatan analisis sumber terbuka. Baca tentang sebab kami memutuskan untuk membangunkan perkhidmatan kami sendiri, perkara yang diberikan kepada kami dan hasil akhirnya (dengan kepingan kod).

Sejarah sumber terbuka kami: cara kami membuat perkhidmatan analitis dalam Go dan menjadikannya tersedia secara terbuka

Mengapa kita perlu membangunkan perkhidmatan kita sendiri?

Ia adalah tahun sembilan puluhan, kami bertahan sebaik mungkin. 2019, kami membangunkan Platform Data Pelanggan Pertama API kSense, yang memungkinkan untuk mengagregat data daripada sumber yang berbeza (iklan Facebook, Stripe, Salesforce, Google play, Google Analitis, dll.) untuk analisis data yang lebih mudah, mengenal pasti kebergantungan, dsb. Kami mendapati ramai pengguna menggunakan platform kami untuk analisis data khususnya Google Analitis (selepas ini GA). Kami bercakap dengan beberapa pengguna dan mendapati bahawa mereka memerlukan data analitik untuk produk mereka yang mereka terima menggunakan GA, tetapi data sampel Google dan bagi kebanyakan orang, antara muka Pengguna GA bukanlah standard kemudahan. Kami mempunyai perbualan yang mencukupi dengan pengguna kami dan menyedari bahawa ramai juga menggunakan platform Segmen (yang sebenarnya, hanya pada hari yang lain dijual pada harga $3.2 bilion).

Mereka memasang piksel javascript Segmen pada sumber web mereka dan data tentang gelagat pengguna mereka telah dimuatkan ke dalam pangkalan data yang ditentukan (contohnya Postgres). Tetapi Segmen juga mempunyai kelemahannya - harga. Contohnya, jika sumber web mempunyai 90,000 MTU (pengguna yang dijejaki bulanan), maka anda perlu membayar ~1,000 $ sebulan kepada juruwang. Terdapat juga masalah ketiga - beberapa sambungan penyemak imbas (seperti AdBlock) menyekat pengumpulan analitik kerana... Permintaan http daripada penyemak imbas telah dihantar ke domain GA dan Segmen. Berdasarkan kehendak pelanggan kami, kami telah mencipta perkhidmatan analitik yang mengumpul set lengkap data (tanpa pensampelan), adalah percuma dan boleh bekerja pada infrastruktur kami sendiri.

Cara perkhidmatan berfungsi

Perkhidmatan ini terdiri daripada tiga bahagian: piksel javascript (yang kemudian kami tulis semula dalam skrip taip), bahagian pelayan dilaksanakan dalam bahasa GO dan ia telah dirancang untuk menggunakan Redshift dan BigQuery sebagai pangkalan data dalaman (kemudian mereka menambah sokongan untuk Postgres, ClickHouse dan Snowflake).

Ia telah memutuskan untuk membiarkan struktur acara GA dan Segmen tidak berubah. Apa yang diperlukan ialah menduplikasi semua acara daripada sumber web tempat piksel dipasang ke bahagian belakang kami. Ternyata, ini tidak sukar dilakukan. Piksel Javascript menggantikan kaedah perpustakaan GA asal dengan kaedah baharu, yang menduplikasi peristiwa ke dalam 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 piksel Segmen semuanya lebih mudah; ia mempunyai kaedah middleware, salah satunya yang 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 menambah keupayaan untuk menghantar json sewenang-wenangnya:


//ΠžΡ‚ΠΏΡ€Π°Π²ΠΊΠ° событий с ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½Ρ‹ΠΌ 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'
});

Seterusnya, mari kita bercakap tentang bahagian pelayan. Bahagian belakang harus menerima permintaan http, mengisinya dengan maklumat tambahan, contohnya, data geo (terima kasih maxmind untuk ini) dan merekodkannya dalam pangkalan data. Kami mahu menjadikan perkhidmatan itu semudah mungkin supaya ia boleh digunakan dengan konfigurasi yang minimum. Kami telah melaksanakan fungsi menentukan skema data berdasarkan struktur acara json masuk. Jenis data ditakrifkan oleh nilai. Objek bersarang diuraikan dan dikurangkan kepada struktur rata:

//входящий 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"
}

Walau bagaimanapun, tatasusunan kini hanya ditukar kepada rentetan kerana Tidak semua pangkalan data hubungan menyokong medan berulang. Anda juga boleh menukar nama medan atau memadamkannya menggunakan peraturan pemetaan pilihan. Mereka membenarkan anda menukar skema data jika perlu atau menukar satu jenis data kepada yang lain. Sebagai contoh, jika medan json mengandungi rentetan dengan cap waktu (field_3_sub_field_1_sub_sub_field_1 daripada contoh di atas), maka untuk mencipta medan dalam pangkalan data dengan jenis cap waktu, anda perlu menulis peraturan pemetaan dalam konfigurasi. Dalam erti kata lain, jenis data medan ditentukan terlebih dahulu oleh nilai json, dan kemudian peraturan penghantaran jenis (jika dikonfigurasikan) digunakan. Kami telah mengenal pasti 4 jenis data utama: STRING, FLOAT64, INT64 dan TIMESTAMP. Peraturan pemetaan dan pemutus jenis kelihatan 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 jenis data:

  • menukar struktur json kepada struktur rata
  • menentukan jenis data medan mengikut nilai
  • menggunakan peraturan pemetaan dan tuangan jenis

Kemudian dari struktur json 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 diperolehi:

"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 berpendapat bahawa pengguna sepatutnya dapat mengkonfigurasi pembahagian atau membahagikan data dalam pangkalan data mengikut kriteria lain dan melaksanakan keupayaan untuk menetapkan nama jadual dengan pemalar atau ungkapan dalam konfigurasi. Dalam contoh di bawah, acara akan disimpan ke jadual dengan nama yang dikira berdasarkan nilai medan product_type dan _timestamp (contohnya bekalan_2020_10):

tableName: '{{.product_type}}_{{._timestamp.Format "2006_01"}}'

Walau bagaimanapun, struktur acara masuk boleh berubah semasa masa jalan. Kami telah melaksanakan algoritma untuk menyemak perbezaan antara struktur jadual sedia ada dan struktur acara masuk. Jika perbezaan ditemui, jadual akan dikemas kini dengan medan baharu. Untuk melakukan ini, gunakan pertanyaan SQL patch:

#ΠŸΡ€ΠΈΠΌΠ΅Ρ€ для Postgres
ALTER TABLE "schema"."table" ADD COLUMN new_column character varying

seni bina

Sejarah sumber terbuka kami: cara kami membuat perkhidmatan analitis dalam Go dan menjadikannya tersedia secara terbuka

Mengapa anda perlu menulis acara ke sistem fail, dan bukan hanya menulisnya terus ke pangkalan data? Pangkalan data tidak selalu berfungsi dengan baik apabila berurusan dengan sejumlah besar sisipan (Cadangan postgres). Untuk melakukan ini, Logger menulis peristiwa masuk ke fail dan dalam goroutine (benang) yang berasingan Pembaca fail membaca fail, kemudian data ditukar dan ditentukan. Selepas pengurus Jadual memastikan bahawa skema jadual adalah terkini, data akan ditulis ke pangkalan data dalam satu kelompok. Selepas itu, kami menambah keupayaan untuk menulis data terus ke pangkalan data, tetapi kami menggunakan mod ini untuk acara yang tidak banyak - contohnya, penukaran.

Sumber Terbuka dan rancangan untuk masa depan

Pada satu ketika, perkhidmatan itu mula kelihatan seperti produk lengkap dan kami memutuskan untuk mengeluarkannya kepada Sumber Terbuka. Pada masa ini, penyepaduan dengan Postgres, ClickHouse, BigQuery, Redshift, S3, Snowflake telah dilaksanakan. Semua penyepaduan menyokong kedua-dua mod kumpulan dan penstriman pemuatan data. Menambah sokongan untuk permintaan melalui API.

Skim integrasi semasa kelihatan seperti ini:

Sejarah sumber terbuka kami: cara kami membuat perkhidmatan analitis dalam Go dan menjadikannya tersedia secara terbuka

Walaupun perkhidmatan boleh digunakan secara bebas (contohnya menggunakan Docker), kami juga mempunyai versi dihoskan, di mana anda boleh menyediakan penyepaduan dengan gudang data, menambah CNAME pada domain anda dan melihat statistik tentang bilangan acara. Rancangan segera kami adalah untuk menambah keupayaan untuk mengagregatkan bukan sahaja statistik daripada sumber web, tetapi juga data daripada sumber data luaran dan menyimpannya ke mana-mana storan pilihan anda!

β†’ GitHub
β†’ Dokumentasi
β†’ Slack

Kami akan gembira jika EventNative membantu menyelesaikan masalah anda!

Hanya pengguna berdaftar boleh mengambil bahagian dalam tinjauan. Log masuk, Sama-sama.

Apakah sistem pengumpulan statistik yang digunakan dalam syarikat anda?

  • 48,0% Google Analytics12

  • 4,0% Segmen1

  • 16,0% Satu lagi (tulis dalam komen)4

  • 32,0% Melaksanakan perkhidmatan anda8

25 pengguna mengundi. 6 pengguna berpantang.

Sumber: www.habr.com

Tambah komen