Zgodovina naše odprte kode: kako smo naredili analitično storitev v Go in jo naredili javno dostopno

Trenutno skoraj vsako podjetje na svetu zbira statistične podatke o dejanjih uporabnikov na spletnem viru. Motivacija je jasna – podjetja želijo vedeti, kako se uporablja njihov izdelek/spletna stran in bolje razumeti svoje uporabnike. Seveda je na trgu ogromno orodij za reševanje te težave – od analitičnih sistemov, ki podajajo podatke v obliki nadzornih plošč in grafov (npr. Google Analytics) na Customer Data Platform, ki vam omogoča zbiranje in združevanje podatkov iz različnih virov v katerem koli skladišču (npr. Segment).

Vendar smo našli problem, ki še ni rešen. Tako se je rodilo EventNative — odprtokodna analitična storitev. Preberite, zakaj smo se odločili razviti lastno storitev, kaj nam je dala in kakšen je bil končni rezultat (z delčki kode).

Zgodovina naše odprte kode: kako smo naredili analitično storitev v Go in jo naredili javno dostopno

Zakaj bi morali razvijati lastno storitev?

Bila so devetdeseta leta, preživeli smo, kakor smo znali. 2019 smo razvili API First Customer Data Platform kSense, ki je omogočila agregacijo podatkov iz različnih virov (Facebook oglasi, Stripe, Salesforce, Google play, Google Analytics itd.) za bolj priročno analizo podatkov, prepoznavanje odvisnosti itd. Opazili smo, da veliko uporabnikov uporablja našo platformo za analizo podatkov, posebej Google Analytics (v nadaljevanju GA). Pogovarjali smo se z nekaterimi uporabniki in ugotovili, da potrebujejo analitične podatke za svoj izdelek, ki jih prejmejo z GA, vendar Google vzorči podatke in za mnoge uporabniški vmesnik GA ni standard priročnosti. Imeli smo dovolj pogovorov z našimi uporabniki in ugotovili, da mnogi uporabljajo tudi platformo Segment (ki je, mimogrede, ravno pred dnevi prodal za 3.2 milijarde dolarjev).

Na svoj spletni vir so namestili piksel Segment javascript in podatke o vedenju njihovih uporabnikov so naložili v navedeno bazo podatkov (na primer Postgres). Ima pa Segment tudi svojo slabo stran - ceno. Na primer, če ima spletni vir 90,000 MTU (mesečno sledenih uporabnikov), potem morate blagajni plačati ~1,000 $ na mesec. Obstajala je tudi tretja težava - nekatere razširitve brskalnika (kot je AdBlock) so blokirale zbiranje analitike, ker... http zahteve iz brskalnika so bile poslane domeni GA in Segment. Na podlagi želja naših naročnikov smo izdelali analitično storitev, ki zbira celoten nabor podatkov (brez vzorčenja), je brezplačna in lahko deluje na lastni infrastrukturi.

Kako storitev deluje

Storitev je sestavljena iz treh delov: javascript pixel (ki smo ga kasneje prepisali v tipkopis), strežniški del je implementiran v jeziku GO, načrtovana pa je bila uporaba Redshift in BigQuery kot lastne podatkovne baze (kasneje so dodali podporo za Postgres, ClickHouse in Snowflake).

Odločeno je bilo, da ostane struktura dogodkov GA in segmenta nespremenjena. Vse, kar je bilo potrebno, je bilo podvojiti vse dogodke iz spletnega vira, kjer je nameščen piksel, v naše zaledje. Kot se je izkazalo, tega ni težko narediti. Piksel Javascript je preglasil izvirno metodo knjižnice GA z novo, ki je podvojila dogodek v naš sistem.

//'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);
        });
    });
}

S pikselom Segment je vse preprostejše; ima metode vmesne programske opreme, eno izmed njih smo uporabili.


//'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.');
}

Poleg kopiranja dogodkov smo dodali možnost pošiljanja poljubnih json:


//Отправка событий с произвольным 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'
});

Nato se pogovorimo o strežniškem delu. Zaledje bi moralo sprejemati zahteve http, jih napolniti z dodatnimi informacijami, na primer z geografskimi podatki (hvala maxmind za to) in zabeležite v bazo podatkov. Storitev smo želeli narediti čim bolj priročno, tako da jo je mogoče uporabljati z minimalno konfiguracijo. Implementirali smo funkcionalnost določanja podatkovne sheme glede na strukturo vhodnega json dogodka. Tipi podatkov so definirani z vrednostmi. Ugnezdeni predmeti so razčlenjeni in zmanjšani na ravno strukturo:

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

Vendar se nizi trenutno preprosto pretvorijo v nize, ker Vse relacijske baze podatkov ne podpirajo ponavljajočih se polj. Prav tako je mogoče spremeniti imena polj ali jih izbrisati z izbirnimi pravili preslikave. Omogočajo vam, da po potrebi spremenite podatkovno shemo ali pretvorite eno vrsto podatkov v drugo. Na primer, če polje json vsebuje niz s časovnim žigom (polje_3_podpolje_1_pod_podpolje_1 iz zgornjega primera), potem morate za ustvarjanje polja v bazi podatkov z vrsto časovnega žiga v konfiguracijo napisati pravilo preslikave. Z drugimi besedami, podatkovni tip polja je najprej določen z vrednostjo json, nato pa se uporabi pravilo za pretvorbo tipa (če je konfigurirano). Identificirali smo 4 glavne vrste podatkov: STRING, FLOAT64, INT64 in TIMESTAMP. Pravila za preslikavo in pretvorbo tipa izgledajo takole:

rules:
  - "/field_1/subfield_1 -> " #правило удаления поля
  - "/field_2/subfield_1 -> /field_10/subfield_1" #правило переноса поля
  - "/field_3/subfield_1/subsubfield_1 -> (timestamp) /field_20" #правило переноса поля и приведения типа

Algoritem za določanje vrste podatkov:

  • pretvori strukturo json v ravno strukturo
  • določanje podatkovnega tipa polj po vrednostih
  • uporaba pravil za preslikavo in ulivanje tipov

Nato iz dohodne strukture json:

{
    "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"
    }
}

podatkovna shema bo pridobljena:

"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

Pomislili smo tudi, da mora imeti uporabnik možnost konfiguriranja particioniranja ali razdelitve podatkov v bazi podatkov po drugih kriterijih in implementirali možnost nastavitve imena tabele s konstanto oz. izraz v konfiguraciji. V spodnjem primeru bo dogodek shranjen v tabelo z imenom, izračunanim na podlagi vrednosti polj product_type in _timestamp (npr. dobave_2020_10):

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

Vendar se lahko struktura dohodnih dogodkov med izvajanjem spremeni. Implementirali smo algoritem za preverjanje razlike med strukturo obstoječe tabele in strukturo dohodnega dogodka. Če se ugotovi razlika, bo tabela posodobljena z novimi polji. Če želite to narediti, uporabite poizvedbo SQL za popravek:

#Пример для Postgres
ALTER TABLE "schema"."table" ADD COLUMN new_column character varying

arhitektura

Zgodovina naše odprte kode: kako smo naredili analitično storitev v Go in jo naredili javno dostopno

Zakaj morate dogodke pisati v datotečni sistem in ne samo neposredno v bazo podatkov? Baze podatkov ne delujejo vedno dobro, ko imajo opravka z velikim številom vstavkov (Postgres priporočila). Da bi to naredil, Logger zapiše dohodne dogodke v datoteko in v ločeni goroutini (nit) Reader datotek prebere datoteko, nato pa se podatki pretvorijo in določijo. Ko se upravitelj tabel prepriča, da je shema tabele posodobljena, bodo podatki v enem paketu zapisani v bazo podatkov. Naknadno smo dodali možnost neposrednega zapisa podatkov v bazo, vendar ta način uporabljamo za dogodke, ki jih ni veliko - na primer konverzije.

Odprta koda in načrti za prihodnost

Na neki točki je storitev začela izgledati kot polnopravni izdelek in odločili smo se, da jo objavimo v odprtokodni različici. Trenutno so implementirane integracije s Postgres, ClickHouse, BigQuery, Redshift, S3, Snowflake. Vse integracije podpirajo paketni in pretočni način nalaganja podatkov. Dodana podpora za zahteve prek API-ja.

Trenutna integracijska shema izgleda takole:

Zgodovina naše odprte kode: kako smo naredili analitično storitev v Go in jo naredili javno dostopno

Čeprav je storitev mogoče uporabljati samostojno (na primer z uporabo Dockerja), jo tudi imamo gostovana različica, v katerem lahko nastavite integracijo s podatkovnim skladiščem, svoji domeni dodate CNAME in si ogledate statistiko o številu dogodkov. Naši takojšnji načrti so, da dodamo možnost združevanja ne samo statističnih podatkov iz spletnega vira, ampak tudi podatkov iz zunanjih virov podatkov in njihovo shranjevanje v katero koli shrambo po vaši izbiri!

→ GitHub
→ Dokumentacija
→ Slack

Veseli bomo, če vam bo EventNative pomagal rešiti težave!

V anketi lahko sodelujejo samo registrirani uporabniki. Prijaviti se, prosim.

Kakšen sistem zbiranja statistike uporabljate v vašem podjetju?

  • 48,0%Google Analytics12

  • 4,0%Segment1

  • 16,0%Še en (napišite v komentarje)4

  • 32,0%Implementirali vašo storitev8

Glasovalo je 25 uporabnikov. 6 uporabnikov se je vzdržalo.

Vir: www.habr.com

Dodaj komentar