Capitulo 8: Desarrollo de aplicaciones confiables (Parte 1)

Lección 1: Seguimiento y recopilación de datos de rendimiento

Implementando la Instrumentación
La Instrumentación permite determinar el estado de ejecución de un sistema despues de que ha sido deployado.
Se instrumenta la aplicación cuando se comienza a desarrollar , creando una política de instrumentación determinando que se quiere instrumentar porque , donde y como. Esto se puede realizar con varias tecnologías como: event logging (registro de eventos), debug tracing (seguimiento de depuración), y performance counters (contadores de rendimiento).

Accediendo a SQL generado por LINQ to SQL
Cuando se trabaja con clases de LINQ to SQL, se puede asignar un TextWriter a la propiedad Log del DataContext y crear un StreamWriter para llenar un archivo de registro y asignárselo a la propiedad Log, y comenzar a ejecutar consultas.
El registro de cada consulta ejecutada, es muy costosa, así que sería bueno controlarlo y esto se realiza en el archivo. Config. Para lograr esto, se agrega un BooleanSwitch y se establece el valor a convertir o desactivar del registro .
Para configurar el registro de una manera mas controlable,se puede crear una nueva clase  LinqToSqlTraceWriter(usando System.Diagnostics), que herede de TextWriter, para así poder asignársela a la propiedad Log del DataContext. Esta clase sobrescribe los métodos de Write y WriteLine, por lo que este reemplazo permite interceptar todos los datos y pasarlos al método Trace.Write (sólo si el BooleanSwitch está habilitada en el archivo .Config) . Tambien se deben reemplazar  los métodos Close y Flush para llamar Trace.Close y Trace.Flush, respectivamente:
-------------------------------------VB-------------------------------------------
Public Class LinqToSqlTraceWriter
Inherits TextWriter
Private logSwitch As BooleanSwitch
Public Sub New(ByVal switchName As String)
logSwitch = New BooleanSwitch(switchName, switchName)
End Sub

Public Overrides ReadOnly Property Encoding As Encoding
Get
Throw New NotImplementedException()
End Get
End Property
Public Overrides Sub Write(ByVal value As Char)
If (logSwitch.Enabled) Then
Trace.Write(value)
End If
End Sub
Public Overrides Sub Flush()
Trace.Flush()
End Sub
Public Overrides Sub Close()
Trace.Close()
End Sub
End Class
-------------------------------------CS-------------------------------------------
using System;
using System.Diagnostics;
using System.Text;
using System.IO;
namespace ReliableApplication.LinqToSql
{
public class LinqToSqlTraceWriter : TextWriter
{
private BooleanSwitch logSwitch;
public LinqToSqlTraceWriter(string switchName)
{
logSwitch = new BooleanSwitch(switchName, switchName);
}
public override Encoding Encoding
{
get { throw new NotImplementedException(); }
}
public override void Write(char value)
{
if (logSwitch.Enabled)
{
Trace.Write(value);
}
}
public override void Flush()
{
Trace.Flush();
}
public override void Close()
{
Trace.Close();
}
}
}
Se puede agregar la clase anterior al proyecto y ejecutar una consulta de LINQ to SQL para registrar los resultados. El siguiente ejemplo muestra una consulta simple para un IEnumerable de clientes:
-------------------------------------VB------------------------------------------- 
Dim db = New LinqToSql.NorthwindDataContext()
db.Log = New LinqToSqlTraceWriter("LinqToSqlSwitch")
Dim cust = From c In db.Customers
Where c.CompanyName.StartsWith("A") _
And c.Country = "UK"
Order By c.CompanyName
Select c
Dim items = cust.ToList()
-------------------------------------CS-------------------------------------------
var db = new LinqToSql.NorthwindDataContext();
db.Log = new LinqToSqlTraceWriter("LinqToSqlSwitch");
var cust = from c in db.Customers
where c.CompanyName.StartsWith("A")
&& c.Country == "UK"
orderby c.CompanyName
select c;
var items = cust.ToList();
Para que el traceo funcione, se debe activar el seguimiento en el archivo .Config:

image


Cuando el interruptor LinqToSqlSwitch se establece a 1,  permite el cambio en el código.

Cuando se ejecuta el código con una consulta LINQ to SQL, se verá la instrucción SQL en  la ventana de resultados (Output) de Visual Studio:

clip_image001[6]

También se puede cambiar la ubicación del registro o añadir otros lugares. Esto se puede hacer desde el archivo. Config, sin necesidad de recompilar la aplicación. Ej. de 2 listeners, uno para escribir en un archivo de texto y otro para la escritura en el registro de sucesos de Windows:
image


Accediendo al SQL generado por el Entity Framework

Si queremos ver el SQL que se genera cuando se ejecuta una consulta LINQ,se puede hacer mediante el método ToTraceString de la clase ObjectQuery. 

La mayoría de consultas de LINQ to Entities devuelven un  IQueryable, que se puede convertir en una clase ObjectQuery. Para implementar esto, puede crear un método de extensión de IQueryable que realice la conversión y ejecute el método ToTraceString:

-------------------------------------VB-------------------------------------------
Imports System.Runtime.CompilerServices
Imports System.Data.Objects
Module ExtensionMethods
Public Function ToTraceString(Of T)(ByVal query As IQueryable(Of T)) As String
Dim objQuery = CType(query, ObjectQuery(Of T))
If (Not objQuery Is Nothing) Then
Return String.Format("{0}{2}{1}{2}{2}", _
DateTime.Now, objQuery.ToTraceString(), _
Environment.NewLine)
End If
Return String.Emp
End Function
End Module
-------------------------------------CS-------------------------------------------
using System;
using System.Data.Objects;
using System.Linq;
namespace ReliableApplication
{
public static class ExtensionMethods
{
public static string ToTraceString(this IQueryable query)
{
var objQuery = query as ObjectQuery;
if (objQuery != null)
return string.Format("{0}{2}{1}{2}{2}",
DateTime.Now, objQuery.ToTraceString(),
Environment.NewLine);
return string.Empty;
}
}
}


Para probar este código,podemos agregar código para realizar una consulta LINQ, llamando a este método y anexar los resultados a un archivo de registro:

-------------------------------------VB-------------------------------------------
Dim traceFile = Environment.GetFolderPath( _
Environment.SpecialFolder.Desktop) _
+ "\EntityFrameworkTrace.log"
Dim db = New NorthwindEntities()
Dim cust = From c In db.Customers
Where c.CompanyName.StartsWith("A") _
And c.Country = "UK"
Order By c.CompanyName
Select c
File.AppendAllText(traceFile, cust.ToTraceString())
-------------------------------------CS-------------------------------------------
var traceFile = Environment.GetFolderPath(
Environment.SpecialFolder.Desktop)
+ @"\EntityFrameworkTrace.log";
var db = new NorthwindEntities();
var cust = from c in db.Customers
where c.CompanyName.StartsWith("A")
&& c.Country == "UK"
orderby c.CompanyName
select c;
File.AppendAllText(traceFile, cust.ToTraceString());


Después de ejecutar el ejemplo de código, detener la aplicación y abrir el archivo  EntityFrameworkTrace.log que está en el escritorio. El resultado es el siguiente:

1/2/2012 8:31:03 PM
SELECT
[Extent1].[CustomerID] AS [CustomerID],
[Extent1].[CompanyName] AS [CompanyName],
[Extent1].[ContactName] AS [ContactName],
[Extent1].[ContactTitle] AS [ContactTitle],
[Extent1].[Address] AS [Address],
[Extent1].[City] AS [City],
[Extent1].[Region] AS [Region],
[Extent1].[PostalCode] AS [PostalCode],
[Extent1].[Country] AS [Country],
[Extent1].[Phone] AS [Phone],
[Extent1].[Fax] AS [Fax]
FROM [dbo].[Customers] AS [Extent1]
WHERE ([Extent1].[CompanyName] LIKE N'A%') AND (N'UK' = [Extent1].[Country])
ORDER BY [Extent1].[CompanyName] ASC
 
El accediendo  e implementando contadores de rendimiento
Los contadores de rendimiento proporcionan datos sobre cómo la aplicación utiliza los recursos. En tiempo de ejecución,se puede utilizar la utilidad de rendimiento que es parte de Microsoft Windows para proporcionar una vista gráfica de los contadores.

Para iniciar la herramienta (Monitor de rendimiento de Windows), Inicio | Panel de control | Herramientas administrativas y doble clic en Monitor de rendimiento.


clip_image002[6]

Después se inicia el Monitor de rendimiento, se puede abrir el nodo de herramientas de seguimiento para ver Monitor de rendimiento. Este se actualiza constantemente con el valor actual de tiempo de procesador por ciento, un contador de rendimiento.

clip_image003[6]

En la parte superior de la pantalla del Monitor de rendimiento hay un signo más, con el que se puede hacer clic para agregar más contadores para el gráfico. Al hacer clic en el signo más se abre la ventana Agregar contadores.
clip_image004[6]

En la parte Agregar contadores se muestra una lista desplegable desde el que puede seleccionar lo que se desea supervisar. Debajo de ella, usted encontrará una lista de categorías de Monitor de rendimiento.

También se puede crear contadores de Monitor de rendimiento  propios para la aplicación usando System.Diagnostics. Antes de añadir un contador de rendimiento personalizado, se debe agregar un PerformanceCounterCategory, pero se debe verificar que la categoría no existe antes de crearlo, o se lanzara una excepción InvalidOperationException:


-------------------------------------VB-------------------------------------------
Dim catName = "MyAppCategory"
If Not PerformanceCounterCategory.Exists(catName) Then
PerformanceCounterCategory.Create(catName, _
"Here is the category help.", _
PerformanceCounterCategoryType.SingleInstance, _
"MyCounter", _
"Esta es la ayuda del contador.")
MessageBox.Show("Category and counter creado")
Else
MessageBox.Show("Category and counter ya existe")
End If
-------------------------------------CS-------------------------------------------
var catName = "MyAppCategory";
if (!PerformanceCounterCategory.Exists(catName))
{
PerformanceCounterCategory.Create(catName,
"Here is the category help.",
PerformanceCounterCategoryType.SingleInstance,
"MyCounter",
"Esta es la ayuda del contador.");
MessageBox.Show("Category and counter creado");
}
else
{
MessageBox.Show("Category and counter ya existe");
}
Enumeracion PerformanceCounterCategoryType
Indica si la categoría de contador de rendimiento puede tener varias instancias:

Nombre
Descripción
Unknown
Se desconoce la funcionalidad de instancia de la categoría de contador de rendimiento.
SingleInstance
La categoría de contador de rendimiento puede tener sólo una instancia.
MultiInstance
La categoría de contador de rendimiento puede tener varias instancias.

Resumen de la lección
  • Al utilizar clases LINQ to SQL, se puede utilizar la propiedad Log del DataContext para recoger todas las instrucciones SQL enviadas al servidor de base de datos cuando se ejecuta la aplicación.
  • Al trabajar con Entity Framework, debe utilizar el método ToTraceString del ObjectQuery.
  • Para acceder al método ToTraceString, se debe convertir la consulta a
    ObjectQuery, utilizando la instrucción de Visual Basic CType  o en C# casting.
  • Se puede utilizar el Trace framework que forma parte de. NET Framework para escribir datos en los  trace listeners, basado en el trace switch.
  • La utilidad de Monitor de rendimiento se puede utilizar mientras se ejecuta la aplicación para ver los contadores del monitor de rendimiento.


No hay comentarios:

Publicar un comentario