Los fundamentos de la construcción de un panel de WordPress Server

Lo que vas a crear

La gente a menudo se queja de que WordPress es lento. Si esto es cierto o no, depende de muchos factores, pero si podemos ver los recursos del servidor dentro del panel de WordPress, entonces podemos dar una idea de qué tan bien está funcionando nuestra instalación de WordPress.. 

En este tutorial, crearemos un complemento para mostrar el estado del servidor, incluido el espacio en disco, los consumos de memoria, el uso de la CPU y el uso del proceso.. 

También aprenderemos sobre el caché de WordPress para evitar consultar estas métricas una y otra vez y también cubriremos los trabajos cron de WordPress para generar estos datos automáticamente.

El panel del administrador, de forma predeterminada, nos presenta un par de bloques llamados widgets. Éstos incluyen: 

  • De un vistazo
  • Actividad
  • Borrador rápido
  • Noticias de WordPress
  • Bienvenido

Los widgets se pueden reordenar por preferencia y se pueden mostrar u ocultar. En general, el panel de control es personalizable..

Como los widgets son muy flexibles y están disponibles en la primera pantalla de la pantalla del administrador, podemos usarlos para mostrar los recursos del servidor: estado del disco, uso de RAM, uso de la CPU e información del sistema operativo. Llamaremos a estos recursos "métricas" para abreviar.

A lo largo de todo esto, aprenderemos la API de Widgets de Dashboard y los roles y capacidades para que estos widgets estén disponibles para algunos usuarios, ya que los datos podrían ser confidenciales.. 

Para hacerlo, también aprenderemos algunos comandos básicos de Linux para extraer información del servidor y colocarlos en nuestro panel de control de widgets. Utilizaremos Transients API para almacenar en caché estos datos. Cronjobs se aprovechará para extraer automáticamente estos datos en lugar de obtenerlos a pedido en cada solicitud.

El trabajo de nuestro plugin está inspirado en Linux Dash..

Nuestro plugin soporta nueve tipos de métricas. Como resultado, tendremos nueve widgets de tablero.

  1. Información del servidor: el sistema operativo, el kernel de Linux, el tiempo de actividad, etc..
  2. Carga de CPU: carga media de CPU en 1, 5 y 15 minutos
  3. Uso de RAM de RAM física y archivo de intercambio
  4. Uso del disco
  5. Software instalado
  6. Procesos
  7. Ethernet
  8. Rendimiento de la red
  9. IO stat

Requerimientos

  1. Un entorno Linux. Mac OS X sigue siendo una opción pero algunos de los comandos para verificar las métricas anteriores no están disponibles, por lo que si recibe un error de comando no encontrado, entonces sabe que no hay soporte para Mac para ese comando.
  2. Comprensión básica de la concha.
  3. Comprensión del plugin básico de WordPress.

La Estructura del Esqueleto del Plugin

Vamos a crear un plugin simple y lo llamamos Tablero del servidor. Comenzaremos con algunas cosas básicas. Un tradicional Hola Mundo te ayudará a tener la oportunidad de agregar un widget al panel. 

Es facil, en realidad. 

Creando una llamada de carpeta Tablero del servidor dentro wp-content / plugins, y un archivo serverdashboard.php. El diseño de la carpeta se ve así. Solo enfóquese en el archivo principal e ignore la ubicación, las pruebas, los widgets, etc..

Usa este código para serverdashboard.php

correr(); ?>

Utilicé espacio de nombres AX \ StatBoard para evitar la colisión de nombres con diferentes complementos de clase, nombre de la función de los temas y otros complementos. 
También utilicé el patrón Singleton para obtener una instancia única de clase de complemento. Creé un método correr para registrar gancho o filtro con WordPress.
Para agregar un widget, tenemos que enganchar a la acción. wp_dashboard_setup. Estos enlaces nos permiten acceder a la opción de personalización relacionada con Dashboard. Nos permite agregar o eliminar el widget del panel de WordPress. 
Dentro de la función de gancho, utilizamos wp_add_dashboard_widget para registrar un widget. Requiere argumentos en este orden:
  1. ID de widget Se utiliza para identificar slug para tu widget. Este slug se usa al representar la identificación de CSS, la clase y como claves en la matriz de widgets.
  2. Título del widget muestra en el título de la caja del widget
  3. Llamar de vuelta para hacer el contenido del widget. Debería salir el contenido directamente, no necesita volver.
La mayoría de las veces, nos encontraremos con devoluciones de llamada como una sola función, una función anónima, una matriz de objetos y métodos, o una matriz de clases y métodos estáticos..
Actualiza tu panel de control. Nuestro plugin muestra su widget. Observe la carné de identidad del elemento div widget.

Nuestro plugin es widget que se muestra con su ID y contenido.

Vamos a avanzar en esto. Mostraremos un gráfico circular con algunos datos ficticios. Para mantenerlo simple, usaré la API de Google Chart. Lo usaremos extensivamente más adelante para las métricas del servidor porque es mejor visualizar este tipo de datos. 

Si no te gusta Google Chart, puedes deshacerte de él y poner tu biblioteca de gráficos favorita. Recuerde que este es un tutorial, así que no se limite, use lo que le resulte más cómodo.!

Necesitamos cargar el script de Google Chart. Cambia tu correr() Método para registrar un gancho más.

 función pública ejecutar () add_action ('wp_dashboard_setup', array ($ this, 'add_dashboard_widgets')); add_action ('admin_enqueue_scripts', array ($ this, 'add_asset')); 

admin_enqueue_scripts es la acción que necesita conectar para agregar su propio script en el panel de administración. Agregaremos un método más llamado add_asset en nuestra clase para manejar la carga de scripts. El implemento de add_asset.

 / ** * Agregar javascript * / function add_asset () wp_enqueue_script ('google-chart', 'https://www.google.com/jsapi');  
Tenemos la biblioteca de cartas. Ahora tenemos que renderizarlo dentro de nuestro panel de control. Puedes jugar con Google Chart. Solo reutilizaremos su ejemplo ahora.
función add_dashboard_widgets () syslog (LOG_DEBUG, "Run"); wp_add_dashboard_widget ('hello_world_dashboard_widget', // Un Slug para identificar este widget 'Hello World', // función de título del widget () echo <<<'EOD' Hey, I'm the body of widget. Thanks for bring me to the life. 
EOD; // función para mostrar el contenido del widget, estoy usando un cierre aquí);

Simplemente agregamos un elemento div más con id hello_piechart y renderizar el gráfico en ese elemento. A ver que tenemos ahora:Observe el ID del elemento widget.

Ahora que sabemos cómo agregar nuestro propio bloque de widgets al panel de control, y ahora que sabemos cómo obtener Google Chart para generar información, podemos combinar los dos para mostrar más información.. 

En la siguiente sección, aprenderemos cómo capturar las métricas del servidor y renderizar el contenido para cada tipo de métrica del servidor que hemos analizado anteriormente..

Tirando de las métricas del servidor

Al extraer las métricas del servidor, usaremos el comando de Linux para obtener esta información. En PHP, podemos usar backtick "o shell_exec para invocar un comando de shell, y recuperar la salida. 

Podemos analizar la salida para obtener datos del servidor. Por ejemplo, para obtener el estado de uso del disco podemos usar el comando. df -h. Conocemos el formato de salida, por lo que podemos analizarlo para obtener lo que queremos.

 $ df = 'df -h'; $ df = explode ("\ n", $ df); if (is_array ($ df) && count ($ df)> = 2) array_shift ($ df); // Deshágase de la primera línea $ df = array_map (function ($ line) if (empty ($ line)) return NULL; $ segment = preg_split ('/ \ s + /', $ line); return array ( 'sistema de archivos' => $ segmento [0], 'tamaño' => $ segmento [1], 'usado' => $ segmento [2], 'disponible' => $ segmento [3], 'use_percent' => $ segmento [4],);, $ df); var_dump ($ df); 

Limpiando con AWK

Para ayudar a limpiar la salida directamente desde el comando de shell, podemos combinar con awk. Ese enlace parece aterrador con mucha información, pero solo usaremos una cantidad muy pequeña en este tutorial. Explicar awk está fuera del alcance de este tutorial.
Si quieres aprender más sobre awk, usa esta hoja de trucos. Básicamente, usamos awk para procesar cada línea de salida, y en cada línea, la cadena se dividirá por tabulación o espacio, y se puede acceder al elemento como variable con $ 1 para el primer elemento, $ 2 para el segundo elemento y así sucesivamente. La sintaxis es: [command_we_run] | awk 'imprimir $ 1, $ 3,…'
Veamos el siguiente ejemplo:
Dash Server Dashboard [master] ls -lh total 32 -rw-r - r-- 1 kureikain staff 2.6K 11 de abril 00:46 Server Dashboard.php drwxr-x-x 3 kureikain staff 102B Mar 29 01:27 bin - rw-r - r-- 1 personal de kureikain 98B 5 de abril 18:53 loader.js -rw-r - r-- 1 personal de kureikain 321B 29 de marzo de 01:27 phpunit.xml drwxr-xr-x 4 personal de kureikain 136B Mar 29 01:27 pruebas drwxr-xr-x 12 personal de kureikain 408B 13 de abril 17:37 widget -rw-r - r-- 1 personal de kureikain 1.1K 6 de abril 01:04 widget.php ☁ Server Dashboard [master] ls -lh | awk 'imprimir $ 3, $ 4, $ 5, $ 9' kureikain staff 2.6K Servidor kureikain staff 102B bin kureikain staff 98B loader.js kureikain staff 321B phpunit.xml kureikain staff 136B tests kureikain staff 408B widget kureikain staff 1.1K widget.php

Como puedes ver cada linea de ls -la contiene nueve campos:
drwxr-xr-x 4 personal de kureikain 136B Mar 29 01:27 pruebas
Separando por espacios, estos 9 campos son:
  1. drwxr-xr-x  
  2. 4
  3. Kureikain 
  4. personal  
  5. 136B
  6. mar
  7. 29
  8. 01:27
  9. pruebas
Puedo usar awk para simplemente tomar el nombre, grupo, tamaño y nombre de archivo / carpeta en el campo correspondiente 3, 4, 5, 9 awk 'imprimir $ 3, $ 4, $ 5, $ 9' y veré
kureikain staff 136B tests

Por lo tanto, al utilizar awk podemos limpiar un poco más la salida antes de utilizar nuestra función de procesamiento de PHP.

Limpiando con GREP

Algunos comandos generan datos adicionales que no necesitamos; por lo tanto, requiere un poco de esfuerzo adicional con PHP para limpiarlo.

Por ejemplo:

[vagrant @ vagrant-centos64 ~] $ free -m total de buffers compartidos gratuitos utilizados en caché Mem: 589 537 51 0 8 271 - / + buffers / cache: 258 330 Swap: 255 0 255
libre -m Nos muestra el uso de la memoria RAM con la memoria y el archivo de intercambio; sin embargo, incluye otras dos líneas con total / used / free y - / + buffers / cache que no necesitamos. 
Solo queremos obtener información de Mem y Swap, es decir, la línea 3 y la línea 5. Una de las formas de lograrlo es usar grep con -mi cambiar. Ese interruptor permite usar el expreso regular para la búsqueda. Porque queremos encontrar la línea con las palabras Mem y Swap, vamos a combinar con grep -E "Mem | Swap"
Aquí está el resultado..
[vagrant @ vagrant-centos64 ~] $ free -m | grep -E "Mem | Swap" Mem: 589 536 52 0 8 271 Swap: 255 0 255
Así que es mucho más limpio. Combina ambos grep y awk Podemos limpiar los datos y obtener solo lo que necesitamos.
[vagrant @ vagrant-centos64 ~] $ free -m | grep -E "Mem | Swap" | awk 'imprimir $ 1, $ 2, $ 3, $ 4' Mem: 589 537 52 Swap: 255 0 255

Comandos de Linux para obtener información del servidor

Tenemos que aprender algunos comandos para obtener las métricas del servidor, por lo que abriremos nuestro shell de servidor e intentaremos escribir debajo del comando para tener una idea rápida.

Revisar el tráfico de la red

$ netstat-en Kernel Tabla de interfaz 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 - no hay estadísticas disponibles - 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 

Comprobar el uso del disco

df -h Tamaño del sistema de archivos usado Avail Use% Montado en / dev / sda7 2.0G 660M 1.3G 35% / / dev / sda8 1.0T 632G 340G 66% / home / 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

Comprobar el uso de la memoria RAM

libre -m total utilizado libre compartido buffers en caché Mem: 32189 32129 59 0 419 9052 - / + buffers / cache: 22656 9532 Swap: 32767 4 3276
Usaremos más comandos más adelante, pero los anteriores le dan un comando fundamental para ver qué podemos obtener del servidor directamente en la línea de comandos.

Construyendo el Widget

Vamos a refactorizar nuestra clase original en la sección anterior un poco. Tenga en cuenta que, a menos que se indique claramente lo contrario, estaremos creando todos los archivos y carpetas. dentro nuestro directorio de plugins.

Primero, no querremos incluir archivos manualmente. Escribiremos un cargador automático de clases para ese propósito. Cuando se inicializa una clase faltante, verificaremos el nombre de la clase e intentaremos incluir el archivo fuente que contiene la definición de la clase. 

Usaremos los espacios de nombres como la ruta y el nombre de la clase como el nombre del archivo. Por ejemplo, una clase. foo en espacio de nombres AX \ StatBoard Debería estar en la raíz de la carpeta del complemento. Una clase zumbido en espacio de nombres AX \ StatBoard \ Bar debería estar en Bar \ buzz.php

Estructura de diseño de carpeta con espacio de nombres, nombre de clase y nombre de archivo para carga automática.

Con eso en mente, sigamos adelante y comencemos a diseñar nuestro método de cargador automático:

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

/ **
* Variable de configuración y proveedor de widget de inicialización.
* /
función __construir ()
$ this -> _ plugin_dir = plugin_dir_path (__FILE__);
spl_autoload_register (array ($ this, 'load_class'));


//…
Entonces, ¿qué pasa aquí? Nuestro plugin utiliza el espacio de nombres. AX \ StatBoard. Por lo tanto, nos aseguramos de que la clase solicitada bajo este espacio de nombres sea manejada por nuestro complemento, de lo contrario, nuestro cargador automático no es capaz de cargarlos. Luego despojamos el AX \ StatBoard en el nombre de la clase y reemplazarlo con la ruta de la carpeta del complemento. La barra invertida \ en espacio de nombres se sustituye por / separador de ruta, y anexar php extensión. Eso significa que el espacio de nombres se utilizará como la ruta a la carpeta que contiene el archivo de clase, y el nombre de la clase es el nombre del archivo. La inclusión solo ocurre si el archivo existe. Ahora, tenemos el cargador automático, aún debemos informarle a PHP que tenemos un cargador automático y queremos usarlo. PHP incluye spl_autoload_register para este propósito. Lo ponemos en nuestra clase constructor..
En segundo lugar, diseñemos nuestra clase de widgets. Tenemos múltiples tipos de métrica de servidor para mostrar. Es mejor mostrar cada una de las métricas en un bloque de widgets separado para que esos widgets se puedan ordenar o organizar, o personalizar para ocultar o mostrar. Poner toda la información en el mismo widget pondrá el costo del control mostrando / ocultando cada métrica de nuestro complemento. 
Suponiendo que usted sabe acerca de la función wp_add_dashboard_widget, Tenemos que darle el título y el contenido. En función de cada widget, tendremos una clase para representar el título y el contenido. A estas clases las llamamos widgets. Proveedor. Todo proveedor de widgets debe definir get_title () y obtener el contenido() para representar contenido.
Para ello, crearemos un Proveedor interfaz, y que nuestra clase de proveedor de widgets implemente esta interfaz. También necesitamos crear un método más llamado get_metric () para extraer datos del servidor.
Crea un archivo widget / provider.php con este contenido:
Esta es una interfaz. Requerimos que cada proveedor de widgets tenga que implementar esta interfaz y, por lo tanto, nos aseguramos de que la clase de proveedor de widgets siempre tenga estos tres métodos.
Crearemos una clase más. Widget para gestionar estos proveedores. Creamos clases de proveedores, luego las entregamos a Widget clase y vista Widget clase como un punto único para que solicitemos un proveedor cuando lo necesitemos. Simplemente podemos poner todo en nuestro archivo de complemento principal, y simplemente crear una instancia de clase con nuevo Operador cuando lo necesitamos pero es difícil de mantener más tarde.. 
Cuando dividimos la cosa en muchas capas, es más fácil de probar y extender. Una vez que hacemos que todos los proveedores sean administrados por una sola clase, podemos usar esa clase para hacer lo mismo en el conjunto de proveedores. Podemos agregar fácilmente más proveedores en cualquier momento, simplemente creando un objeto que implemente una clase de proveedor y aliméntelos a Widget clase
Componer un archivo widget.php en el directorio raíz de la carpeta de plugin.

espacio de nombres AX \ StatBoard;
use AX \ StatBoard \ Widget \ Provider;

Widget de clase
const WIDGET_SLUG_PREFIX = 'AX';

protegido $ _providers = array ();
$ _instancia estática protegida;

instancia de función estática ()
return self :: $ _ instance = self :: $ _ instance?: new self ();


función __construir ()


/ **
* Añadir un proveedor de widget
* @param string nombre del widget
* @param proveedor objeto para manejar la representación del contenido del widget
* /
función pública add_provider ($ name, Provider $ handler)
$ esto -> _ proveedores [$ nombre] = $ manejador;
devuelve $ esto;


/ **
* Obtener todos los proveedores o un proveedor en particular
* /
función pública get_provider ($ name = NULL)
si (! $ nombre)
devuelve $ esto -> _ proveedores;

devuelve $ esto -> _ proveedores [$ nombre];


/ **
* Registrar un widget para renderizarlo..
* /
registro de función pública ($ nombre)
$ slugid = self :: WIDGET_SLUG_PREFIX. $ nombre;
$ widget_provider = $ this-> get_provider ($ name);
if (vacío ($ widget_provider))
falso retorno;


wp_add_dashboard_widget (
$ slugid,
$ widget_provider-> get_title (),
array ($ widget_provider, 'get_content'));
devuelve verdadero



Nuevamente, estamos usando el patrón Singleton para nuestra clase de widgets. Un breve resumen de nuestro método aquí..
  1. los añadir_proveedor El método agregará un objeto de proveedor de widgets a la lista de proveedores de widgets. También utilizamos sugerencias de tipo para asegurarnos de que el paso de objeto a add_provider debe ser un Proveedor implementando nuestro Proveedor interfaz.
  2. los obtener_proveedor El método puede devolver una lista de todos los proveedores, o un proveedor en particular.
  3. los registro El método en realidad registrará nuestro objeto proveedor con WordPress para generar un widget de panel con wp_add_dashboard_widget. El ID del widget se genera según el prefijo, una constante predefinida y el nombre de la clase del widget. El título y el contenido serán tirados vía obtener_título y get_content del proveedor. Nos aseguramos de que implementen nuestra interfaz de proveedor. Con este método de registro, abstraemos la implementación de agregar el widget al panel de control. Todo lo que tenemos que hacer ahora es llamar registro con el nombre del proveedor que agregamos antes con añadir_proveedor. Con esto en mente, cuando la API de WordPress cambia, no necesitamos ir a todos los lugares de wp_add_dashboard_widget, acabamos de actualizar en un solo lugar.

Volviendo a nuestro archivo de plugin principal original serverdashboard.php, Inicializaremos todos los proveedores y los agregaremos a la lista de proveedores del objeto Widget..
 _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')); foreach ($ this -> _ dashboard_widget as $ item) if (! file_exists ($ this -> _ plugin_dir. '/ widget /'. $ item. '.php')) continue;  $ classname = 'AX \\ StatBoard \\ Widget \\'. ucwords ($ item); Widget :: instance () -> add_provider ($ item, new $ classname ()); 

Pondremos todas las clases de proveedores de widgets bajo el espacio de nombres AX \ StatBoard \ Widget y por lo tanto se sentarán dentro de la carpeta widget. Apoyamos nueve tipos de métricas y nombramos la clase correspondiente a la matriz _dashboard_widgets encima. 
Para cada uno de los widgets, creamos una nueva instancia de su proveedor y la agregamos a Widget clase. Esto es lo que obtendremos más adelante con esta estructura:
Recuerda que nos enganchamos en wp_dashboard_setup, Y dentro de ella llamamos a la función. wp_add_dashboard_widget para agregar nuevo widget al panel de control. A continuación, tenemos nuestro registro Método para este fin. Iremos a todos los proveedores agregados y los registraremos. Actualizar el contenido de add_dashboard_widgets de serverdashboard.php volverse:
 
/ ** * Registrar el proider del widget del panel de control para que aparezca en el panel de control * / function add_dashboard_widgets () $ widget = Widget :: instance (); foreach ($ widget-> get_provider () como $ name => $ provider) $ widget-> register ($ name);


A continuación, nos conectaremos a admin_footer para generar JavaScript en línea en la parte inferior de la página de administración para inicializar el paquete de clase de Google Chart. Nuestro correr() Método también se actualiza para nuevo gancho.
 / ** * Comenzar a configurar el gancho * / 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'));  / ** * JavaScript en línea para el gráfico * / función pie de página () echo '  '; 

En este momento, completamos el archivo básico, y el archivo del complemento principal debería tener este aspecto.
_plugin_dir. strtolower (str_replace ('\\', '/', $ classname). '.php'); if (! file_exists ($ filepath)) return false;  incluye $ filepath;  / ** * Variable de configuración e intializar proveedor de widgets * / function __construct () $ this -> _ plugin_dir = plugin_dir_path (__FILE__); spl_autoload_register (array ($ this, 'load_class')); $ this -> _ dashboard_widget = array ('server', 'cpuload', 'ram', 'disk', 'software', 'process', 'ethernet', 'networkio', 'iostat',); foreach ($ this -> _ dashboard_widget as $ item) if (! file_exists ($ this -> _ plugin_dir. '/ widget /'. $ item. '.php')) continue;  $ classname = 'AX \\ StatBoard \\ Widget \\'. ucwords ($ item); Widget :: instance () -> add_provider ($ item, new $ classname ());  / ** * Crear una instancia única a través de la aplicación * / public static function instance () return self :: $ _ instance = self :: $ _ instance?: New self ();  / ** * Comenzar a configurar hook * / 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'));  / ** * Registrar el proider del widget del panel de control para que aparezca en el panel de control * / function add_dashboard_widgets () $ widget = Widget :: instance (); foreach ($ widget-> get_provider () como $ name => $ provider) $ widget-> register ($ name);  / ** * Carga de activos: hoja de estilo, JS. * / function add_asset () syslog (LOG_DEBUG, "Loaded"); wp_enqueue_script ('google-chart', 'https://www.google.com/jsapi'); // wp_enqueue_script ('plugin_dir_url', plugin_dir_url (__ FILE__). '/loader.js');  / ** * JavaScript en línea para el gráfico * / función pie de página () echo '  ';  Dashboard :: instance () -> run (); 
Básicamente creamos una instancia de la clase del complemento principal y llamamos al método de ejecución. Que a su vez acaba de configurar una lista de gancho. Cada gancho es otro método dentro de la clase. También creamos y registramos nuestro objeto proveedor con Widget objeto.

Que sigue?

En este punto, todavía no mostramos nada; sin embargo, establecimos una estructura para nuestro anuncio de complemento que comenzó a conectarse a Google Charts.
Puede descargar el script completo de los enlaces de descarga en la parte superior de este artículo. Iremos al detalle de implementación de cada proveedor de widgets en el próximo artículo, así que asegúrate de seguir la siguiente parte. 
Espero que hayan disfrutado este artículo. Deja comentarios con cualquiera de tus pensamientos y me aseguraré de responderlos..