Streaming de las trazas en Azure Web Sites

Una característica interesante cuando desplegamos nuestras aplicaciones en Windows Azure Web Sites es la posibilidad de tener un streaming en tiempo real de las trazas de la aplicación, cosa que resulta muy útil, sobre todo en tiempo de desarrollo.

Esta funcionalidad está disponible para todos los frameworks y lenguajes que están soportados en la plataforma, en el caso de aplicaciones .NET, se integra perfectamente con System.Diagnostics.

Por ejemplo, si partimos de una aplicación de ejemplo de ASP.NET MVC, podemos añadir las siguientes trazas de información, error o advertencia en cada uno de los controladores que tenemos:

public ActionResult Index()
{
    Trace.TraceInformation("Index action selected!");

    ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
    return View();
}

public ActionResult About()
{
    Trace.TraceError("About action selected!");

    ViewBag.Message = "Your app description page.";
    return View();
}

public ActionResult Contact()
{
    Trace.TraceWarning("Contact action selected!");

    ViewBag.Message = "Your contact page.";
    return View();
}

Después de desplegar la aplicación en la plataforma, podemos hacer uso de las herramientas de líneas de comandos, disponibles en todas las plataformas, para conectarnos al site y ver las trazas que se van generando.

El comando es: azure site log tail <site>

La herramienta permite tanto ver el log en tiempo real, como descargarse los logs.

Streaming2

Aquí tenemos un ejemplo de las trazas generadas.

Streaming3

Y aquí un ejemplo dónde filtro por las trazas que tienen la palabra “Index”.

Streaming4

Claro está, además de poder ver o descargar el log desde la línea de comandos, también podemos conectarnos por FTP a nuestro site y ver los logs generados. Por defecto la plataforma divide el log en ficheros máximos de 128k. Así mismo permite por defecto hasta 1 Mb de log para la aplicación. Los logs permanecen en el sistema hasta un máximo de 12 horas.

Streaming5

Desde la configuración del site, en el portal de Windows Azure, podremos ver y modificar la configuración del site.

Si no tenemos activada el log de la aplicación y nos conectamos con la herramienta de línea de comandos, ésta activará automáticamente el log.

Streaming1

Por último, comentar también que modificar la configuración de las trazas de la aplicación no implica que se recicle el pool y que no tanto se reinicie nuestro site. La configuración de diagnóstico se guarda en un fichero settings.json al que podemos acceder por FTP y verlo en el directorio diagnostics.

 

Streaming6

Log se guarda por defecto 12 horas

Si se conectas con la herramienta de línea de comandos para ver el streaming, te activa automáticamente el log.

Por defecto los ficheros se dividen en partes de 128K y el log siempre queda por debajo de 1 MB. Se pueden sobreescribir estos valores.

Cambiar la configuración de diagnóstico no recicla el pool y ni reinicia tu aplicación.

Securizar aplicaciones Windows Phone 8 con ACS

Siguiendo con la serie de post sobre gestión de identidad y seguridad basada en claims, después de ver cómo es posible securizar aplicaciones Windows 8, en esta entrada toca hablar de Windows Phone 8.

Para este ejemplo partimos de post anterior, dónde veíamos cómo usar WebAutenticationBroker para securizar aplicaciones Windows 8, y los cambios que debíamos hacer en nuestro servicio WebAPI para generar el token que autenticación.

En Windows Phone 8 NO tenemos disponible la librería Windows Autentication Library (AAL), ni tampoco el WebAutenticationBroker, pero aún así, veremos cómo el código a realizar es bastante sencillo.

Después de crear una aplicación de ejemplo de Windows Phone 8 en Visual Studio, crearemos una nueva página llamada SignIn.xaml dónde meteremos la lógica de autenticación. En la página principal de nuestra aplicación podemos añadir la lógica necesaria para que si el usuario no está autenticado, se le lleve a esta página.

La página de SingIn lo único que va a tener es un control WebBrowser, que será el encargado de mostrar la página de autenticación del proveedor o proveedores de identidad que tengamos configurados en Windows Azure Access Control.

WP8ACS1

En la página sólo tendremos que código, para que en el webrowser se vea la ventana de login del proveedor de identidad.

Fijaros en que la URL que mostramos es exactamente la misma que usábamos en el ejemplo de Windows 8 con WebAuthenticationBroker. Al igual que el ejemplo anterior, el namespace del ACS es “estoyenlanube”, mientras que el servicio WebAPI lo tengo desplegado en https://estoyenlanube.azurewebsites.net. Lo tengo desplegamos en un servidor real porque ACS no es capaz de redirigir a direcciones localhost.

public SignIn()
{
    InitializeComponent();

    signInBrowser.IsScriptEnabled = true;

}

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    string authURL = string.Format(
        "https://estoyenlanube.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=https://estoyenlanube.azurewebsites.net/&wreply=https://estoyenlanube.azurewebsites.net/api/federation");

    //navigate to it
    signInBrowser.Navigate(new Uri(authURL));
}

Con este código mostramos la ventana de login, pero una vez autenticado tenemos que ser capaces de coger el token de autenticación para poder usarlo en las llamadas a nuestro servicio WebAPI. Para ello usaremos el evento Naviagating para llamar cuando el navegador va a la URL que le hemos que tiene que redirigir una vez autenticado. El token lo obtenemos de la misma manera que el ejemplo de Windows 8.

private void Navigating(object sender, NavigatingEventArgs e)
{
    string returnURL = e.Uri.ToString();
    if (returnURL.StartsWith("https://estoyenlanube.azurewebsites.net/api/federation/end"))
    {
        e.Cancel = true;
        signInBrowser.Visibility = System.Windows.Visibility.Collapsed;
        var token = returnURL.Substring(returnURL.IndexOf("token=", StringComparison.Ordinal) + 6);
        DoGet(token);
    }
}

async Task DoGet(string token)
{
    HttpClient httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", "Bearer " + token);

    var response = await httpClient.GetStringAsync(https://estoyenlanube.azurewebsites.net/api/values);
}

Snapshots de máquinas virtuales

Trabajando con virtualización una de las funcionalidades habituales que tenemos es la posibilidad de generar snapshots de nuestras máquinas virtuales, los cuáles nos permiten volver cuando queremos a tener la máquina en el estado en el que estaba cuando lo creamos.

Trabajando con Windows Azure no tenemos de forma directa esta funcionalidad, pero sí tenemos la posibilidad de generar snapshots de los ficheros VHDs sobre el que se monta la máquinas virtual, por lo que al menos tenemos una posible alternativa.

La primera opción que podemos usar es utilizar una herramienta que disponga ya de esta funcionalidad, como Cloud Storage Studio. Esta herramienta nos permite conectarnos a un storage de Windows Azure y ver los VHDs sobre los que montan las máquinas virtuales. Cerebrata también dispone de Cmdlets de powershell que ofrecen la misma funcionalidad.

Una vez seleccionado el blob podemos generar snaphots, ver los snapshots existentes, promocionar uno etc…

snapshopt1

snapshopt2

Otra opción, si no tenemos una herramienta que nos ofrezca la funcionalidad, es usar nosotros directamente el API de Windows Azure para hacernos nuestra propia aplicación que haga los snapshots.

A modo de ejemplo, aquí os dejo un código que se conecta a un almacenamiento de Windows Azure, genera un snapshot y luego lo restaura.

 

private CloudBlobClient blobClient;
private const string storageName = "<storagename>";
private const string privateKey = "<privatekey>";

[TestMethod]
public void TestBlobSnapshot()
{
    string connectionString = String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", storageName,privateKey);
    CloudStorageAccount account = CloudStorageAccount.Parse(connectionString);
    blobClient = account.CreateCloudBlobClient();

    CloudBlobContainer testcontainer = new CloudBlobContainer("vhds",blobClient);

    // Upload a blob to the storage service, populate under the current container
    var blobRef = testcontainer.GetBlobReference("sourcetobackup.vhd");

    // Create a snapshot for the blob
    CloudBlob snapshotRef1 = blobRef.CreateSnapshot();

    // restore from snapshop
    var blobTargetRef = testcontainer.GetBlobReference("newserver.vhd");
    blobTargetRef.DeleteIfExists(new BlobRequestOptions()
    {
        // need to specify this option in order to delete blob with snapshots
        DeleteSnapshotsOption = DeleteSnapshotsOption.IncludeSnapshots
    });

    blobTargetRef.CopyFromBlob(snapshotRef1);

}