Google Analytics

Que es Goolge Analytics?

Google Analytics captura la información de navegación de los usuarios.
A partir de esta información podemos analizar diferentes tipos de estadísticas:

  • Audience: Como es nuestro usuario (ubicación, dispositivo, gustos, edad…).
  • Adquisición: Cual es el origen del trafico (buscador, anuncio, referencia…).
  • Behaviour: Como el usuario se comporta (paginas vistas, abandonos…).
  • Conversions: Como conseguimos los objetivos de navegación.
  • Customization: Definir nuestras propias estadísticas personalizadas.

Arquitectura de Configuración Analytics

El siguiente diagrama muestra la entidades principales a definir:

Anuncios
Publicado en Uncategorized | Deja un comentario

Azure Information Protection

Que es Azure Information Protection (AIP)?

Permite añadir etiquetas a documentos y emails para protegerlos. Estas etiquetas también pueden ser recomendadas en base a reglas. Al aplicar la etiqueta se utiliza una plantilla de Azure Rights Management (RMS) que define los permisos (acceso, derechos y restricciones de uso) a aplicar. Azure Rights Management (RMS) cifra el documento y este se descifra cuando se valida el acceso de un usuario con permisos.

Azure Information Protection y PowerShell

Es posible modificar la configuración mediante PowerShell (Install-Module -Name AADRM). Por ejemplo añadir un nuevo acceso por dominio a una plantilla.

Connect-AadrmService
#Plantilla donde añadir un nuevo permiso.
$templateId = "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxx"  
#Dominio al que se le da el permiso.
$dominio = "Contoso.com"
$CurrentRightsDefinitions = [array](Get-AadrmTemplateProperty -TemplateId $templateId -RightsDefinitions).RightsDefinitions
$newRule = New-AadrmRightsDefinition -DomainName $dominio -Rights "VIEW", "VIEWRIGHTSDATA", "OBJMODEL"
$CurrentRightsDefinitions = $CurrentRightsDefinitions + $newRule
Set-AadrmTemplateProperty -TemplateId $templateId -RightsDefinition $CurrentRightsDefinitions
Publicado en Azure, PowerShell, Uncategorized | Deja un comentario

Desactivar Alertas en Azure por PowerShell

Desactivar las Alertas de Azure

No hay comando para deshabilitar la alarma; se ha de modificar la alerta con el parámetro DisableRule activo.

$SubscriptionId = "xxxxxxxx-xxxx-xxxxxxxx-xxxxxxxxxx" //Subscription Id
$disable = $true
$resourceGroup = "GroupName"
$alertName = "AlertName"
Add-AzureRmAccount
<# On Automation
#$Conn = Get-AutomationConnection -Name AzureRunAsConnection
#Add-AzureRMAccount -ServicePrincipal -Tenant $Conn.TenantID -ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint
#>
Set-AzureRmContext -SubscriptionId $SubscriptionId
$alert = Get-AzureRmAlertRule -ResourceGroupName $resourceGroup -Name $alertName
if ($alert.Condition.DataSource.MetricName -eq 'GSMT_AvRaW') {
   if ($alert.Description)
   {    
       Write-Output "Add-AzureRmWebtestAlertRule"        
       Add-AzureRmWebtestAlertRule -Name $alert.Name -Location $alert.Location -ResourceGroupName $resourceGroup -TargetResourceUri $alert.Condition.DataSource.ResourceUri -MetricName $alert.Condition.DataSource.MetricName -FailedLocationCount $alert.Condition.FailedLocationCount -WindowSize $alert.Condition.WindowSize -Action $alert.Actions -Description $alert.Description -DisableRule:$disable
   } else {
       Write-Output "Add-AzureRmWebtestAlertRule No Description"        
       Add-AzureRmWebtestAlertRule -Name $alert.Name -Location $alert.Location -ResourceGroupName $resourceGroup -TargetResourceUri $alert.Condition.DataSource.ResourceUri -MetricName 
       $alert.Condition.DataSource.MetricName -FailedLocationCount $alert.Condition.FailedLocationCount -WindowSize $alert.Condition.WindowSize -Action $alert.Actions -DisableRule:$disable
   }
} else { 
   if ($alert.Description)
   {    
       Write-Output "Add-AzureRmMetricAlertRule"       
       Add-AzureRmMetricAlertRule -Name $alert.Name -Location $alert.Location -ResourceGroupName $resourceGroup -TargetResourceId $alert.Condition.DataSource.ResourceUri -MetricName 
       $alert.Condition.DataSource.MetricName -Operator $alert.Condition.OperatorProperty -Threshold $alert.Condition.Threshold -WindowSize $alert.Condition.WindowSize -TimeAggregationOperator 
       $alert.Condition.TimeAggregation -Action $alert.Actions -Description $alert.Description -DisableRule:$disable            
    } else {
       Write-Output "Add-AzureRmMetricAlertRule No Description"                
       Add-AzureRmMetricAlertRule -Name $alert.Name -Location $alert.Location -ResourceGroupName $resourceGroup -TargetResourceId $alert.Condition.DataSource.ResourceUri -MetricName 
       $alert.Condition.DataSource.MetricName -Operator $alert.Condition.OperatorProperty -Threshold $alert.Condition.Threshold -WindowSize $alert.Condition.WindowSize -TimeAggregationOperator 
       $alert.Condition.TimeAggregation -Action $alert.Actions -DisableRule:$disable
    }
}

Desactivar Availability Test dels Application Insights

El paso anterior desactiva la recepción de alarmas; pero estas se acumulan en un buffer (no se descartan). Cuando volvamos activar las alertas; recibiremos las que no recibimos 😦 . En el caso de un webtest de Azure Insights debemos ademas deshabilitarlo mediante Set-AzureRmResource.

    $alertExtended = Get-AzureRmResource -ResourceGroupName $resourceGroup -ResourceName $alertName -ResourceType microsoft.insights/webtests -ExpandProperties
    $properties = $alertExtended.Properties
    $properties.Enabled = !($disable)
    Set-AzureRmResource -ResourceGroupName $alert.ResourceGroupName -ResourceName $alertName -ResourceType microsoft.insights/webtests -PropertyObject $properties -Force
Publicado en Uncategorized | Deja un comentario

Azure Archive Storage

Que es Azure Archive Storage?

El nivel Archive en el Storage nos permite almacenar la información de una manera más económica que la tradicional; a cambio no permite el acceso a la información en tiempo real.
En el Portal de Azure, al entrar en el detalle del blob podemos cambiar el nivel de servicio a Archive.

Cambiar todos los blobs del Contenedor a Nivel de Servicio Archive

Cuando tenemos muchos blobs en el contendor cambiarlo mediante el portal de Azure no es práctico. Este paso lo podemos hacer mediante un script PowerShell.

Add-AzureAccount
$storageAccountName = "<Account Name"
$storageContainerName = "<Container Name>"
$storageKey = "< Storage Key ends with == >"
$storageCtx = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageKey
$blobs = Get-AzureStorageBlob -Container $storageContainerName -Context $storageCtx
foreach ($blob in $blobs) {
     if ($blob.ICloudBlob.Properties.StandardBlobTier -ne "Archive") {
        $blob.ICloudBlob.SetStandardBlobTier("Archive");
     }
}
Publicado en Azure | Deja un comentario

Como mejorar el rendimiento en Azure App Service

Configuración de Infraestructura

  • Activar HTPP 2: El protocolo HTTP 2 aumenta la velocidad de carga de las paginas. Activar en la sección Application settings del App Service.
  • App Service Local Cache: Los App Services utilizan un Azure Storage compartido con el objetivo de poderse escalar verticalmente a múltiples instancias. El problema es que el rendimiento del Azure Storage es menor con respecto al disco local de la instancia. App Service Local Cache permite desplazar la aplicación y sus datos al disco local. Adjunto dos enlaces que aportan más información:

Cache

Cuando los resultados retornados no varían y la obtención de los mismos es costosa; activar un mecanismo de cache es recomendable.

  • Cache a nivel de Pagina con Output Cache: En aplicaciones MVC, cachear el resultado de las paginas web mediante el atributo [OutputCache]. OutputCache utiliza como proveedor de almacenamiento de las respuestas HTTP la memoria de la instancia. Este recurso es limitado en App Services pero es posible usar Redis como proveedor (Proveedor de caché de salida de ASP.NET para Azure Redis Cache). Hay la posiblidad de crear nuestro propio proveedor de OutputCache; así usando FileCache podemos almacenar en disco la cache.
        public class FileCacheOutputCacheProvider : OutputCacheProvider
        {
            static FileCache FileCache { get; set; }
            public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
            {
                var path = "d:\home\site";
                FileCache = new FileCache(path);
                base.Initialize(name, config);
            }
            private String Hash(String key)
            {
                return key.GetHashCode().ToString();
            }
            public override object Add(string key, object entry, DateTime utcExpiry)
            {
                var keyHash = Hash(key);
                // check if cache object already exists
                var results = FileCache.Get(keyHash);
                if (results != null)
                    return results;
                else
                {
                    //create the cache object
                    FileCache.Set(keyHash, entry, new CacheItemPolicy() { AbsoluteExpiration = utcExpiry });                  
                    return entry;
                }
            }
            public override object Get(string key)
            {
    
                return FileCache.Get(Hash(key));
            }
            public override void Remove(string key)
            {
                FileCache.Remove(Hash(key));
            }
            public override void Set(string key, object entry, DateTime utcExpiry)
            {
                FileCache.Set(Hash(key), entry, new CacheItemPolicy() { AbsoluteExpiration = utcExpiry });
            }
        }
    
  • Cache a nivel de Negocio o Repositorio: usando en nuestro código un patrón de cache.
    Por ejemplo usando MemoryCache.

    public class CachedDescriptionService: DescriptionService
    {
         private Cache<String> cacheName = new Cache<String>();
         public override int NameToId(String name)
         {
             return cacheName.getItem(name, () => base.NameToId(name));
         }
    }
    

    Clase base de cache:

        public class Cache<T>
        {
            private MemoryCache _cache = new MemoryCache("MemoryCache");
    
            public T getItem(String key, Func<T> getItemBase) 
            {
                var item = _cache.Get(key);
                if (item == null)
                {
                    item = getItemBase();
                    if (item == null) return default(T);
                    _cache.Set(key, item, new CacheItemPolicy());
                }
                return (T) item;
            }
    
        }
    

    También podríamos haber usado FileCache como en el caso anterior.

Publicado en Azure | Deja un comentario

Securizar y reutilizar parámetros en runbooks

Parámetros en el script

Los comandos de PowerShell que ejecutamos en el Azure Automation necesitan de parámetros (usuarios, passwords, claves,…). Podemos almacenar el valor de estos parámetros en el Azure Automation, en lugar de ponerlos directamente en el script. Las ventajas principales son:

  • Reutilización: Si un día cambian únicamente se modifican en un único punto.
  • Seguridad: se guardan cifrados y no se muestra su valor en el script.

Credenciales

Permite añadir una credencial con usuario y un password.

  • Añadir la credencial en el Portal de Azure.

    Add Credential on Automation Account

  • Acceder en el script
    $Credencial = Get-AutomationPSCredential -Name 'acceso'
    #Obtiene el Usuario de la Credencial
    $usuario = $Credencial.UserName
    #Obtiene el password cifrado
    $password = $Credencial.Password
    #Obtiene el password descrifrado
    $password = $Credencial.GetNetworkCredential().Password
    

Variables

Permite añadir un clave.

Publicado en Azure, PowerShell | Deja un comentario

Hybrid Runbook Worker y Plan de Mantenimiento de SQL Azure

Que es Hybrid Runbook Worker?

Las tareas que se ejecutan en el Azure Automation se ejecutan en Azure Sandbox y tienen un timeout de ejecución de 3 horas. Con Hybrid Runbook Worker podemos ejecutar las tareas en una maquina física o virtual. Azure Automation tiene el script de PowerShell que envia a la máquina para su ejecución. Esta máquina debe agruparse en un grupo donde pueden añadirse más nodos/máquinas de ejecución de tareas.

Plan de Mantenimiento de SQL Azure

SQL Azure no dispone de plan de mantenimiento; podemos realizar un script de TSQL para que realice el manteniento (por ejemplo reconstrucción de indices). Si la base de datos es de gran tamaño es posible que esta ejecución dure más de 3 horas; con lo que si no utilizamos Hybrid Runbook Worker nuestro plan se abortaría.

  • PowerShell que realiza un plan de Mantenimiento. Este script ejecuta un stored procedure que realiza nuestro plan de mantenimiento.
    $serverName = "serverName.database.windows.net"
    $databaseOriginal = "DatabaseName"
    $databaseLogin = "user"
    $databasePassword="password"
    $SQLOutput = $(Invoke-Sqlcmd -ServerInstance $serverName -Username $databaseLogin -Password $databasePassword -Database $databaseOriginal -Query "exec [dbo].[RebuildInxex]" -QueryTimeout (8*60*60) -ConnectionTimeout 60 -Verbose) 4>&1
     
    Write-Output $SQLOutput
    
    $SQLOutput = $(Invoke-Sqlcmd -ServerInstance $serverName -Username $databaseLogin -Password $databasePassword -Database $databaseOriginal -Query "exec [dbo].[RebuildStadistics]" -QueryTimeout (8*60*60) -ConnectionTimeout 60 -Verbose) 4>&1
    
    Write-Output $SQLOutput
    
    
  • SQL Ejemplo de script que reindexa la base de datos
    CREATE PROCEDURE [dbo].[RebuildInxex]
    AS
    BEGIN
    
    	DECLARE @IndexName varchar(250)
    	DECLARE @TableName varchar(250)
    	DECLARE @Fragmentation float
    
    	DECLARE IndexFragmented CURSOR FOR
    	--- For Instance, indexes fragmented over 20 percent
    		(
    		SELECT name, OBJECT_NAME(a.object_id), a.avg_fragmentation_in_percent 
    		FROM sys.dm_db_index_physical_stats (
    			DB_ID(DB_NAME())
    			, NULL
    			, NULL
    			, NULL
    			, NULL) AS a
    		JOIN sys.indexes AS b 
    		ON a.object_id = b.object_id AND a.index_id = b.index_id
    		WHERE avg_fragmentation_in_percent >20)
    
    	OPEN IndexFragmented
    	FETCH NEXT FROM IndexFragmented INTO @IndexName, @TableName, @Fragmentation
    	WHILE @@FETCH_STATUS = 0
    	BEGIN
    		PRINT 'Rebuilding ' + @IndexName + ' ON ' + @TableName + ' (' + CONVERT(VARCHAR(50), @Fragmentation) + '% Current Fragmentation) ...'
    	
    		EXEC('ALTER INDEX ' + @IndexName + ' ON ' + @TableName + ' REBUILD WITH (STATISTICS_NORECOMPUTE = ON, ONLINE=ON)')
    
    		FETCH NEXT FROM IndexFragmented INTO @IndexName, @TableName, @Fragmentation
    
    	END
    
    	CLOSE IndexFragmented
    	DEALLOCATE IndexFragmented
    
    END
    GO
    
  • SQL Ejemplo de script que actualiza las estadísticas de la base de datos
    CREATE PROCEDURE [dbo].[RebuildStadistics]
    AS
    BEGIN
    
    	DECLARE @StatName varchar(250)
    	DECLARE @TableName varchar(250)
    
    	DECLARE stadistics CURSOR FOR
    			select A.name StatName, B.name TableName 
                from sys.stats A 
                inner join sys.tables B on a.object_id = b.object_id
                cross apply sys.dm_db_stats_properties(a.object_id, a.stats_id)
                where (auto_created =1 or user_created=1 ) and modification_counter >0;
    
    	OPEN stadistics
    	FETCH NEXT FROM stadistics INTO @StatName, @TableName
    	WHILE @@FETCH_STATUS = 0
    	BEGIN
    
    		PRINT 'Update Statics ' + @StatName + ' ON ' + @TableName + '...'
    		EXEC('UPDATE STATISTICS ' + @TableName + ' (' + @StatName + ') WITH FULLSCAN')
    		FETCH NEXT FROM stadistics INTO @StatName, @TableName
    
    	END
    
    	CLOSE stadistics
    	DEALLOCATE stadistics
    
    END
    GO
    

    Instalar Hybrid Runbook Worker

    • En la siguiente entrada se detalla el proceso de instalación. Podemos crear una maquina virtual en Azure y realizar los pasos descritos.
    • También hay que tener en cuenta que hay que instalar el modulo SQLServer para ejecutar el comando Invoke-Sqlcmd en PowerShell.
      install-module -Name "SQLServer"
      

    Ejecutar los Runbooks en Hybrid Runbook Worker

    • Manualmente:
    • Programado (esta opción aparece al activar Hybrid Runbook Worker 😉 ):

    Notas sobre Hybrid Runbook Worker

    • Aunque la tarea se acaba ejecutando en otra maquina, aunque no tenga mucho sentido el importe facturado en el Automation incluye ese tiempo de ejecución. No discrimina si se ejecuta en un nodo nuestro. 😦
    • El Hybrid Runbook Worker sólo puede ser usado por un Automation.
    • Automation contra recursos de Azure:
      Al ejecutar el típico script de conexión a recursos de Azure se obtiene el siguiente error Add-AzureRMAccount : No certificate was found in the certificate store with thumbprint. Esto ocurre porque no tenemos instalado el certificado de conexión en la máquina.

      $Conn = Get-AutomationConnection -Name AzureRunAsConnection
      Add-AzureRMAccount -ServicePrincipal -Tenant $Conn.TenantID -ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint
      

      Se ha de ejecutar el siguiente script para instalar el certificado en la maquina de ejecución; de esta manera nuestro script de Automation funcionará normalmente.

      <#PSScriptInfo
      .VERSION 1.0
      .GUID 3a796b9a-623d-499d-86c8-c249f10a6986
      .AUTHOR Azure Automation Team
      .COMPANYNAME Microsoft
      .COPYRIGHT
      .TAGS Azure Automation
      .LICENSEURI
      .PROJECTURI
      .ICONURI
      .EXTERNALMODULEDEPENDENCIES
      .REQUIREDSCRIPTS
      .EXTERNALSCRIPTDEPENDENCIES
      .RELEASENOTES
      #>
      
      <#
      .SYNOPSIS
      Exports the Run As certificate from an Azure Automation account to a hybrid worker in that account.
      
      .DESCRIPTION
      This runbook exports the Run As certificate from an Azure Automation account to a hybrid worker in that account.
      Run this runbook in the hybrid worker where you want the certificate installed.
      This allows the use of the AzureRunAsConnection to authenticate to Azure and manage Azure resources from runbooks running in the hybrid worker.
      
      .EXAMPLE
      .\Export-RunAsCertificateToHybridWorker
      
      .NOTES
      AUTHOR: Azure Automation Team
      LASTEDIT: 2016.10.13
      #>
      
      # Generate the password used for this certificate
      Add-Type -AssemblyName System.Web -ErrorAction SilentlyContinue | Out-Null
      $Password = [System.Web.Security.Membership]::GeneratePassword(25, 10)
      
      # Stop on errors
      $ErrorActionPreference = 'stop'
      
      # Get the management certificate that will be used to make calls into Azure Service Management resources
      $RunAsCert = Get-AutomationCertificate -Name "AzureRunAsCertificate"
      
      # location to store temporary certificate in the Automation service host
      $CertPath = Join-Path $env:temp  "AzureRunAsCertificate.pfx"
      
      # Save the certificate
      $Cert = $RunAsCert.Export("pfx",$Password)
      Set-Content -Value $Cert -Path $CertPath -Force -Encoding Byte | Write-Verbose
      
      Write-Output ("Importing certificate into $env:computername local machine root store from " + $CertPath)
      $SecurePassword = ConvertTo-SecureString $Password -AsPlainText -Force
      Import-PfxCertificate -FilePath $CertPath -CertStoreLocation Cert:\LocalMachine\My -Password $SecurePassword -Exportable | Write-Verbose
      
      # Test that authentication to Azure Resource Manager is working
      $RunAsConnection = Get-AutomationConnection -Name "AzureRunAsConnection"
      
      Connect-AzureRmAccount `
          -ServicePrincipal `
          -TenantId $RunAsConnection.TenantId `
          -ApplicationId $RunAsConnection.ApplicationId `
          -CertificateThumbprint $RunAsConnection.CertificateThumbprint | Write-Verbose
      
      Set-AzureRmContext -SubscriptionId $RunAsConnection.SubscriptionID | Write-Verbose
      
      # List automation accounts to confirm Azure Resource Manager calls are working
      Get-AzureRmAutomationAccount | Select-Object AutomationAccountName
      
Publicado en Azure, PowerShell, Sql Azure | Deja un comentario