viernes, 20 de octubre de 2017

Herramienta imprescindible: Azure Storage Explorer

Cuando trabajamos con cuentas de almacenamiento de Azure, lo más lógico o normal es que en un momento dado necesitemos acceder a dichas cuentas para ver su contenido.

Desde el propio Portal de Azure no tenemos forma de ver la información almacenada en las cuentas de almacenamiento (o yo no lo he encontrado todavía) pero eso no quiere decir que no podamos hacerlo… Me consta que existen varias herramientas que permiten acceder a la información, pero ésta que os comento me ha parecido muy interesante:

El Azure Storage Explorer (en versión preliminar todavía) es una aplicación independiente que permite trabajar fácilmente con datos de Azure Storage en Windows, macOS y Linux

Esta herramienta proporciona varias maneras de conectar con las cuentas de almacenamiento. Por ejemplo, podemos:

  • Conectar con las cuentas de almacenamiento asociadas a las suscripciones de Azure.
  • Conectar con las cuentas de almacenamiento y los servicios que se comparten desde otras suscripciones de Azure.
  • Conectar con el almacenamiento local, y administrarlo, mediante el Emulador de Azure Storage.

Además, permite trabajar con cuentas de almacenamiento en nubes de Azure globales y nacionales:

En la siguiente captura podemos ver cómo tenemos acceso a las suscripciones de Azure que tengamos asignadas:

image

Y como muestra, el contenido de una cuenta de almacenamiento de tipo “Table”

image

Como podemos ver en la captura anterior, además de acceder a los datos podemos también generar consultas, ver estadísticas de la tabla e incluso manipular los datos.

Detalle de las consultas:

image

En definitiva, una herramienta imprescindible para gestionar el “Storage” en Azure. Como comento, me consta que hay más herramientas que ofrecen esta funcionalidad, pero ésta me ha parecido clara, sencilla y útil.

Enlace a la aplicación [aquí] y… con el código en GitHub [acceso]

lunes, 9 de octubre de 2017

ASP.NET CORE–Validadores

Una de las características que tenemos disponible en aplicaciones ASP.NET desde hace más tiempo del que puedo recordar es el uso de validadores (Validators) para automatizar, en mayor o menor medida, las validaciones que siempre tenemos que realizar cuando enviamos información de un formulario al servidor.

Con la llegada de JQuery y sus extensiones JQuery.Validation y JQuery.Validation.Unobtrusive, la funcionalidad que proporcionan estos validadores mejoró en sus capacidades, ya que de manera automática (hasta donde yo sé) son capaces de realizar las validaciones en cliente antes de hacer el envío o post al servidor, haciendo que el rendimiento de la aplicación web no se resienta.

Reconozco que a mí no me habían gustado nunca, ya que les veía poca funcionalidad, poca flexibilidad y… bueno, que no me convencían. He decidido darles otra oportunidad en el ámbito de ASP.NET Core, porque lo cierto es que al final es muy probable que nos ahorren tiempo.

Primero quiero empezar con una captura de los validadores estándar que podemos encontrar en una aplicación ASP.Net Core:

image

Bastante feo, ¿no?

¿Cómo funcionan?

En el post sobre localización [acceso] ya estuvimos hablando sobre los DataAnnotations así que aquí no trabajaremos con localización, de momento una pequeña explicación de cómo funciona el sistema de validadores en ASP.NET Core.

Modelo:

En el modelo especificamos qué condiciones tiene que cumplir la propiedad para ser válida:

image

En el ejemplo anterior estamos indicando que la propiedad Email es obligatoria y que tiene que ser una dirección de correo ‘bien formada’. Estos atributos (normalmente en el namespace System.ComponentModel.DataAnnotations) se encargan automáticamente de realizar validaciones sobre los valores introducidos en la vista. Cuando el envío llega al controlador, la propiedad IsValid del ModelState indicará si los valores son correctos o no:

image

Aquí podemos ver que si el modelo no es valido, directamente vuelve a cargar la página, en la que veremos los validadores aplicados como se ven en la primera captura.

He dicho antes que los validadores se ejecutan en el cliente, pero en esta pequeña explicación sólo he hablado de la parte de servidor, lo he hecho así para poder hablar de la propiedad IsValid ya que nos puede servir también para operaciones avanzadas con el modelo una vez que estamos en la parte del servidor.

Cliente:

Para poder ejecutar esos validadores en el cliente tenemos que utilizar las librerías de Javascript JQuery.Validation y JQuery.Validation.Unobtrusive, que por suerte tenemos ya disponibles cuando creamos un proyecto de ASP.NET Core en Visual Studio:

image

Además, si entramos a la vista donde utilizamos los validadores, veremos al final de la misma como los scripts necesarios se incluyen mediante una vista parcial:

image

Esto es interesante ya que si queremos incluir nuestros propios scripts de validación, si añadimos la referencia en esta vista parcial, los tendremos disponibles automáticamente en el resto de vistas donde se utilicen los validadores estándar.

Para poder utilizar los validadores tenemos que añadirlos en la vista (tiene sentido ¿no?)

image

Como podemos ver, tenemos varios atributos asp-xxx que gestionan la validación:

  • asp-validation-summary define una sección con todos los errores encontrados.
  • asp-validation-for especifica una sección donde se mostrarán los errores encontrados para la propiedad del modelo indicada (en este ejemplo Email)

¿Cómo podemos saber que la validación funciona sólo en cliente?

Esta es fácil, basta con poner un punto de ruptura en la acción del controlador y ejecutar el proyecto, si ponemos valores incorrrectos en el formulario y hacemos el Post, veremos que NO llega ninguna petición al controlador, porque no llegaremos al punto de ruptura. De hecho, si alguna vez llegáis al servidor sin que se hayan evaluado las validaciones de cliente, tenéis un problema.

¿Esto es todo?

hasta ahora, todo lo que hemos visto es el comportamiento estándar de los validadores, pero siguen quedando como ‘feuchos’. Gracias a Bootstrap podemos hacer alguna adaptación que quede un poco más elegante, algo como esto (con iconos en las cajas):

image

Peeero, si queremos algo más avanzado, como mostrar los errores en una ventana modal (algo bastante habitual por otra parte) es cuando empiezan nuestros problemas.

Al turrón

Lo primero que hacemos es crear una vista parcial en la que ponemos el código del ‘esqueleto’ de la ventana modal que queremos mostrar:

image

A continuación incluimos esta vista parcial en la vista deseada (podríamos añadirla también en el _Layout para tenerla disponible en todas las vistas de la aplicación si nos interesa)

image

Lo siguiente que tenemos que hacer es preparar un script para que ‘capture’ el submit del formulario a validar y si hay errores muestre una ventana modal. El script en cuestión podría ser algo como esto (se trata de un ejemplo, no seáis muy duros):

image

En esta función lo que hacemos es codificar el submit del formulario, lanzamos las validaciones que tenga configuradas, y si hay algún error en esas validaciones, mostramos la ventana modal evitando que se continúe con el envío del formulario. En este ejemplo nos quedamos sólo con el último error detectado, pero creo que como ejemplo es suficiente.

Por supuesto este script tendremos que añadirlo en la página, si no, pues no se iba a ejecutar…

Si a continuación probamos el funcionamiento, tendremos esto:

image

Como podéis ver en la captura se siguen mostrando los errores de los validadores por defecto, si queremos evitarlo basta con quitar los validadores de la vista, ya que en las pruebas realizadas parece que no es necesario que estén físicamente en la página para que se realice la validación.

Conclusión

Me da la sensación de que interceptar las validaciones que se realizan por defecto puede acabar dándonos algún problemilla, pero lo cierto es que si queremos hacer algo diferente a los mensajes por defecto esta sería la aproximación que yo recomendaría.

martes, 3 de octubre de 2017

ASP.NET CORE–Localización de aplicaciones

Una de las mayores ventajas que nos proporciona la plataforma ASP.NET Core es la facilidad con la que podemos acceder a ‘las tripas’ de las llamadas que se realizan, así como el soporte por defecto de inyección de dependencias.
Combinando estas y otras características, tenemos una sustancial mejora a la hora de gestionar comportamientos como el del multiidioma, localización y globalización de aplicaciones.

Introducción

La localización en ASP.NET Core es bastante similar a como funciona en ASP.NET 4.X. Por defecto definimos una serie de archivos de recursos .resx, uno para cada cultura que soportamos. Entonces podemos referenciar los recursos por clave y, dependiendo de la cultura actual, se obtiene el valor apropiado del archivo de recursos que corresponda.
Mientras el concepto de un archivo .resx por cultura se mantiene en ASP.NET Core, la manera en la que los recursos se utilizan ha cambiado significativamente. En la versión anterior, cuando añadíamos un archivo .resx a nuestra solución, se generaba automáticamente un archivo “designer” que proporcionaba acceso a los recursos de una manera directa (static strongly typed access) mediante llamadas del tipo “Resources.MyTitleString”.
En ASP.NET Core, los recursos se acceden a través de dos abstracciones, IStringLocalizer y IStringLocalizer<T>, que se ‘preparan’ cuando son necesarias mediante la “inyección de dependencias”. Estos interfaces proporcionan un indexador que permite acceder a los recursos por clave. Si no existe un recurso para la clave especificada, el sistema utiliza la propia clave como valor del recurso.
La idea detrás de esta nueva aproximación es permitir que la aplicación se diseñe desde el principio para ser “localizable” sin que sea necesario crear todos los archivos de recursos al inicio. Así podemos simplemente utilizar los valores por defecto como claves y añadir los distintos archivos de recursos a posteriori.
Indudablemente se trata de una opción muy interesante, pero lógicamente tiene un problema relativamente serio, ya que al no tener acceso ‘tipado’ a los recursos se puede dar el caso de que sin querer cambiemos uno de esos literales / claves y entonces perdemos el vínculo con su recurso. Entiendo que es muy probable que al final cojamos costumbre de trabajar de esta manera, aunque me da la sensación de que también es muy posible que tengamos ‘dificultades’ para detectar en un momento dado qué tenemos traducido y qué no… Lo mejor entiendo que será aprovechar las ventajas de la nueva gestión de la localización, pero trabajando desde el principio con los archivos de recursos necesarios en la aplicación.

Al turrón

Todo esto es muy bonito (o lo parece) pero, ¿cómo se hace?

Añadir localización a una aplicación

El primer paso es añadir los servicios de localización a nuestra aplicación. En este caso, como estamos trabajando con una aplicación MVC, configuraremos también localización para las Vistas e incluso para los “DataAnnotations”. En ASP.NET Core añadimos estos servicios en el método “ConfigureServices” de la clase “Startup
image
En la captura anterior podemos observar cómo añadimos los servicios de localización para los tres elementos que hemos comentado; como punto interesante indicar que al especificar un “ResourcesPath” le estamos diciendo al motor dónde se ubicarán los archivos de recursos (en este caso en una carpeta “Resources”.
Al añadir estos servicios tenemos la posibilidad de inyectar las abstracciones que hemos comentado en la parte de la introducción, así como una especialización de ellas que permite trabajar con vistas “IViewLocalizer”.
Con estas instrucciones ya podríamos utilizar localización en nuestra aplicación, pero el sistema nos queda cojo ya que no hemos hecho nada para que las peticiones a la aplicación utilicen la cultura…
Para manipular estas peticiones configuraremos el middleware “RequestLocalizationMiddleware”. Este middleware utiliza una serie de proveedores para determinar la cultura actual, estos proveedores de definen en el método “ConfigureServices” de la clase “Startup
image
En la captura anterior tenemos un ejemplo de cómo generar una lista con las culturas que ‘soporta’ la aplicación y aplicar una cultura por defecto. Una vez aplicada esta configuración tenemos que añadir el middleware de localización, que se hace en el método “Configure” de la clase “Startup”.
image
Lo que hacemos en este método es obtener el servicio que hemos registrado anteriormente y lo utilizamos para indicar que lo queremos utilizar para la localización de las peticiones.

Utilizar localización en controladores y servicios

Cuando necesitemos acceder a texto localizado en servicios o controladores, lo primero que tendremos que hacer es inyectar In “IStringLocalizer<T>” en la clase y utilizar el indexador proporcionado para obtener el valor del texto:
image
Como ya hemos explicado, en el constructor del controlador inyectamos la dependencia para el “localizer” y en la “acción” Index accedemos al recurso “Título de la aplicación en castellano”. Si ahora accedemos a la página de inicio de la aplicación, veremos que aparece el texto que hemos utilizado como ‘índice’ (como hemos comentado antes, si no existe una entrada con la clave indicada, dicha clave se utiliza como texto ‘de vuelta’:
image
Ahora sería buen momento para añadir el archivo de recursos para un idioma adicional… Si partimos del hecho de que el idioma por defecto de nuestra aplicación será el castellano y viendo cómo funciona la localización en ASP.NET Core, podríamos asumir que NO necesitamos archivo de recursos para castellano, por lo que directamente crearemos el archivo de recursos para el resto de culturas configuradas, por ejemplo como se ve en las capturas anteriores, inglés.
En la parte de configuración hemos indicado que los archivos de recursos van en una carpeta “Resources”, que ASP.NET Core intenta encontrar en el raíz de nuestra aplicación, con lo que tendremos que crear dicha carpeta. a continuación, el sistema de ‘localización’ buscará el archivo de recursos correspondiente a la clase en la que estamos (HomeController), para ello por convención buscará una carpeta “Controllers” y dentro de ella el archivo de recursos (HomeController.en.resx), o también puede buscar un archivo de recurso con un nombre según este patrón: Controllers.HomeController.en.resx. Yo recomiendo la primera estructura de carpetas, lo que nos lleva a esta captura:
image
En esta carpeta crearemos el archivo de recursos (HomeController.en.resx) y en él añadiremos la entrada correspondiente a la clave que hemos utilizado anteriormente:
image
Como veréis, Visual Studio se “queja” de la clave que hemos utilizado, incluso es posible que aparezca un error en el panel de “Error List” pero por lo visto se trata de un problema del propio Visual Studio y no afecta a la compilación del proyecto. Sí, es un inconveniente…
image

Utilizar localización en Vistas

En el caso de las vistas, en lugar de ‘inyectar’ un “IStringLocalizer<T>” haremos lo propio con un “IViewLocalizer”. Este componente utiliza un patrón idéntico al que hemos visto en el caso anterior para encontrar los archivos de recursos, pero utilizando la estructura de vistas existente. por ejemplo para crear un archivo de recursos para una vista “Index.cshtml” que está en una carpeta “Home” tendríamos la siguiente estructura de carpetas:
image
Dentro de esta carpeta crearemos un archivo de recursos con el mismo nombre que la vista, como por ejemplo Index.en.resx:
image
La inyección del “IViewLocalizer” se realiza en la vista con la instrucción @inject”:
image
Como podemos ver en la captura, necesitamos importar el namespace para el interfaz, y con la instrucción @inject” generamos una propiedad “Localizer” mediante la cual accedemos al recurso.
image

Utilizar localización en ViewModels

Otro de los puntos que normalmente queremos localizar serán literales de posibles mensajes de error o advertencia que mostramos en las clases del “ViewModel”, por ejemplo a través de atributos de “DataAnnotation”. El mecanismo es análogo a los que hemos explicado anteriormente, el archivo de recursos estará en una subcarpeta de este estilo: “Resources/ViewModels/HomeViewModel.en.resx” y el uso en atributos iría así:
image
En el ejemplo vemos qué claves queremos localizar, el sistema los mapeará de manera automática.
image

Permitir a los usuarios elegir una cultura

Hasta ahora hemos estado hablando de localizar una aplicación ASP.NET Core, pero todo esto no sirve de nada si no disponemos de un mecanismo que permita al usuario cambiar el idioma de la aplicación… Hombre, sí que sirve si lo que queremos es basarnos en el idioma del navegador, pero ya que tenemos una aplicación multiidioma, pues vamos a aprovechar, ¿no?
El middleware que hemos configurado para activar la localización (recuerda, el RequestLocalizationMiddleware) ofrece un mecanismo extensible de proveedores de ‘cultura’ y además viene con tres proveedores por defecto:
  • QueryStringRequestCultureProvider: Especificar la cultura en la QueryString, por ejemplo ?culture=en
  • AcceptLanguageHeaderRequestCultureProvider: Especificar la cultura en el encabezado de la petición (mediante Accept-Language)
  • CookieRequestCultureProvider: Especificar la cultura mediante una Cookie.
En esta entrada vamos a probar el tercer proveedor, ya que parece que tiene más sentido utilizar cookies para este tema, ¿verdad?
Para permitir al usuario cambiar de idioma vamos a crear el equivalente a un control de usuario ascx en ASP.NET Core (o así lo entiendo yo) así que utilizaremos una vista parcial, _SelectLanguagePartial.cshtml en la carpeta Shared de las vistas:
image
En la captura anterior hay mucha tela que cortar, pero por intentar resumir un poco los pasos, tendríamos:
  1. Inyectamos el objeto para la localización (IViewLocalizer)
  2. Inyectamos el objeto donde hemos almacenado las opciones de la localización (IOptions<RequestLocalizationOptions>)
  3. Obtenemos la cultura de la petición, así como las distintas culturas que tenemos disponibles, estas últimas en una lista de objetos SelectListItem para poder utilizarlas en un combo con el que el usuario podrá cambiar el idioma de la aplicación (toda la sección HTML de la parte inferior)
Una vez diseñada la vista parcial tenemos que añadirla en las páginas deseadas (normalmente querremos el cambio de idioma en todas las páginas, así que podemos utilizar la vista _Layout.cshtml), para añadirla utilizaremos el método HTML.PartialAsync:
image
Para terminar, necesitamos implementar el código de controlador que realizará el cambio de idioma, acción “SetLanguage” del controlador “HomeController” como se puede ver en la captura del control de cambio de idioma.
image
En este código podemos ver cómo añadimos la cookie por defecto para el idioma en la colección de la respuesta y como (en este ejemplo) establecer un año de validez a la cookie.
¿Cómo queda el control de cambio de usuario?
Pues en esta ocasión quedaría así:
image
Si cambiamos el idioma en el combo y hacemos clic en “Guardar”, podemos ver cómo los literales se cogen de los distintos archivos de recursos.

Conclusiones

A ver, es mucho más sencillo ‘localizar’ aplicaciones en ASP.NET Core, pero, no por ser más sencillo estamos ‘aprueba’ de errores, algunos de los más típicos:
  1. Clave del recurso incorrecta (o modificada): Como este sistema no requiere que los archivos de recursos estén generados, y no tenemos tipado fuerte, se puede dar el caso de que al corregir, por ejemplo, una falta ortográfica en uno de los textos, se nos olvide modificar el texto también en los archivos de recursos… Resultado, no hay traducción.
  2. Ruta de los archivos de recursos: Por convención, el acceso a los archivos de recursos se realiza en función del Namespace de las clases donde vamos a utilizarlos, es un poco raro, pero si en algún momento veis que no está cogiendo traducciones, revisad por favor la ruta del archivo de recursos (y por supuesto como he puesto en el punto anterior, el nombre de la clave)
Creo que todavía tiene margen de mejora, pero lo cierto es que olvidarnos de establecer el CurrentCulture, la Cookie y demás, resulta ummm, cómodo.

Nota final

Si alguien se lo está preguntando, no he hecho ninguna prueba con el comportamiento de este mecanismo con controles tipo “Kendo”… No me chilléis, por favor.

martes, 12 de marzo de 2013

Rastrear usos intensivos de CPU en aplicaciones web

En este artículo vamos a presentar una estrategia para intentar localizar problemas en aplicaciones web que se traducen en usos intensivos de CPU.

La estrategia aquí presentada no es la única posible, pero yo la he utilizado con éxito.

Antes de comenzar

Antes de hacer nada de lo que se expone en este artículo, es necesario destacar que durante el periodo de análisis de la aplicación web se producen momentos de mucho ‘stress’ en el servidor de aplicaciones, con lo que es fundamental que todas estas pruebas se realicen en un entorno aislado en el que se haya podido reproducir el problema.

Además para facilitar la tarea es recomendable que el pool de aplicación asignado a la aplicación web esté dedicado únicamente a ella, ya que de lo contrario se puede generar un ruido innecesario.

Un punto fundamental antes de comenzar es que tenemos que haber conseguido previamente reproducir el problema; esto quiere decir que la manera más eficaz de realizar este tipo de análisis es siendo capaces de provocar el uso intensivo de CPU.

Requisitos

Para poder analizar la información necesaria para localizar el problema, necesitaremos una serie de herramientas (gratuitas) que necesitaremos instalar por un lado en el servidor web y por otro en el equipo donde realizaremos los análisis (si es distinto del servidor)

Herramienta

URL Descarga

Cliente / Servidor

Debug Diagnostic Tool 1.2

Enlace externo

Servidor

WinDbg

Enlace externo

Cliente

SOS.dll

Disponible en la carpeta del Framework 2.0

Cliente

La instalación de la herramienta de diagnóstico “Debug Diagnostic Tool 1.2” puede ser un poco “enrevesada” ya que tiene reconocidos problemas cuando se instala en un equipo que no esté en inglés. Para las instrucciones de instalación en este tipo de sistemas, podemos consultar el artículo correspondiente publicado hace un tiempo [acceso].

Captura de información

Lo primero que tenemos que hacer es capturar la información necesaria para realizar posteriores análisis e intentar determinar el origen de los problemas. Esta información se recoge en forma de “volcados” o “dumps” y se realizará en el servidor mediante la herramienta “Debug Diagnostic Tool 1.2”

Pasos para realizar el volcado correctamente:

1. Realizamos una llamada a la aplicación web para que se inicie el proceso ‘w3wp’ correspondiente, por si acaso.

2. Iniciamos sesión en el servidor.

3. Abrimos la consola de IIS, seleccionamos el servidor y hacemos doble clic en “Procesos de trabajo” en la sección de la derecha correspondiente a “IIS”
clip_image001

4. En la ventana que se abre aparecen todos los pools de aplicaciones que están activos, tendremos que apuntar el ID del proceso que nos interesa (el correspondiente al pool de aplicación de nuestra aplicación web)
clip_image002

5. Arrancamos la herramienta “Debug Diagnostic Tool” y cancelamos la ventana emergente que aparece.

6. Vamos a la pestaña “proceses” y localizamos el correspondiente al ID obtenido anteriormente.
clip_image003

7. Realizamos las operaciones necesarias en la aplicación web hasta conseguir que se dispare el uso de CPU

8. En el momento en el conseguimos el comportamiento incorrecto, tenemos que realizar un volcado de memoria mediante la herramienta de Debug. Para esto, hacemos clic con el botón derecho del ratón sobre el proceso y seleccionamos “Create full user dump”
clip_image004

9. Una vez finalizado el volcado, nos aparecerá el siguiente mensaje, indicando además en qué ubicación de disco se ha generado dicho volcado.
clip_image005

10. Listo, hemos generado el volcado correctamente

En ocasiones en función del grado de uso u ocupación del proceso, es posible que en lugar del mensaje de éxito nos aparezca un mensaje de que NO se ha podido generar el volcado. Esto suele suceder porque llegado un grado “X” de uso, el pool se recicla como parte de su configuración anti-errores. Para evitar que esto nos afecte, tendremos que cambiar ese comportamiento en la “Configuración avanzada” del pool de aplicación, la opción aparece destacada en la siguiente captura:

clip_image006

Si la protección rápida está habilitada y se produce el problema mencionado, bastará con deshabilitar esa opción de manera temporal.

Analizando la información

Una vez que hemos conseguido el volcado del proceso, llega el momento de analizarlo para intentar localizar los puntos de ‘conflicto’

Es necesario destacar que este proceso no es una ‘ciencia exacta’ por lo que tal vez no obtengamos información útil, pero al menos es una posibilidad muy a tener en cuenta.

El análisis de los volcados lo realizaremos con la herramienta “WinDbg”, pero antes tenemos que realizar una pequeña configuración:

1. Abrimos la carpeta del ‘Framework’ donde está la dll “SOS.dll” especificada en la tabla del punto 5.

2. Copiamos esa dll a la carpeta de instalación de “WinDbg”. Esta librería es necesaria porque proporciona información sobre el entorno interno del CLR.

3. En una carpeta del equipo donde realizaremos el análisis, creamos una carpeta “symcache” (será utilizada por el depurador para desargar los símbolos de los archivos PDB’s) en este documento se asume que la carpeta existe en la ruta c:\symcache

Para analizar el volcado, seguimos los siguientes pasos:

1. Arrancamos la herramienta WinDgb

2. Cargamos el archivo de volcado, mediante el menú “File”, “Open Crash Dump”

3. Una vez cargado el archivo, ejecutamos los siguientes comandos:

a. .symfix c:\symcache

b. .reload

c. .load sos

4. Obtenemos todos los procesos recogidos en el volcado con el comando !runaway, que nos dará un resultado como este:
clip_image001[5]
En esta lista, ordenada por tiempo de CPU, podemos observar qué procesos están haciendo un mayor uso de la CPU. En la captura anterior, vemos que son los procesos con ids 27 y 23

5. Comprobamos que los hilos ‘sospechosos’ pertenecen a procesos de .Net, con el comando !threads:
clip_image003[5]
La imagen se ve pequeñita, pero se confirma que uno de los hilos ‘sospechosos’ es un hilo ‘manejado’ por el CLR.
Además, podemos ver que uno de los hilos que aparecen está en un estado de “excepción”. Un vistazo de los dos hilos implicados, releva el estado de la ejecución:

a. Hilo 27: System.Threading.ThreadAbortException

b. Hilo 25: System.CannotUnloadAppDomainException

6. A continuación, ‘navegamos’ a los hilos con el comando ~27s y ~25s (el formato es ~[#hilo]s

7. En cada uno de ellos, obtenemos la pila de llamadas con el comando !clrstack. Con esta pila podemos intentar averiguar qué está pasando en la aplicación.

Como complemento al documento, se añaden las capturas de los hilos y la conclusión que nos han permitido obtener.

Detalle del hilo “27”

clip_image004[5]

Detalle del hilo “25”

clip_image006[5]

Conclusiones

Con la información que hemos obtenido, podemos determinar que la aplicación en cuestión ha intentado descargarse de memoria (System.AppDomain.Unload en el hilo 25) pero que existe un hilo (el 27) que está ocupando mucho tiempo de CPU al hacer:

Oracle.DataAccess.ClientOracleTuningAgent.DoScan().

En esta ocasión, podemos interpretar que existe algún problema con el Cliente Oracle. Una búsqueda en google nos da el siguiente enlace, que avala nuestra teoría [acceso].

Extracto de la página:

“This has been resolved. The fix is released in Oracle 11.2.0.1.2, which is available through the oracle.com website”

lunes, 25 de febrero de 2013

Instalar la herramienta Debug Diagnostic Tool v1.2

Sin morir en el intento

Problema

Tenemos una aplicación web que está teniendo un uso excesivo de CPU en determinadas ocasiones, pero que no estamos pudiendo determinar cuándo o más importante, por qué, está haciendo ese uso intensivo de CPU.
Para revisar la aplicación decidimos descargar e instalar esta herramienta, disponible [aquí].
Comenzamos la instalación (siguiente, siguiente siguiente) y de repente:
image
Después de buscar mucho por aquí y por allí, lo que encontramos es que es un problema con el soporte multiidioma del instalador de la herramienta. Lo cierto es que es bastante triste, pero el instalador requiere que exista un grupo ‘Users’ en la máquina de instalación, y como en este caso la máquina de instalación está en español, ese grupo, pues no existe. Triste triste.

La solución

Pues no se trata de una solución como tal, más bien de un ‘workaround’ que nos permitirá instalar y ejecutar la herramienta sin problemas.
  1. Vamos a la Administración del Equipo
  2. En la sección de grupos locales, creamos un grupo que se llame “Users” y en el incluimos el usuario con el que hayamos iniciado sesión en la máquina.
  3. Damos permisos de control total a este grupo en la carpeta de instalación.
  4. Instalar la herramienta.
En este punto es posible que nos de otro error diciendo en la fase de “Removing backup files”. En este punto, si le damos a continuar la instalación NO se realiza y además borra los archivos que hubiera copiado originalmente. Para solucionar este problema, cuando nos dé este error:
  1. Antes de pulsar el botón, vamos a la carpeta de instalación (por defecto “C:\Program Files\DebugDiag”) y copiamos el contenido llevándolo a una ubicación temporal.
  2. Le damos al botón de finalizar en la ventana de error y nos borrará el contenido de esa carpeta
  3. Movemos los archivos de la ubicación temporal a la carpeta de instalación.
  4. Ejecutamos de nuevo la instalación.
SOLUCIONADO.
No preguntéis por que, porque no lo sé, pero bajo mi humilde opinión es una ‘cagada’ con todas las letras por parte de Microsoft, además de ser incomprensible. Por supuesto, una vez instalada la herramienta podemos eliminar el grupo creado sin problemas.

jueves, 22 de noviembre de 2012

Visual Studio no lanza todas las excepciones del código

Hoy me ha pasado una cosa un poco extraña relacionada con la gestión de excepciones.

El problema

Tenemos un formulario de Windows con una caja de texto en la que en el evento “TextChanged” realizamos una serie de operaciones, llamando para ello a un método externo.

El tema es que en un momento dado, me he fijado que en el método externo se estaba produciendo una excepción, pero en depuración no me estaba mostrando la típica ventana de excepción no controlada… Vamos, que no me estaba enterando de que había un problema con el código.

Para reproducir este comportamiento, basta con añadir una caja de texto a un formulario y codificar en el manejador del evento “TextChanged” una llamada a una función que produzca una excepción, por ejemplo:

image

Ejecutamos el formulario y escribimos algo en la caja de texto.

¿Aparece esta ventana?

image

Entonces no tienes el mismo problema que yo y te has equivocado de post…

Lo que a mí me pasaba, es… nada. No da ningún tipo de excepción al trabajar con el formulario en cuestión. entonces, ¿cómo sabemos que hay una excepción? en la ventana de “Output” aparece la siguiente entrada:

image

Una explicación (rapidita)

Por lo visto, este comportamiento es así por diseño, siempre que estemos ejecutando Visual Studio en un sistema en 64 Bits (como es mi caso) cuando la excepción se produce en un método que cause una transición al kernel (como por ejemplo el manejador en cuestión, esta excepción se trata en el propio kernel y se atrapa por el sistema operativo. Como la excepción ya ha sido controlada, lo que sucede es que nosotros no nos enteramos.

Para más detalle, entiendo que Google estará encantado de ayudarnos.

Una solución (más bien alternativa)

Para conseguir que el depurador de Visual Studio nos avise de esas excepciones, tenemos que indicarle explícitamente, en la ventana de “Exceptions”

image

Esta ventana aparece en el menú “Debug”, “Exceptions…” y para evitar el comportamiento que he explicado, basta con marcar la casilla “Thrown” del grupo “Common Language Runtime Exceptions”

Una vez marcada la casilla, cuando llega al punto de la excepción, ya nos aparece la ventana de excepción no controlada que necesitamos. De esta manera ya no se nos “enmascaran” posibles errores…

¿Por qué digo que es una alternativa?

Un efecto colateral de esta configuración es que a partir de activar la opción, cada vez que de una excepción (sea controlada o no) nos va a aparecer la dichosa ventanita, deteniendo el depurador hasta que le demos a continuar.

Esto en condiciones normales es un auténtico problema, pero yo considero que me merece la pena el inconveniente, sobre todo si trabajamos con ‘rethrowing’

Último apunte

El problema expuesto aquí no genera ningún problema adicional en el código desarrollado, ya que si en lugar de arrancar el depurador ejecutamos el archivo compilado o lanzamos la ejecución SIN depuración (Ctrl + F5) la excepción no controlada SÍ que aparece aunque, claro, con la apariencia que nadie queremos en nuestros programas

image

martes, 6 de noviembre de 2012

Trabajando con NuGet–Un inicio

¿Qué es NuGet?

NuGet es una extensión de Visual Studio que hace que sea fácil agregar, actualizar y elimina bibliotecas (implementadas como paquetes) en un proyecto de Visual Studio. Un paquete de NuGet es un conjunto de archivos empaquetados en un solo archivo con extensión .nupkg que usa el formato Convenciones de empaquetado abierto (OPC).

(Copiado íntegramente del MSDN)

¿Qué hace falta?

Lo primero, instalarlo.

En Visual Studio 2010 se instala mediante el administrador de extensiones (Menú Tools, Extension Manager) mientras que Visual Studio 2012 lo trae instalado por defecto.

Una vez instalado, basta utilizar los nuevos menús (Manage NuGet Packages)

Esta herramienta es brutal, pero lo verdaderamente brutal sería poder crear nuestro propio repositorio de paquetes de NuGet, de forma que en la organización tuviéramos todos los componentes homologados disponibles para su utilización, actualizables además muy fácilmente.

En el artículo indicado anteriormente tenemos las instrucciones básicas, que a continuación intentaré explicar un poco más si es necesario.

Generar un servidor NuGet

No es necesario generar un servidor de NuGet para poder trabajar con un repositorio particular de paquetes, pero considero que es importante y útil como para al menos indicarlo.

Sencillo:

  1. Creamos una aplicación web ASP.NET (4.0) vacía en Visual Studio.
  2. Instalamos el paquete de NuGet “NuGet.Server”
  3. Publicamos la aplicación en un servidor web.
  4. Publicamos en la carpeta “Packages” los paquetes de NuGet que queramos que estén disponibles.

Añadir una ruta de paquetes en Visual Studio

Para configurar Visual Studio de forma que pueda conectar al repositorio, tenemos que ir a Herramientas, Opciones, y añadir un nuevo origen de paquetes en la ventana:

image

Generar un paquete de NuGet

Para generar nuestros propios paquetes para NuGet, podemos hacerlo mediante línea de comandos (descargando nuget.exe) o podemos hacerlo con un interfaz gráfico (descargando el “NuGet Package Explorer”) se trata de una aplicación click-once, con lo que se actualizará automáticamente.

A continuación vamos a ver los pasos necesarios para generar un paquete con el cliente click-once.

  1. Arrancamos el “NuGet Package Explorer”
  2. Elegimos la opción “Create a new package”
    image
  3. En la parte de la izquierda editamos los metadatos del paquete (Menú Edit, Metadata)
  4. En la parte de la derecha arrastramos en ensamblado que queremos empaquetar.
    image
  5. Guardamos el paquete en la ruta deseada con el menú File, Save o podemos exportarlo con el menú File, Export…

En el momento de generar el paquete podemos además indicar las dependencias que nuestro paquete tenga con otros componentes. Para añadir una dependencia, hacemos clic en el botón “Edit dependencies” en la parte inferior de la sección izquierda (donde hemos puesto la información del paquete)

  1. Añadimos un nuevo grupo con el botón con el símbolo “más”
    image
  2. Ahora hacemos clic en el botón con el icono de propiedades para elegir una dependencia alojada en un repositorio, y la seleccionamos con doble clic (en la siguiente captura, seleccionamos el paquete de log4net)
    image
  3. Confirmamos haciendo clic en el botón de añadir nueva dependencia (a la derecha de la caja con la versión del componente)
    image
  4. Confirmamos con “OK” y ya tenemos la dependencia creada.

Al añadir una dependencia, lo que conseguimos es que cada vez que se instale el paquete, automáticamente se instalen también las dependencias configuradas.

Otra opción interesante es hacer ‘transformaciones’. Esto significa que podemos configurar el paquete para que actualice archivos presentes en el proyecto, por ejemplo el archivo App.config.

Para esto, en la sección de “Package contents”

  1. Añadimos la carpeta para contenido (menú Content, Add, Content Folder)
    image
  2. Sobre la carpeta “content” añadimos un nuevo archivo con el botón derecho del ratón y, muy importante, le damos al archivo el nombre del archivo que queremos modificar, terminado en “.transform”
    image
  3. Esto genera un archivo vacío, en el que incluiremos el contenido que deseamos que se añada al configurar el paquete en el proyecto, en la siguiente captura se puede ver el contenido necesario para el correcto funcionamiento del paquete ‘log4net’
    image

Una vez hecho todo esto, cuando configuremos el proyecto para utilizar el paquete, automáticamente añadirá las entradas especificadas en el archivo de configuración.

Actualizar un paquete de NuGet

Realmente no existe el concepto como tal de actualizar, realmente lo que hacemos es un “Save as” del paquete anterior, modificando la versión en la sección de “Package Metadata”. Al hacer el “Save as” nos propone el nombre original actualizado con la nueva versión, y una vez en la solución, si hacemos clic con el botón derecho del ratón sobre la solución y elegimos “Manage NuGet Packages for Solution” veremos que tenemos nueva versión del paquete, y podremos actualizar todos los proyectos de la solución de un plumazo.

image

image

Ultimas consideraciones

Existen más posibilidades al generar paquetes, como por ejemplo publicar distintas versiones de los ensamblados para distintas versiones del Framework, pero de momento no vamos a entrar más a fondo, como primera aproximación es suficiente.