Grunden för att bygga en WordPress Server Dashboard

Vad du ska skapa

Folk klagar ofta på att WordPress är långsam. Huruvida detta är sant beror på många faktorer, men om vi kan se servernes resurser inne i WordPress instrumentpanel kan det ge en viss insikt om hur bra vår WordPress-installation är i drift. 

I denna handledning skapar vi ett plugin för att visa serverstatus inklusive diskutrymme, minneskonsumtion, CPU-användning och processanvändning. 

Vi kommer också att lära oss om WordPress-cache för att undvika att fråga dessa mätningar om och om igen, och vi kommer också att täcka WordPress cron-jobb för att generera denna data automatiskt.

Administratörens instrumentpanel presenterar som standard oss ​​ett par block som kallas widgets. Dessa inkluderar: 

  • Kortfattat
  • Aktivitet
  • Snabbt utkast
  • WordPress News
  • Välkommen

Widgetarna kan beställas omedelbart och kan visas eller döljas - i allmänhet kan instrumentpanelen anpassas.

Eftersom widgets är mycket flexibla och tillgängliga direkt på skärmbildens första skärm kan vi använda dem för att visa serverresurs: diskstatus, RAM-användning, CPU-användning och operativsysteminformation. Vi kommer att kalla dessa resurser "mätvärden" för korta.

Under hela seriet kommer vi att lära API och Roller och funktioner för Dashboard Widgets för att göra dessa widgets tillgängliga för vissa användare eftersom data kan vara känsliga. 

För att göra det kommer vi också att lära oss några grundläggande Linux-kommandon för att dra serverinformation och frö till vår widgetens instrumentbräda. Vi kommer att använda Transients API för att cache dessa data. Cronjobs levereras för att automatiskt dra dessa data istället för att få dem på begäran vid varje förfrågan.

Arbetet i vårt plugin inspireras av Linux Dash.

Vårt plugin stöder nio typer av mätvärden. Som ett resultat kommer vi att ha nio instrumentbrädor.

  1. Serverinformation: operativsystemet, Linux-kärnan, uppetiden, etc..
  2. CPU-belastning: Genomsnittlig belastning på CPU i 1, 5 och 15 minuter
  3. RAM-användning av fysiskt RAM och swap-fil
  4. Diskanvändning
  5. Installerad programvara
  6. processer
  7. Ethernet
  8. Nätverksprestanda
  9. IO stat

Krav

  1. En Linux-miljö. Mac OS X är fortfarande ett alternativ men några av kommandona för att kontrollera ovanstående mätvärden är inte tillgängliga, så om du får ett kommando som inte hittats, vet du att det inte finns något Mac-stöd för det här kommandot.
  2. Grundläggande förståelse av skalet
  3. Basic WordPress plugin förståelse.

Plugin Skeleton Structure

Låt oss skapa ett enkelt plugin och ringa det Server Dashboard. Vi börjar med några grundläggande saker. En traditionell Hej världen hjälper dig att smaka på att lägga till en widget på instrumentbrädan. 

Det är enkelt, faktiskt. 

Skapa ett mappsamtal Server Dashboard inuti wp-content / plugins, och en fil serverdashboard.php. Mapplayouten ser ut så här. Bara fokusera på huvudfilen och ignorera bin, test, widgets och så vidare.

Använd den här koden för serverdashboard.php

springa(); ?>

Jag använde namespace AX \ StatBoard för att undvika namnkollision med olika plugins-klass, funktionsnamn för teman och andra plugins. 
Jag använde också Singleton Pattern för att få en unik instans av plugin-klass. Jag skapade en metod springa att registrera krok eller filter med WordPress.
För att lägga till en widget måste vi koppla till handling wp_dashboard_setup. Dessa krokar ger oss tillgång till Dashboards relaterade anpassningsalternativ. Det gör att vi kan lägga till eller ta bort instrumentbräd widget från WordPress. 
Inuti krokfunktionen använder vi wp_add_dashboard_widget att registrera en widget. Det kräver argument i denna ordning:
  1. Widget ID används för att identifiera slug för din widget. Denna slug används när CSS-ID, klass och som nycklar i widget-array visas.
  2. Widget Title visas på titeln på widgetboxen
  3. Ring tillbaka att göra innehållet i widgeten. Det ska utmatas innehåll direkt, behöver inte återvända.
För det mesta kommer vi att möta återuppringningar som en enda funktion, en anonym funktion, en grupp av objekt och metod, eller array av klass och statisk metod.
Uppdatera din instrumentpanel. Vårt plugin visar sin widget. Lägg märke till id av widget div element.

Vår plugin är widgeten visas med sitt ID och innehåll

Låt oss göra detta framåt. Vi visar ett cirkeldiagram med några dummy data. För att hålla saker enkelt, använder jag Google Chart API. Vi använder det i stor utsträckning senare för serverns statistik eftersom det är bättre att visualisera denna typ av data. 

Om du inte gillar Google-diagram kan du bli av med den och lägga till ditt favoritschema bibliotek. Kom ihåg att det här är en handledning, så begränsa inte dig själv - använd vad som helst du är bekväm med att använda!

Vi måste ladda Google Chart-skriptet. Ändra din springa() Metod för att registrera ytterligare en krok.

 public function run () add_action ('wp_dashboard_setup', array ($ this, 'add_dashboard_widgets')); add_action ('admin_enqueue_scripts', array ($ this, 'add_asset')); 

admin_enqueue_scripts är den åtgärd som du behöver koppla in för att lägga till ditt eget skript i administratörens instrumentbräda. Vi lägger till ytterligare ett metodsamtal add_asset i vår klass för att hantera skriptläsning. Redskapet av add_asset.

 / ** * Lägg till javascript * / function add_asset () wp_enqueue_script ('google-chart', 'https://www.google.com/jsapi');  
Vi har kartbiblioteket. Nu måste vi göra det inne i instrumentbrädan. Du kan leka med Google Chart. Vi kommer bara att använda deras exempel nu.
funktion add_dashboard_widgets () syslog (LOG_DEBUG, "Run"); wp_add_dashboard_widget ('hello_world_dashboard_widget', // En Slug för att identifiera den här widgeten 'Hello World', // Widget title function () echo <<<'EOD' Hey, I'm the body of widget. Thanks for bring me to the life. 
EOD; // funktion för att göra innehållet i widgeten, jag använder en nedläggning här);

Vi lägger helt enkelt till ytterligare ett div-element med id hello_piechart och gör diagrammet till det här elementet. Låt oss se vad vi har nu:Lägg märke till widgetelementets ID.

Nu när vi vet hur man lägger till vårt eget widgetblock i instrumentbrädan, och nu när vi vet hur man får Google-diagram för att göra information kan vi kombinera de två för att visa mer information. 

I nästa avsnitt kommer vi att lära oss hur vi tar tag i serverns statistik och gör innehåll för varje typ av servermätning som vi tidigare diskuterat.

Dra ut serverns statistik

När vi använder serverns mätvärden använder vi kommandot av Linux för att få denna information. I PHP kan vi använda backtick "eller shell_exec för att åberopa ett kommandot shell och hämta utmatningen. 

Vi kan analysera utdata för att få serverdata. Till exempel, för att få diskanvändningsstatus kan vi använda kommandot df -h. Vi vet formatet för produktionen, så vi kan analysera det för att få det vi vill ha.

 $ df = 'df -h'; $ df = explodera ("\ n", $ df); om (is_array ($ df) && count ($ df)> = 2) array_shift ($ df); // Avsluta den första raden $ df = array_map (funktion ($ linje) om (tom ($ linje)) return NULL; $ segment = preg_split ('/ \ s + /', $ linje); 'filesystem' => $ segment [0], 'size' => $ segment [1], 'used' => $ segment [2], 'tillgängligt' => $ segment [3], 'use_percent' => $ segment [4],);, $ df); var_dump ($ df); 

Rengöring med AWK

För att hjälpa till att rensa utmatningen direkt från shell-kommandot kan vi kombinera med awk. Den länken är läskig med mycket information, men vi kommer bara att använda en mycket liten mängd i den här handledningen. Att förklara awk är utom räckhåll för denna handledning.
Om du vill lära dig mer om awk, använd det här cheatsheetet. I grund och botten använder vi awk för att bearbeta varje produktionslinje, och på varje rad delas strängen av flik eller utrymme, och elementet kan komma åt som variabel med $ 1 för första elementet, $ 2 för andra element och så vidare. Syntaxen är: [command_we_run] | awk 'skriv ut $ 1, $ 3, ...'
Låt oss titta på följande exempel:
☁ Server Dashboard [master] ls -lh totalt 32 -rw-r-r-- 1 kureikain personal 2.6K Apr 11 00:46 Server Dashboard.php drwxr-xr-x 3 kureikain personal 102B Mar 29 01:27 bin - rw-r - r-- 1 kureikain personal 98B apr 5 18:53 loader.js -rw-r - r-- 1 kureikain personal 321B mar 29 01:27 phpunit.xml drwxr-xr-x 4 kureikain personal 136B Mar 29 01:27 test drwxr-xr-x 12 kureikain personal 408B apr 13 17:37 widget -rw-r - r-- 1 kureikain personal 1.1K apr 6 01:04 widget.php ☁ Server Dashboard [master] ls -lh | awk 'print $ 3, $ 4, $ 5, $ 9' kureikain personal 2.6K Server kureikain personal 102B bin kureikain personal 98B loader.js kureikain personal 321B phpunit.xml kureikain personal 136B tester kureikain personal 408B widget kureikain personal 1.1K widget.php

Som du kan se varje rad av ls-la innehåller nio fält:
drwxr-xr-x 4 kureikain personal 136B mar 29 01:27 test
Separering av mellanslag är dessa 9 fält:
  1. drwxr-xr-x  
  2. 4
  3. kureikain 
  4. personal  
  5. 136B
  6. mar
  7. 29
  8. 01:27
  9. tester
Jag kan använda awk för att bara ta namn, grupp, storlek och fil / mappnamn i motsvarande fält 3, 4, 5, 9 awk 'skriv ut $ 3, $ 4, $ 5, $ 9' och jag kommer att se:
kureikain personal 136B test

Därför använder vi awk vi kan städa upp produktionen lite mer innan vi matar in i vår PHP-bearbetningsfunktion.

Rengöring med GREP

Vissa kommandon matar ut extra data som vi inte behöver, Därför krävs det lite extra insats med PHP för att städa upp det.

Till exempel:

[vagrant @ vagrant-centos64 ~] $ free -m totalt används gratis delade buffertar cachade Mem: 589 537 51 0 8 271 - / + buffert / cache: 258 330 Byte: 255 0 255
gratis -m visar oss RAM-användningen med minnet och byta fil; men det innehåller två andra rader med totalt / använd / gratis och - / + buffert / cache som vi kanske inte behöver. 
Vi vill bara dra information om Mem och Swap - det vill säga linje 3 och linje 5. Ett av sätten att uppnå detta är att använda grep med -E växla. Den omkopplaren tillåter användningen att använda vanlig express för sökning. Eftersom vi vill hitta raden med ord Mem och byt, låt oss kombinera med grep -E "Mem | Swap"
Här är resultatet.
[vagrant @ vagrant-centos64 ~] $ free -m | grep -E "Mem | Swap" Mem: 589 536 52 0 8 271 Byte: 255 0 255
Så det är mycket renare. Kombinera båda grep och awk Vi kan städa upp data och få bara det vi behöver.
[vagrant @ vagrant-centos64 ~] $ free -m | grep -E "Mem | Swap" | awk 'skriv ut $ 1, $ 2, $ 3, $ 4' Mem: 589 537 52 Byta: 255 0 255

Linux-kommandon för att få serverinformation

Vi måste lära oss några kommandon för att dra serverns mätvärden, så låt oss öppna vårt serverskal och försök att skriva under kommandot för att få en snabb smak.

Kontrollera nätverkstrafik

$ netstat-i Kernel Interface-tabell Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg eth0 1500 0 5538339494 0 0 0 6216082004 0 0 0 BMRU eth0: 1 1500 0 - ingen statistik tillgänglig - BMRU eth1 1500 0 96707328840 0 0 0 102776317608 0 0 0 BMRU eth2 1500 0 33 0 0 0 7 0 0 0 BMRU lo 16436 0 29461422 0 0 0 29461422 0 0 0 LRU 

Kontrollera diskanvändning

df -h Filsystem Storlek Används Tillåten Användning% Monterad på / dev / sda7 2.0G 660M 1.3G 35% / / dev / sda8 1.0T 632G 340G 66% / hem / dev / sda6 2.0G 68M 1.9G 4% / tmp / dev / sda5 20G 1.5G 18G 8% / var / dev / sda2 20G 2.1G 17G 12% / usr / dev / sda1 194M 25M 160M 14% / boot / dev / hdb1 459G 277G 159G 64% / backup tmpfs 16G 0 16G 0% / dev / shm

Kontrollera RAM-användning

gratis -m totalt använda gratis delade buffertar cachade Mem: 32189 32129 59 0 419 9052 - / + buffert / cache: 22656 9532 Byt: 32767 4 3276
Vi kommer att använda mer kommando senare, men ovanför ger dig några grundläggande kommandon för att se vad vi kan få från servern direkt på kommandoraden.

Bygga Widget

Vi kommer att refactor vår ursprungliga klass i föregående avsnitt lite. Observera att, om inte annat anges, skapar vi alla filer och mappar inom vår plugin katalog.

För det första vill vi inte manuellt inkludera filer. Vi kommer att skriva en automatisk klasslastare för det ändamålet. När en saknas klass initialiseras kontrollerar vi klassnamnet och försöker inkludera källfilen som innehåller klassdefinitionen. 

Vi använder namnområden som sökväg och klassnamn som filnamn. Till exempel en klass foo i namespace AX \ StatBoard borde vara i roten till plugin mappen. En klass surr i namespace AX \ StatBoard \ Bar borde vara i Bar \ buzz.php

Mapplayoutstruktur med namnrymd, klassnamn och filnamn för automatisk laddning.

Med det i åtanke, låt oss gå vidare och börja utforma vår autoladdningsmetod:

_plugin_dir. strtolower (str_replace ('\\', '/', $ classname). '.php'); om (! file_exists ($ filepath)) return false;  inkludera $ filepath;  

/ **
* Inställningsvariabel och initiera widgetleverantör
* /
funktionen __construct ()
$ this -> _ plugin_dir = plugin_dir_path (__FILE__);
spl_autoload_register (array ($ this, 'load_class'));


// ...
Så vad händer här? Vår plugin använder namnrymden AX \ StatBoard. Så vi ser till att den begärda klassen under denna namnrymd ska hanteras av vårt plugin, annars kan vår autoladare inte kunna ladda dem. Vi stripar sedan AX \ StatBoard i klassnamn och ersätt det med sökvägen till plugin-mappen. Bakslaget \ i namespace ersätts med / vägseparatorn och lägg till php förlängning. Det betyder att namnrymden kommer att användas eftersom sökvägen till mappen innehåller klassfil och klassnamnet är filnamnet. Inkluderande sker endast om filen finns. Nu har vi automatisk laddare, vi behöver fortfarande låta PHP veta att vi har en automatisk laddare och vi vill använda den. PHP innehåller spl_autoload_register för detta ändamål. Vi lägger den i vår klasskonstruktor.
För det andra, låt oss utforma vår widgets klass. Vi har flera typer av servervärden att visa. Det är bättre att visa varje mätvärde i ett separat widgetblock så att dessa widgets kan sorteras eller ordnas, eller anpassas för att dölja eller visa. Om du lägger all information i samma widget kommer kostnaden för kontroll att visa / gömma varje mätvärde i vårt plugin. 
Förutsatt att du vet om funktionen wp_add_dashboard_widget, Vi måste ge den titeln och innehållet. Motsvarar varje widget, kommer vi att ha en klass för att göra titel och innehåll för det. Vi kallar dessa klasser är widget provider. Alla widgetleverantörer måste definiera get_title () och get_content () att göra innehåll.
För det ändamålet kommer vi att skapa en provider gränssnitt, och ha vår widgetleverantörsklass implementera detta gränssnitt. Vi behöver också skapa ett nytt metodsamtal get_metric () att dra serverns data.
Skapa fil widget / provider.php med detta innehåll:
Detta är ett gränssnitt. Vi krävde att alla widgetleverantörer måste implementera detta gränssnitt, och därför ser vi till att tat-widgetleverantörsklassen alltid har dessa tre metoder.
Vi kommer att skapa en mer klass widget att hantera dessa leverantörer. Vi skapar leverantörskurser och delar ut dem till widget klass och visa widget klass som en enda punkt för att vi ska fråga om en leverantör när vi behöver. Vi kan helt enkelt lägga allt i vår huvudsakliga pluginfil och bara skapa klassexempel med ny operatör när vi behöver men det är svårt att behålla senare. 
När vi bryter ner i många lager, är det lättare att testa och förlänga. När vi gör alla leverantörer förvaltas av en enda klass kan vi använda den enda klassen för att göra samma sak över uppsättningen leverantörer. Vi kan enkelt lägga till fler leverantörer när som helst, genom att bara skapa ett objekt som implementerar leverantörsklassen och matar dem till widget klass
Komponera en fil widget.php i rotkatalogen i plugin-mappen.

namnrymd AX \ StatBoard;
använd AX \ StatBoard \ Widget \ Provider;

klass Widget
const WIDGET_SLUG_PREFIX = 'AX';

skyddad $ _providers = array ();
skyddad statisk $ _instance;

statisk funktion instans ()
returnera själv: $ _ instance = self :: $ _ instance?: nytt själv ();


funktionen __construct ()


/ **
* Lägg till en widgetleverantör
* @param string widget namn
* @param-leverantörsobjekt för att hantera widgetens innehållsgenerering
* /
offentlig funktion add_provider ($ name, Provider $ handler)
$ this -> _ leverantörer [$ name] = $ handler;
returnera $ this;


/ **
* Få alla leverantörer eller en viss leverantör
* /
offentlig funktion get_provider ($ name = NULL)
om (! $ namn)
returnera $ this -> _ leverantörer;

returnera $ this -> _ leverantörer [$ namn];


/ **
* Registrera en widget för att göra det.
* /
offentligt funktionsregister ($ namn)
$ slugid = själv :: WIDGET_SLUG_PREFIX. $ Name;
$ widget_provider = $ this-> get_provider ($ name);
om (tomt ($ widget_provider))
returnera false;


wp_add_dashboard_widget (
$ slugid,
$ Widget_provider-> get_title (),
array ($ widget_provider, 'get_content'));
återvänd sant;



Återigen använder vi Singleton Pattern för vår Widget-klass. En snabb sammanfattning av vår metod här.
  1. De add_provider Metoden kommer att lägga till ett widgetleverantörsobjekt till widgetleverantörslistan. Vi använder också typhypotes för att se till att objektet övergår till add_provider måste vara a provider genom att implementera vår provider gränssnitt.
  2. De get_provider Metoden kan returnera en lista över alla leverantörer, eller en viss leverantör.
  3. De Registrera Metoden kommer faktiskt att registrera vårt leverantörsobjekt med WordPress för att göra en instrumentbräda med wp_add_dashboard_widget. ID för widget skapas baserat på prefixet, en fördefinierad konstant och klassnamnet för widgeten. Titeln kommer och innehållet kommer att dra via get_title och get_content av leverantören. Vi försäkrade att de implementerar vårt Provider-gränssnitt. Med denna registreringsmetod abstraherar vi implementeringen av att lägga till widgeten i instrumentbrädan. Allt vi behöver göra nu är att ringa Registrera med namnet på leverantören som vi lägger till tidigare med add_provider. Med detta i åtanke, när WordPress API ändras, behöver vi inte gå till varje ställe wp_add_dashboard_widget, Vi uppdaterar bara på ett ställe.

Kommer tillbaka vår ursprungliga huvud pluginfil serverdashboard.php, Vi kommer att initiera alla leverantörer och lägga till dem i leverantörslistan med Widget-objekt.
 _plugin_dir = plugin_dir_path (__FILE__); spl_autoload_register (array ($ this, 'load_class')); $ this -> _ dashboard_widget = array ("server", "cpu_load", "ram", "disk", "diskio", "software", "ethernet", "internetspeed", "networkio", "process"); $ ($ this -> _ plugin_dir. '/ widget /'. $ item. '.php')) forts;  $ classname = 'AX \\ StatBoard \\ Widget \\'. ucwords ($ item); Widget :: instance () -> add_provider ($ item, new $ classname ()); 

Vi lägger alla widgetleverantörsklasser under namnrymden AX \ StatBoard \ Widget och därför kommer de att sitta inuti mappen widget. Vi stöder nio typer av metriska och vi heter klassen som motsvarar matrisen _dashboard_widgets ovan. 
För varje widget skapar vi en ny instans av dess leverantör och lägger till i widget klass. Här är vad vi kommer att få senare med denna struktur:
Kom ihåg att vi hakade in wp_dashboard_setup, och inom det kallar vi funktionen wp_add_dashboard_widget att lägga till ny widget i instrumentpanelen. Därefter har vi vår Registrera metod för detta ändamål. Vi slår över alla tilläggsleverantörer och registrerar dem. Uppdatera innehållet i add_dashboard_widgets av serverdashboard.php bli:
 
/ ** * Registrera dashboard widget proider att dyka upp på instrumentbrädan * / function add_dashboard_widgets () $ widget = Widget :: instans (); foreach ($ widget-> get_provider () som $ name => $ provider) $ widget-> register ($ name);


Därefter kommer vi att koppla in admin_footer för att skriva inline JavaScript på undersidan av admin sidan för att initiera Google Chart Class-paketet. Vår springa() Metoden är också uppdaterad för ny krok.
 / ** * Börja med att installera krok * / public function run () add_action ('wp_dashboard_setup', array ($ this, 'add_dashboard_widgets')); add_action ('admin_enqueue_scripts', array ($ this, 'add_asset')); add_action ('admin_footer', array ($ this, 'footer'));  / ** * Inline JavaScript för diagram * / funktion footer () echo '  '; 

För tillfället slutförde vi basen, och huvudinplugningsfilen ska se ut så här.
_plugin_dir. strtolower (str_replace ('\\', '/', $ classname). '.php'); om (! file_exists ($ filepath)) return false;  inkludera $ filepath;  / ** * Inställningsvariabel och initiera widgetleverantör * / funktion __construct () $ this -> _ plugin_dir = plugin_dir_path (__FILE__); spl_autoload_register (array ($ this, 'load_class')); $ this -> _ dashboard_widget = array ("server", "cpuload", "ram", "disk", "programvara", "process", "ethernet", "networkio", "iostat"); $ ($ this -> _ plugin_dir. '/ widget /'. $ item. '.php')) forts;  $ classname = 'AX \\ StatBoard \\ Widget \\'. ucwords ($ item); Widget :: instance () -> add_provider ($ item, new $ classname ());  / ** * Skapa en unik instans genom att använda appen * / offentlig statisk funktion instans () returnera själv :: $ _ instance = själv :: $ _ instans?: Nytt själv ();  / ** * Börja med att konfigurera krok * / public function run () add_action ('wp_dashboard_setup', array ($ this, 'add_dashboard_widgets')); add_action ('admin_enqueue_scripts', array ($ this, 'add_asset')); add_action ('admin_footer', array ($ this, 'footer'));  / ** * Registrera dashboard widget proider att dyka upp på instrumentbrädan * / function add_dashboard_widgets () $ widget = Widget :: instans (); foreach ($ widget-> get_provider () som $ name => $ provider) $ widget-> register ($ name);  / ** * Tillgångsbelastning: stylesheet, JS. * / funktion add_asset () syslog (LOG_DEBUG, "Loaded"); wp_enqueue_script ('google-diagram', 'https://www.google.com/jsapi'); // wp_enqueue_script ('plugin_dir_url', plugin_dir_url (__ FILE__). '/loader.js');  / ** * Inline JavaScript för diagram * / funktion footer () echo '  ';  Dashboard :: instans () -> kör (); 
Vi skapar i grunden en instans av huvud plugin-klassen och kallar körmetoden. Som i sin tur bara ställa upp en lista med krok. Varje krok är en annan metod inom klassen. Vi skapar och registrerar även vårt leverantörsobjekt med widget objekt.

Vad kommer härnäst?

Vid den här tiden visar vi fortfarande ingenting; Vi lade dock ut en struktur för vår plugin-annons började ansluta till Google Charts.
Du kan ladda ner det fullständiga skriptet från hämtningslänkarna högst upp i den här artikeln. Vi kommer att gå in i detaljerna för varje widgetleverantör i nästa artikel, så se till att du följer nästa del. 
Jag hoppas att du haft den här artikeln. Lämna kommentarer med något av dina tankar och jag kommer säkert att svara på dem.