Meie avatud lähtekoodiga ajalugu: kuidas tegime Go's analüüsiteenuse ja tegime selle avalikult kättesaadavaks

Praegu kogub peaaegu iga ettevõte maailmas statistikat kasutajate tegevuste kohta veebiressursil. Motivatsioon on selge – ettevõtted tahavad teada, kuidas nende toodet/veebi kasutatakse ning mõistavad paremini oma kasutajaid. Loomulikult on selle probleemi lahendamiseks turul suur hulk tööriistu – alates analüüsisüsteemidest, mis pakuvad andmeid armatuurlaudade ja graafikute kujul (näiteks Google Analytics) kliendiandmete platvormile, mis võimaldab teil koguda ja koondada andmeid erinevatest allikatest mis tahes laos (näiteks KATEGOORIA).

Kuid leidsime probleemi, mida pole veel lahendatud. Nii sündis EventNative — avatud lähtekoodiga analüüsiteenus. Lugege, miks otsustasime oma teenust arendada, mida see meile andis ja milline oli lõpptulemus (koos koodijuppidega).

Meie avatud lähtekoodiga ajalugu: kuidas tegime Go's analüüsiteenuse ja tegime selle avalikult kättesaadavaks

Miks peaksime oma teenust ise arendama?

Olid üheksakümnendad, elasime nii hästi kui suutsime. 2019. aastal töötasime välja API First Customer Data Platformi kSense, mis võimaldas koondada andmeid erinevatest allikatest (Facebooki reklaamid, Stripe, Salesforce, Google play, Google Analytics jne) mugavamaks andmeanalüüsiks, sõltuvuste tuvastamiseks jne. Oleme märganud, et paljud kasutajad kasutavad meie platvormi andmeanalüüsiks just Google Analyticsit (edaspidi GA). Rääkisime mõne kasutajaga ja saime teada, et nad vajavad oma toote kohta GA kaudu saadavaid analüütilisi andmeid, kuid Google proovib andmeid ja paljude jaoks ei ole GA kasutajaliides mugavuse standard. Vestelsime oma kasutajatega piisavalt ja mõistsime, et paljud kasutasid ka platvormi Segment (mis, muide, oli just eelmisel päeval müüdi 3.2 miljardi dollari eest).

Nad installisid oma veebiressurssi JavaScripti segmenti piksli ja andmed nende kasutajate käitumise kohta laaditi määratud andmebaasi (näiteks Postgres). Kuid Segmendil on ka oma varjukülg – hind. Näiteks kui veebiressursil on 90,000 1,000 MTU (igakuised jälgitavad kasutajad), siis tuleb kassasse maksta ~XNUMX $ kuus. Tekkis ka kolmas probleem – mõned brauseri laiendused (nt AdBlock) blokeerisid analüütika kogumise, kuna... Brauseri http-päringud saadeti GA ja Segmendi domeenidele. Klientide soovidest lähtuvalt oleme loonud analüütikateenuse, mis kogub (ilma proovivõtuta) täielikku andmekomplekti, on tasuta ja saab töötada meie enda taristul.

Kuidas teenus töötab

Teenus koosneb kolmest osast: javascripti piksel (mille hiljem masinakirjas ümber kirjutasime), serveriosa on realiseeritud GO keeles ning ettevõttesisese andmebaasina plaaniti kasutada Redshifti ja BigQueryt (hiljem lisati tugi ka Postgres, ClickHouse ja Snowflake).

Otsustati jätta GA ja segmendi sündmuste struktuur muutmata. Kõik, mida oli vaja, oli kopeerida kõik sündmused veebiressursist, kuhu piksel on installitud, meie taustaprogrammi. Nagu selgub, pole seda raske teha. Javascripti piksel alistas algse GA teegi meetodi uuega, mis dubleeris sündmuse meie süsteemi.

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

Segmendi piksliga on kõik lihtsam, sellel on vahevara meetodid, millest ühte kasutasime.


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

Lisaks sündmuste kopeerimisele oleme lisanud võimaluse saata suvaline 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'
});

Järgmisena räägime serveri osast. Taustaprogramm peaks vastu võtma http-päringuid, täitma need lisateabega, näiteks geoandmetega (aitäh maxmind selleks) ja salvestage see andmebaasi. Soovisime teha teenuse võimalikult mugavaks, et seda saaks kasutada minimaalse konfiguratsiooniga. Oleme rakendanud sissetuleva json-sündmuse struktuuri alusel andmeskeemi määramise funktsiooni. Andmetüübid on määratletud väärtustega. Pesastatud objektid lagunevad ja taandatakse tasaseks struktuuriks:

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

Kuid massiivid teisendatakse praegu lihtsalt stringideks, sest Kõik relatsiooniandmebaasid ei toeta korduvaid välju. Samuti on võimalik väljade nimesid muuta või kustutada valikuliste vastendusreeglite abil. Need võimaldavad vajadusel muuta andmeskeemi või teisendada üht andmetüüpi teiseks. Näiteks kui json-väli sisaldab stringi ajatempliga (field_3_sub_field_1_sub_sub_field_1 ülaltoodud näitest), siis selleks, et luua andmebaasis ajatempli tüübiga väli, tuleb konfiguratsioonis kirjutada vastendusreegel. Teisisõnu määrab välja andmetüübi esmalt json-väärtus ja seejärel rakendatakse tüübi ülekandmise reegel (kui see on konfigureeritud). Oleme tuvastanud 4 peamist andmetüüpi: STRING, FLOAT64, INT64 ja TIMESTAMP. Kaardistamise ja tüübi ülekandmise reeglid näevad välja järgmised:

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

Andmetüübi määramise algoritm:

  • teisendada json-struktuur tasaseks struktuuriks
  • väljade andmetüübi määramine väärtuste järgi
  • kaardistamise ja tüübi valamise reeglite rakendamine

Seejärel sissetulevast json-struktuurist:

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

saadakse andmeskeem:

"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

Samuti arvasime, et kasutajal peaks olema võimalus seadistada andmebaasis partitsioonide jagamist või jagada andmeid muude kriteeriumide järgi ning rakendasime võimaluse määrata tabeli nimi konstandiga või väljendus konfiguratsioonis. Allolevas näites salvestatakse sündmus tabelisse nimega, mis arvutatakse väljade product_type ja _timestamp väärtuste põhjal (näiteks tarvikud_2020_10):

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

Sissetulevate sündmuste struktuur võib aga käitusajal muutuda. Oleme rakendanud algoritmi, et kontrollida erinevust olemasoleva tabeli struktuuri ja sissetuleva sündmuse struktuuri vahel. Kui leitakse erinevus, täiendatakse tabelit uute väljadega. Selleks kasutage SQL-i paigapäringut:

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

arhitektuur

Meie avatud lähtekoodiga ajalugu: kuidas tegime Go's analüüsiteenuse ja tegime selle avalikult kättesaadavaks

Miks on vaja sündmused failisüsteemi kirjutada, mitte lihtsalt otse andmebaasi kirjutada? Andmebaasid ei tööta alati hästi, kui käsitletakse suurt hulka lisasid (Postgresi soovitused). Selleks kirjutab Logger sissetulevad sündmused faili ja eraldi gorutiinis (lõime) Faililugeja loeb faili, seejärel teisendatakse ja määratakse andmed. Pärast seda, kui tabelihaldur on veendunud, et tabeliskeem on ajakohane, kirjutatakse andmed andmebaasi ühe partiina. Seejärel lisasime võimaluse kirjutada andmeid otse andmebaasi, kuid kasutame seda režiimi sündmuste puhul, mida pole palju – näiteks konversioonid.

Avatud lähtekood ja tulevikuplaanid

Mingil hetkel hakkas teenus välja nägema täisväärtusliku tootena ja otsustasime selle avatud lähtekoodiga välja anda. Hetkel on juurutatud integratsioonid Postgresi, ClickHouse'i, BigQuery, Redshift, S3, Snowflake'iga. Kõik integratsioonid toetavad nii andmete pakett- kui ka voogesituse režiimi. Lisatud on API kaudu päringute tugi.

Praegune integratsiooniskeem näeb välja selline:

Meie avatud lähtekoodiga ajalugu: kuidas tegime Go's analüüsiteenuse ja tegime selle avalikult kättesaadavaks

Kuigi teenust saab kasutada iseseisvalt (näiteks Dockeri abil), on meil ka hostitud versioon, milles saate seadistada integratsiooni andmelaoga, lisada oma domeenile CNAME-i ja vaadata sündmuste arvu statistikat. Meie lähiplaanid on lisada võimalus koondada mitte ainult veebiressursi statistikat, vaid ka andmeid välistest andmeallikatest ja salvestada need teie valitud salvestusruumi!

→ GitHub
→ Документация
→ Lõtv

Meil on hea meel, kui EventNative aitab teie probleeme lahendada!

Küsitluses saavad osaleda ainult registreerunud kasutajad. Logi sissepalun.

Millist statistika kogumise süsteemi teie ettevõttes kasutatakse?

  • 48,0%Google Analytics 12

  • 4,0%Segment 1

  • 16,0%Teine (kirjuta kommentaaridesse)4

  • 32,0%Rakendasin teie teenust8

25 kasutajat hääletas. 6 kasutajat jäi erapooletuks.

Allikas: www.habr.com

Lisa kommentaar