Statistikat e faqes dhe ruajtja juaj e vogël

Webalizer dhe Google Analytics më kanë ndihmuar të fitoj njohuri për atë që po ndodh në faqet e internetit për shumë vite. Tani e kuptoj që ato ofrojnë shumë pak informacion të dobishëm. Duke pasur akses në skedarin tuaj access.log, është shumë e lehtë të kuptosh statistikat dhe të zbatosh mjete mjaft elementare, si sqlite, html, gjuha sql dhe çdo gjuhë programimi skriptimi.

Burimi i të dhënave për Webalizer është skedari access.log i serverit. Ja si duken shiritat dhe numrat e tij, nga të cilët është i qartë vetëm vëllimi i përgjithshëm i trafikut:

Statistikat e faqes dhe ruajtja juaj e vogël
Statistikat e faqes dhe ruajtja juaj e vogël
Mjete të tilla si Google Analytics mbledhin të dhëna nga faqja e ngarkuar vetë. Ata na tregojnë disa diagrame dhe rreshta, në bazë të të cilave shpesh është e vështirë të nxirren përfundime të sakta. Ndoshta duhej bërë më shumë përpjekje? nuk e di.

Pra, çfarë doja të shihja në statistikat e vizitorëve të faqes në internet?

Trafiku i përdoruesve dhe i robotëve

Shpesh trafiku i faqes është i kufizuar dhe është e nevojshme të shihet se sa trafik i dobishëm po përdoret. Për shembull, si kjo:

Statistikat e faqes dhe ruajtja juaj e vogël

Kërkesa e raportit SQL

SELECT
1 as 'StackedArea: Traffic generated by Users and Bots',
strftime('%d.%m', datetime(FCT.EVENT_DT, 'unixepoch')) AS 'Day',
SUM(CASE WHEN USG.AGENT_BOT!='n.a.' THEN FCT.BYTES ELSE 0 END)/1000 AS 'Bots, KB',
SUM(CASE WHEN USG.AGENT_BOT='n.a.' THEN FCT.BYTES ELSE 0 END)/1000 AS 'Users, KB'
FROM
  FCT_ACCESS_USER_AGENT_DD FCT,
  DIM_USER_AGENT USG
WHERE FCT.DIM_USER_AGENT_ID=USG.DIM_USER_AGENT_ID
  AND datetime(FCT.EVENT_DT, 'unixepoch') >= date('now', '-14 day')
GROUP BY strftime('%d.%m', datetime(FCT.EVENT_DT, 'unixepoch'))
ORDER BY FCT.EVENT_DT

Grafiku tregon aktivitetin e vazhdueshëm të robotëve. Do të ishte interesante të studioheshin në detaje përfaqësuesit më aktivë.

Bots të bezdisshëm

Ne i klasifikojmë robotët bazuar në informacionin e agjentit të përdoruesit. Statistikat shtesë mbi trafikun ditor, numri i kërkesave të suksesshme dhe të pasuksesshme japin një ide të mirë të aktivitetit të robotëve.

Statistikat e faqes dhe ruajtja juaj e vogël

Kërkesa e raportit SQL

SELECT 
1 AS 'Table: Annoying Bots',
MAX(USG.AGENT_BOT) AS 'Bot',
ROUND(SUM(FCT.BYTES)/1000 / 14.0, 1) AS 'KB per Day',
ROUND(SUM(FCT.IP_CNT) / 14.0, 1) AS 'IPs per Day',
ROUND(SUM(CASE WHEN STS.STATUS_GROUP IN ('Client Error', 'Server Error') THEN FCT.REQUEST_CNT / 14.0 ELSE 0 END), 1) AS 'Error Requests per Day',
ROUND(SUM(CASE WHEN STS.STATUS_GROUP IN ('Successful', 'Redirection') THEN FCT.REQUEST_CNT / 14.0 ELSE 0 END), 1) AS 'Success Requests per Day',
USG.USER_AGENT_NK AS 'Agent'
FROM FCT_ACCESS_USER_AGENT_DD FCT,
     DIM_USER_AGENT USG,
     DIM_HTTP_STATUS STS
WHERE FCT.DIM_USER_AGENT_ID = USG.DIM_USER_AGENT_ID
  AND FCT.DIM_HTTP_STATUS_ID = STS.DIM_HTTP_STATUS_ID
  AND USG.AGENT_BOT != 'n.a.'
  AND datetime(FCT.EVENT_DT, 'unixepoch') >= date('now', '-14 day')
GROUP BY USG.USER_AGENT_NK
ORDER BY 3 DESC
LIMIT 10

Në këtë rast, rezultati i analizës ishte vendimi për të kufizuar aksesin në sit duke e shtuar atë në skedarin robots.txt

User-agent: AhrefsBot
Disallow: /
User-agent: dotbot
Disallow: /
User-agent: bingbot
Crawl-delay: 5

Dy robotët e parë u zhdukën nga tabela dhe robotët MS u zhvendosën nga rreshtat e parë.

Dita dhe ora e aktivitetit më të madh

Ngritjet janë të dukshme në trafik. Për t'i studiuar ato në detaje, është e nevojshme të theksohet koha e shfaqjes së tyre dhe nuk është e nevojshme të shfaqen të gjitha orët dhe ditët e matjes së kohës. Kjo do ta bëjë më të lehtë gjetjen e kërkesave individuale në skedarin e regjistrit nëse nevojitet analiza e detajuar.

Statistikat e faqes dhe ruajtja juaj e vogël

Kërkesa e raportit SQL

SELECT
1 AS 'Line: Day and Hour of Hits from Users and Bots',
strftime('%d.%m-%H', datetime(EVENT_DT, 'unixepoch')) AS 'Date Time',
HIB AS 'Bots, Hits',
HIU AS 'Users, Hits'
FROM (
	SELECT
	EVENT_DT,
	SUM(CASE WHEN AGENT_BOT!='n.a.' THEN LINE_CNT ELSE 0 END) AS HIB,
	SUM(CASE WHEN AGENT_BOT='n.a.' THEN LINE_CNT ELSE 0 END) AS HIU
	FROM FCT_ACCESS_REQUEST_REF_HH
	WHERE datetime(EVENT_DT, 'unixepoch') >= date('now', '-14 day')
	GROUP BY EVENT_DT
	ORDER BY SUM(LINE_CNT) DESC
	LIMIT 10
) ORDER BY EVENT_DT

Ne vëzhgojmë orët më aktive 11, 14 dhe 20 të ditës së parë në tabelë. Por të nesërmen në orën 13:XNUMX robotët ishin aktivë.

Aktiviteti mesatar ditor i përdoruesit sipas javës

Ne i rregulluam pak gjërat me aktivitetin dhe trafikun. Pyetja tjetër ishte aktiviteti i vetë përdoruesve. Për statistika të tilla, periudha të gjata grumbullimi, si një javë, janë të dëshirueshme.

Statistikat e faqes dhe ruajtja juaj e vogël

Kërkesa e raportit SQL

SELECT
1 as 'Line: Average Daily User Activity by Week',
strftime('%W week', datetime(FCT.EVENT_DT, 'unixepoch')) AS 'Week',
ROUND(1.0*SUM(FCT.PAGE_CNT)/SUM(FCT.IP_CNT),1) AS 'Pages per IP per Day',
ROUND(1.0*SUM(FCT.FILE_CNT)/SUM(FCT.IP_CNT),1) AS 'Files per IP per Day'
FROM
  FCT_ACCESS_USER_AGENT_DD FCT,
  DIM_USER_AGENT USG,
  DIM_HTTP_STATUS HST
WHERE FCT.DIM_USER_AGENT_ID=USG.DIM_USER_AGENT_ID
  AND FCT.DIM_HTTP_STATUS_ID = HST.DIM_HTTP_STATUS_ID
  AND USG.AGENT_BOT='n.a.' /* users only */
  AND HST.STATUS_GROUP IN ('Successful') /* good pages */
  AND datetime(FCT.EVENT_DT, 'unixepoch') > date('now', '-3 month')
GROUP BY strftime('%W week', datetime(FCT.EVENT_DT, 'unixepoch'))
ORDER BY FCT.EVENT_DT

Statistikat javore tregojnë se mesatarisht një përdorues hap 1,6 faqe në ditë. Numri i skedarëve të kërkuar për përdorues në këtë rast varet nga shtimi i skedarëve të rinj në sajt.

Të gjitha kërkesat dhe statuset e tyre

Webalizer tregonte gjithmonë kode specifike të faqeve dhe gjithmonë doja të shihja vetëm numrin e kërkesave dhe gabimeve të suksesshme.

Statistikat e faqes dhe ruajtja juaj e vogël

Kërkesa e raportit SQL

SELECT
1 as 'Line: All Requests by Status',
strftime('%d.%m', datetime(FCT.EVENT_DT, 'unixepoch')) AS 'Day',
SUM(CASE WHEN STS.STATUS_GROUP='Successful' THEN FCT.REQUEST_CNT ELSE 0 END) AS 'Success',
SUM(CASE WHEN STS.STATUS_GROUP='Redirection' THEN FCT.REQUEST_CNT ELSE 0 END) AS 'Redirect',
SUM(CASE WHEN STS.STATUS_GROUP='Client Error' THEN FCT.REQUEST_CNT ELSE 0 END) AS 'Customer Error',
SUM(CASE WHEN STS.STATUS_GROUP='Server Error' THEN FCT.REQUEST_CNT ELSE 0 END) AS 'Server Error'
FROM
  FCT_ACCESS_USER_AGENT_DD FCT,
  DIM_HTTP_STATUS STS
WHERE FCT.DIM_HTTP_STATUS_ID=STS.DIM_HTTP_STATUS_ID
  AND datetime(FCT.EVENT_DT, 'unixepoch') >= date('now', '-14 day')
GROUP BY strftime('%d.%m', datetime(FCT.EVENT_DT, 'unixepoch'))
ORDER BY FCT.EVENT_DT

Raporti shfaq kërkesat, jo klikimet (goditjet), ndryshe nga LINE_CNT, metrika REQUEST_CNT llogaritet si COUNT(DISTINCT STG.REQUEST_NK). Qëllimi është të tregohen ngjarje efektive, për shembull, MS bots anketojnë skedarin robots.txt qindra herë në ditë dhe, në këtë rast, sondazhe të tilla do të numërohen një herë. Kjo ju lejon të zbutni kërcimet në grafik.

Nga grafiku mund të shihni shumë gabime - këto janë faqe që nuk ekzistojnë. Rezultati i analizës ishte shtimi i ridrejtimeve nga faqet e largëta.

Kërkesa të këqija

Për të shqyrtuar kërkesat në detaje, mund të shfaqni statistika të detajuara.

Statistikat e faqes dhe ruajtja juaj e vogël

Kërkesa e raportit SQL

SELECT
  1 AS 'Table: Top Error Requests',
  REQ.REQUEST_NK AS 'Request',
  'Error' AS 'Request Status',
  ROUND(SUM(FCT.LINE_CNT) / 14.0, 1) AS 'Hits per Day',
  ROUND(SUM(FCT.IP_CNT) / 14.0, 1) AS 'IPs per Day',
  ROUND(SUM(FCT.BYTES)/1000 / 14.0, 1) AS 'KB per Day'
FROM
  FCT_ACCESS_REQUEST_REF_HH FCT,
  DIM_REQUEST_V_ACT REQ
WHERE FCT.DIM_REQUEST_ID = REQ.DIM_REQUEST_ID
  AND FCT.STATUS_GROUP IN ('Client Error', 'Server Error')
  AND datetime(FCT.EVENT_DT, 'unixepoch') >= date('now', '-14 day')
GROUP BY REQ.REQUEST_NK
ORDER BY 4 DESC
LIMIT 20

Kjo listë do të përmbajë gjithashtu të gjitha thirrjet, për shembull, një kërkesë në /wp-login.php Duke rregulluar rregullat për rishkrimin e kërkesave nga serveri, mund të rregulloni reagimin e serverit ndaj kërkesave të tilla dhe t'i dërgoni ato në faqen fillestare.

Pra, disa raporte të thjeshta të bazuara në skedarin e regjistrit të serverit japin një pamje mjaft të plotë të asaj që po ndodh në sit.

Si të merrni informacion?

Një bazë të dhënash sqlite është e mjaftueshme. Le të krijojmë tabela: ndihmëse për regjistrimin e proceseve ETL.

Statistikat e faqes dhe ruajtja juaj e vogël

Faza e tabelës ku do të shkruajmë skedarë log duke përdorur PHP. Dy tabela të përmbledhura. Le të krijojmë një tabelë ditore me statistika mbi agjentët e përdoruesve dhe statuset e kërkesave. Për orë me statistika për kërkesat, grupet e statusit dhe agjentët. Katër tabela të matjeve përkatëse.

Rezultati është modeli i mëposhtëm relacional:

Modeli i të dhënaveStatistikat e faqes dhe ruajtja juaj e vogël

Skript për të krijuar një objekt në një bazë të dhënash sqlite:

Krijimi i objektit DDL

DROP TABLE IF EXISTS DIM_USER_AGENT;
CREATE TABLE DIM_USER_AGENT (
  DIM_USER_AGENT_ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
  USER_AGENT_NK     TEXT NOT NULL DEFAULT 'n.a.',
  AGENT_OS          TEXT NOT NULL DEFAULT 'n.a.',
  AGENT_ENGINE      TEXT NOT NULL DEFAULT 'n.a.',
  AGENT_DEVICE      TEXT NOT NULL DEFAULT 'n.a.',
  AGENT_BOT         TEXT NOT NULL DEFAULT 'n.a.',
  UPDATE_DT         INTEGER NOT NULL DEFAULT 0,
  UNIQUE (USER_AGENT_NK)
);
INSERT INTO DIM_USER_AGENT (DIM_USER_AGENT_ID) VALUES (-1);

Fazë

Në rastin e skedarit access.log, është e nevojshme të lexoni, analizoni dhe shkruani të gjitha kërkesat në bazën e të dhënave. Kjo mund të bëhet ose drejtpërdrejt duke përdorur një gjuhë skriptimi ose duke përdorur mjete sqlite.

Formati i skedarit të regjistrit:

//67.221.59.195 - - [28/Dec/2012:01:47:47 +0100] "GET /files/default.css HTTP/1.1" 200 1512 "https://project.edu/" "Mozilla/4.0"
//host ident auth time method request_nk protocol status bytes ref browser
$log_pattern = '/^([^ ]+) ([^ ]+) ([^ ]+) ([[^]]+]) "(.*) (.*) (.*)" ([0-9-]+) ([0-9-]+) "(.*)" "(.*)"$/';

Përhapja kryesore

Kur të dhënat e papërpunuara janë në bazën e të dhënave, ju duhet të shkruani çelësat që nuk janë aty në tabelat e matjes. Atëherë do të jetë e mundur të ndërtohet një referencë për matjet. Për shembull, në tabelën DIM_REFERRER, çelësi është një kombinim i tre fushave.

Kërkesa e përhapjes së çelësit SQL

/* Propagate the referrer from access log */
INSERT INTO DIM_REFERRER (HOST_NK, PATH_NK, QUERY_NK, UPDATE_DT)
SELECT
	CLS.HOST_NK,
	CLS.PATH_NK,
	CLS.QUERY_NK,
	STRFTIME('%s','now') AS UPDATE_DT
FROM (
	SELECT DISTINCT
	REFERRER_HOST AS HOST_NK,
	REFERRER_PATH AS PATH_NK,
	CASE WHEN INSTR(REFERRER_QUERY,'&sid')>0 THEN SUBSTR(REFERRER_QUERY, 1, INSTR(REFERRER_QUERY,'&sid')-1) /* отрезаем sid - специфика цмс */
	ELSE REFERRER_QUERY END AS QUERY_NK
	FROM STG_ACCESS_LOG
) CLS
LEFT OUTER JOIN DIM_REFERRER TRG
ON (CLS.HOST_NK = TRG.HOST_NK AND CLS.PATH_NK = TRG.PATH_NK AND CLS.QUERY_NK = TRG.QUERY_NK)
WHERE TRG.DIM_REFERRER_ID IS NULL

Përhapja në tabelën e agjentit të përdoruesit mund të përmbajë logjikë bot, për shembull fragmentin sql:


CASE
WHEN INSTR(LOWER(CLS.BROWSER),'yandex.com')>0
	THEN 'yandex'
WHEN INSTR(LOWER(CLS.BROWSER),'googlebot')>0
	THEN 'google'
WHEN INSTR(LOWER(CLS.BROWSER),'bingbot')>0
	THEN 'microsoft'
WHEN INSTR(LOWER(CLS.BROWSER),'ahrefsbot')>0
	THEN 'ahrefs'
WHEN INSTR(LOWER(CLS.BROWSER),'mj12bot')>0
	THEN 'majestic-12'
WHEN INSTR(LOWER(CLS.BROWSER),'compatible')>0 OR INSTR(LOWER(CLS.BROWSER),'http')>0
	OR INSTR(LOWER(CLS.BROWSER),'libwww')>0 OR INSTR(LOWER(CLS.BROWSER),'spider')>0
	OR INSTR(LOWER(CLS.BROWSER),'java')>0 OR INSTR(LOWER(CLS.BROWSER),'python')>0
	OR INSTR(LOWER(CLS.BROWSER),'robot')>0 OR INSTR(LOWER(CLS.BROWSER),'curl')>0
	OR INSTR(LOWER(CLS.BROWSER),'wget')>0
	THEN 'other'
ELSE 'n.a.' END AS AGENT_BOT

Tabelat e përmbledhura

Së fundi, ne do të ngarkojmë tabelat e përgjithshme; për shembull, tabela ditore mund të ngarkohet si më poshtë:

Kërkesa SQL për ngarkimin e agregatit

/* Load fact from access log */
INSERT INTO FCT_ACCESS_USER_AGENT_DD (EVENT_DT, DIM_USER_AGENT_ID, DIM_HTTP_STATUS_ID, PAGE_CNT, FILE_CNT, REQUEST_CNT, LINE_CNT, IP_CNT, BYTES)
WITH STG AS (
SELECT
	STRFTIME( '%s', SUBSTR(TIME_NK,9,4) || '-' ||
	CASE SUBSTR(TIME_NK,5,3)
	WHEN 'Jan' THEN '01' WHEN 'Feb' THEN '02' WHEN 'Mar' THEN '03' WHEN 'Apr' THEN '04' WHEN 'May' THEN '05' WHEN 'Jun' THEN '06'
	WHEN 'Jul' THEN '07' WHEN 'Aug' THEN '08' WHEN 'Sep' THEN '09' WHEN 'Oct' THEN '10' WHEN 'Nov' THEN '11'
	ELSE '12' END || '-' || SUBSTR(TIME_NK,2,2) || ' 00:00:00' ) AS EVENT_DT,
	BROWSER AS USER_AGENT_NK,
	REQUEST_NK,
	IP_NR,
	STATUS,
	LINE_NK,
	BYTES
FROM STG_ACCESS_LOG
)
SELECT
	CAST(STG.EVENT_DT AS INTEGER) AS EVENT_DT,
	USG.DIM_USER_AGENT_ID,
	HST.DIM_HTTP_STATUS_ID,
	COUNT(DISTINCT (CASE WHEN INSTR(STG.REQUEST_NK,'.')=0 THEN STG.REQUEST_NK END) ) AS PAGE_CNT,
	COUNT(DISTINCT (CASE WHEN INSTR(STG.REQUEST_NK,'.')>0 THEN STG.REQUEST_NK END) ) AS FILE_CNT,
	COUNT(DISTINCT STG.REQUEST_NK) AS REQUEST_CNT,
	COUNT(DISTINCT STG.LINE_NK) AS LINE_CNT,
	COUNT(DISTINCT STG.IP_NR) AS IP_CNT,
	SUM(BYTES) AS BYTES
FROM STG,
	DIM_HTTP_STATUS HST,
	DIM_USER_AGENT USG
WHERE STG.STATUS = HST.STATUS_NK
  AND STG.USER_AGENT_NK = USG.USER_AGENT_NK
  AND CAST(STG.EVENT_DT AS INTEGER) > $param_epoch_from /* load epoch date */
  AND CAST(STG.EVENT_DT AS INTEGER) < strftime('%s', date('now', 'start of day'))
GROUP BY STG.EVENT_DT, HST.DIM_HTTP_STATUS_ID, USG.DIM_USER_AGENT_ID

Baza e të dhënave sqlite ju lejon të shkruani pyetje komplekse. ME përmban përgatitjen e të dhënave dhe çelësave. Pyetja kryesore mbledh të gjitha referencat për dimensionet.

Kushti nuk do të lejojë ngarkimin përsëri të historisë: CAST(STG.EVENT_DT AS INTEGER) > $param_epoch_from, ku parametri është rezultat i kërkesës
'SELECT COALESCE(MAX(EVENT_DT), '3600') SI TË FUNDIT_EVENT_EPOCH NGA FCT_ACCESS_USER_AGENT_DD'

Kushti do të ngarkojë vetëm ditën e plotë: CAST(STG.EVENT_DT SI INTEGER) < strftime('%s', data ('tani', 'fillimi i ditës'))

Numërimi i faqeve ose skedarëve kryhet në mënyrë primitive, duke kërkuar për një pikë.

Raportet

Në sistemet komplekse të vizualizimit, është e mundur të krijohet një meta-model i bazuar në objektet e bazës së të dhënave, të menaxhohen në mënyrë dinamike filtrat dhe rregullat e grumbullimit. Në fund të fundit, të gjitha mjetet e mira gjenerojnë një pyetje SQL.

Në këtë shembull, ne do të krijojmë pyetje të gatshme SQL dhe do t'i ruajmë ato si pamje në bazën e të dhënave - këto janë raporte.

Vizualizimi

Bluff: Grafikët e bukur në JavaScript u përdorën si një mjet vizualizimi

Për ta bërë këtë, ishte e nevojshme të kaloni të gjitha raportet duke përdorur PHP dhe të krijoni një skedar html me tabela.

$sqls = array(
'SELECT * FROM RPT_ACCESS_USER_VS_BOT',
'SELECT * FROM RPT_ACCESS_ANNOYING_BOT',
'SELECT * FROM RPT_ACCESS_TOP_HOUR_HIT',
'SELECT * FROM RPT_ACCESS_USER_ACTIVE',
'SELECT * FROM RPT_ACCESS_REQUEST_STATUS',
'SELECT * FROM RPT_ACCESS_TOP_REQUEST_PAGE',
'SELECT * FROM RPT_ACCESS_TOP_REQUEST_REFERRER',
'SELECT * FROM RPT_ACCESS_NEW_REQUEST',
'SELECT * FROM RPT_ACCESS_TOP_REQUEST_SUCCESS',
'SELECT * FROM RPT_ACCESS_TOP_REQUEST_ERROR'
);

Mjeti thjesht vizualizon tabelat e rezultateve.

Prodhim

Duke përdorur analizën e uebit si shembull, artikulli përshkruan mekanizmat e nevojshëm për të ndërtuar depo të dhënash. Siç shihet nga rezultatet, mjetet më të thjeshta janë të mjaftueshme për analiza të thella dhe vizualizim të të dhënave.

Në të ardhmen, duke përdorur këtë depo si shembull, ne do të përpiqemi të zbatojmë struktura të tilla si dimensionet që ndryshojnë ngadalë, meta të dhënat, nivelet e grumbullimit dhe integrimi i të dhënave nga burime të ndryshme.

Gjithashtu, le të hedhim një vështrim më të afërt në mjetin më të thjeshtë për menaxhimin e proceseve ETL bazuar në një tabelë të vetme.

Le t'i kthehemi temës së matjes së cilësisë së të dhënave dhe automatizimit të këtij procesi.

Ne do të studiojmë problemet e mjedisit teknik dhe mirëmbajtjen e ruajtjes së të dhënave, për të cilat do të implementojmë një server ruajtjeje me burime minimale, për shembull, bazuar në një Raspberry Pi.

Burimi: www.habr.com

Shto një koment