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

Iegādājieties uzticamu mitināŔanu vietnēm ar DDoS aizsardzÄ«bu, VPS VDS serveriem šŸ”„ Iegādājieties uzticamu tÄ«mekļa vietņu mitināŔanu ar DDoS aizsardzÄ«bu, VPS VDS serveriem | ProHoster