Mūsu atvērtā pirmkoda vēsture: kā mēs pakalpojumā Go izveidojām analīzes pakalpojumu un padarījām to publiski pieejamu

Pašlaik gandrīz katrs uzņēmums pasaulē apkopo statistiku par lietotāja darbībām tīmekļa resursā. Motivācija ir skaidra – uzņēmumi vēlas uzzināt, kā tiek izmantots viņu produkts/vietne, un labāk izprast savus lietotājus. Protams, tirgū ir pieejams liels skaits rīku šīs problēmas risināšanai — no analītikas sistēmām, kas nodrošina datus informācijas paneļu un grafiku veidā (piemēram, Google Analytics) uz klientu datu platformu, kas ļauj vākt un apkopot datus no dažādiem avotiem jebkurā noliktavā (piemēram, Segments).

Bet mēs atradām problēmu, kas vēl nav atrisināta. Tā piedzima EventNative — atvērtā koda analīzes pakalpojums. Lasiet par to, kāpēc mēs nolēmām izstrādāt savu pakalpojumu, ko tas mums sniedza un kāds bija gala rezultāts (ar koda daļām).

Mūsu atvērtā pirmkoda vēsture: kā mēs pakalpojumā Go izveidojām analīzes pakalpojumu un padarījām to publiski pieejamu

Kāpēc mums pašiem jāattīsta savs pakalpojums?

Bija deviņdesmitie gadi, mēs izdzīvojām, kā varējām. 2019. gadā mēs izstrādājām API First Customer Data Platform kSense, kas ļāva apkopot datus no dažādiem avotiem (Facebook reklāmas, Stripe, Salesforce, Google play, Google Analytics u.c.) ērtākai datu analīzei, atkarību noteikšanai utt. Esam ievērojuši, ka daudzi lietotāji izmanto mūsu platformu datu analīzei, īpaši Google Analytics (turpmāk GA). Mēs runājām ar dažiem lietotājiem un noskaidrojām, ka viņiem ir nepieciešami sava produkta analītikas dati, ko viņi saņem, izmantojot GA, taču Google ņem datu paraugus un daudziem GA lietotāja interfeiss nav ērtības standarts. Mums bija pietiekami daudz sarunu ar saviem lietotājiem un sapratām, ka daudzi arī izmantoja segmentu platformu (kas, starp citu, bija tikai citu dienu pārdots par 3.2 miljardiem dolāru).

Viņi savā tīmekļa resursā instalēja segmenta javascript pikseļu, un dati par lietotāju uzvedību tika ielādēti norādītajā datu bāzē (piemēram, Postgres). Taču Segmentam ir arī savs mīnuss – cena. Piemēram, ja tīmekļa resursam ir 90,000 1,000 MTU (ikmēneša izsekotie lietotāji), tad kasierim ir jāmaksā ~XNUMX USD mēnesī. Bija arī trešā problēma – daži pārlūkprogrammas paplašinājumi (piemēram, AdBlock) bloķēja analītikas apkopošanu, jo... http pieprasījumi no pārlūkprogrammas tika nosūtīti uz GA un Segment domēniem. Pamatojoties uz mūsu klientu vēlmēm, esam izveidojuši analītikas pakalpojumu, kas savāc pilnu datu kopumu (bez paraugu ņemšanas), ir bezmaksas un var darboties savā infrastruktūrā.

Kā pakalpojums darbojas

Pakalpojums sastāv no trim daļām: javascript pikseļa (kuru vēlāk pārrakstījām mašīnrakstā), servera daļa ir realizēta GO valodā, kā arī bija plānots izmantot Redshift un BigQuery kā iekšējo datu bāzi (vēlāk pievienoja atbalstu Postgres, ClickHouse un Snowflake).

Tika nolemts GA un segmentu notikumu struktūru atstāt nemainīgu. Viss, kas bija nepieciešams, bija dublēt visus notikumus no tīmekļa resursa, kurā pikselis ir instalēts, uz mūsu aizmugursistēmu. Kā izrādās, to nav grūti izdarīt. Javascript pikselis ignorēja sākotnējo GA bibliotēkas metodi ar jaunu, kas dublēja notikumu mūsu sistēmā.

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

Ar Segment pikseļu viss ir vienkāršāk; tam ir starpprogrammatūras metodes, no kurām vienu mēs izmantojām.


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

Papildus notikumu kopēšanai esam pievienojuši iespēju nosūtīt patvaļīgu 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'
});

Tālāk parunāsim par servera daļu. Aizmugursistēmai vajadzētu pieņemt http pieprasījumus, aizpildīt tos ar papildu informāciju, piemēram, ģeogrāfiskajiem datiem (paldies maxmind šim) un ierakstiet to datu bāzē. Mēs vēlējāmies pakalpojumu padarīt pēc iespējas ērtāku, lai to varētu izmantot ar minimālu konfigurāciju. Mēs esam ieviesuši datu shēmas noteikšanas funkcionalitāti, pamatojoties uz ienākošā JSON notikuma struktūru. Datu tipus nosaka vērtības. Ligzdotie objekti tiek sadalīti un samazināti līdz plakanai struktūrai:

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

Tomēr pašlaik masīvi tiek vienkārši pārveidoti par virknēm, jo Ne visas relāciju datu bāzes atbalsta atkārtotus laukus. Ir iespējams arī mainīt lauku nosaukumus vai dzēst tos, izmantojot izvēles kartēšanas noteikumus. Tie ļauj mainīt datu shēmu, ja nepieciešams, vai pārveidot vienu datu tipu citā. Piemēram, ja json laukā ir virkne ar laikspiedolu (field_3_sub_field_1_sub_sub_field_1 no iepriekš minētā piemēra), tad, lai datu bāzē izveidotu lauku ar laikspiedola veidu, konfigurācijā ir jāieraksta kartēšanas kārtula. Citiem vārdiem sakot, lauka datu tipu vispirms nosaka json vērtība, un pēc tam tiek lietots tipa apraides kārtula (ja tā ir konfigurēta). Mēs esam identificējuši 4 galvenos datu tipus: STRING, FLOAT64, INT64 un TIMESTAMP. Kartēšanas un veidu izdalīšanas noteikumi izskatās šādi:

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

Algoritms datu veida noteikšanai:

  • pārveidot json struktūru plakanā struktūrā
  • lauku datu tipa noteikšana pēc vērtībām
  • piemērojot kartēšanas un tipu liešanas noteikumus

Pēc tam no ienākošās JSON struktūras:

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

tiks iegūta datu shēma:

"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

Mēs arī domājām, ka lietotājam jāspēj konfigurēt sadalīšanu vai sadalīt datus datu bāzē pēc citiem kritērijiem un ieviesām iespēju iestatīt tabulas nosaukumu ar konstantu vai izteiksme konfigurācijā. Tālāk esošajā piemērā notikums tiks saglabāts tabulā ar nosaukumu, kas aprēķināts, pamatojoties uz lauku product_type un _timestamp vērtībām (piemēram, piegādes_2020_10):

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

Tomēr ienākošo notikumu struktūra izpildes laikā var mainīties. Mēs esam ieviesuši algoritmu, lai pārbaudītu atšķirību starp esošās tabulas struktūru un ienākošā notikuma struktūru. Ja tiek konstatēta atšķirība, tabula tiks atjaunināta ar jauniem laukiem. Lai to izdarītu, izmantojiet ielāpa SQL vaicājumu:

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

Arhitektūra

Mūsu atvērtā pirmkoda vēsture: kā mēs pakalpojumā Go izveidojām analīzes pakalpojumu un padarījām to publiski pieejamu

Kāpēc notikumi jāraksta failu sistēmā, nevis tikai tiešā veidā datu bāzē? Datu bāzes ne vienmēr darbojas labi, strādājot ar lielu skaitu ieliktņu (Postgres ieteikumi). Lai to izdarītu, Logger ieraksta ienākošos notikumus failā un atsevišķā gorutīnā (pavedienā) Failu lasītājs nolasa failu, pēc tam tiek konvertēti un noteikti dati. Kad tabulu pārvaldnieks ir pārliecinājies, ka tabulas shēma ir atjaunināta, dati tiks ierakstīti datu bāzē vienā partijā. Pēc tam mēs pievienojām iespēju rakstīt datus tieši datu bāzē, bet mēs izmantojam šo režīmu notikumiem, kuru skaits nav liels, piemēram, reklāmguvumiem.

Open Source un nākotnes plāni

Kādā brīdī pakalpojums sāka izskatīties kā pilnvērtīgs produkts, un mēs nolēmām to izlaist atvērtā koda versijā. Šobrīd ir ieviestas integrācijas ar Postgres, ClickHouse, BigQuery, Redshift, S3, Snowflake. Visas integrācijas atbalsta gan pakešu, gan straumēšanas datu ielādes režīmus. Pievienots atbalsts pieprasījumiem, izmantojot API.

Pašreizējā integrācijas shēma izskatās šādi:

Mūsu atvērtā pirmkoda vēsture: kā mēs pakalpojumā Go izveidojām analīzes pakalpojumu un padarījām to publiski pieejamu

Lai gan pakalpojumu var izmantot neatkarīgi (piemēram, izmantojot Docker), arī mums ir mitinātā versija, kurā varat iestatīt integrāciju ar datu noliktavu, pievienot savam domēnam CNAME un skatīt statistiku par notikumu skaitu. Mūsu tuvākie plāni ir pievienot iespēju apkopot ne tikai statistiku no tīmekļa resursiem, bet arī datus no ārējiem datu avotiem un saglabāt tos jebkurā jūsu izvēlētā krātuvē!

→ GitHub
→ Документация
→ Ļengans

Mēs priecāsimies, ja EventNative palīdzēs atrisināt jūsu problēmas!

Aptaujā var piedalīties tikai reģistrēti lietotāji. Ielogoties, lūdzu.

Kāda statistikas vākšanas sistēma tiek izmantota jūsu uzņēmumā?

  • 48,0%Google Analytics12

  • 4,0%Segments 1

  • 16,0%Vēl viens (raksti komentāros)4

  • 32,0%Ieviesa jūsu pakalpojumu8

Nobalsoja 25 lietotāji. 6 lietotāji atturējās.

Avots: www.habr.com

Pievieno komentāru