sábado, 3 de enero de 2015

IntelliTrace Collector–Sharepoint 2013

Siempre es útil debuggear apps en producción, pero no siempre nos dejan instalar Visual Studio para hacer el debugging. En estos casos podemos usar IntelliTrace collector para guardar información de diagnóstico en un Intellitrace log file (.iTrace files). Nos permite registrar que pasa en nuestra app sin instalar Visual Studio o hacer cambios en el ambiente.

image

Folder: C:\IntelliTraceCollector

Abro una consola de powershell con permisos de administrador, y ejecuto lo siguiente:

cd C:\IntelliTraceCollector

expand /f:* IntelliTraceCollection.cab. C:\IntelliTraceCollector

image

Ejecuto el siguiente comando en la consola de powershell:
Import-Module C:\IntelliTraceCollector\Microsoft.VisualStudio.IntelliTrace.PowerShell.dll

image

Para saber sobre que App Pool voy a ejecutar el tracer, ejecuto el siguiente comando:

[Microsoft.SharePoint.Administration.SPWebService]::ContentService.ApplicationPools | ft Name

Este nos retorna todos los app pools de los web application. En el caso que quieras debuggear alguna feature del Central Administration, ejecuta el siguiente comando:

[Microsoft.SharePoint.Administration.SPWebService]::AdministrationService.ApplicationPools | ft Name

El mismo nos retorna el nombre del pool del Central Administration.

Ahora ejecuto lo siguiente:

Start-IntelliTraceCollection "DefaultAppPool (6.20.2014 10.27.31 AM)" "C:\IntelliTraceCollector\collection_plan.ASP.NET.default.xml" "C:\IntelliTraceCollector"

image

Ahora ejecuto el siguiente comando

Get-IntelliTraceCollectionStatus

El cual nos lista todos los App Pool y el estado del trace.

image

collection_plan.ASP.NET.default.xml: Colecciona solo IntelliTrace events y SharePoint events, incluyendo exceptions, database calls, y Web server requests. Si queres tener un trace más detallado tenes que ejecutarlo con collection_plan.ASP.NET.trace.xml

DefaultAppPool (6.20.2014 10.27.31 AM) –> es el nombre del Pool

C:\IntelliTraceCollector –> es el output de salida del archivo iTrace

Después de haber verificado que está OK el trace , reproduzco el problema, y recorro un poco el sitio de Sharepoint para coleccionar datos.

Una vez que reproduje el error, ejecuto el siguiente comando:

Checkpoint-IntelliTraceCollection "DefaultAppPool (6.20.2014 10.27.31 AM)"

image

Para finalizar el trace, ejecuto el comando:

Stop-IntelliTraceCollection "DefaultAppPool (6.20.2014 10.27.31 AM)"

Get-IntelliTraceCollectionStatus

En el directorio, está el archivo iTrace. El cual se puede abrir con Visual Studio 2013.

image

Después puedo recorrer el trace

image

Por ejemplo, puedes agregar el correlation ID de la excepción de Sharepoint para buscar la sección del trace que le corresponde.

Puedes ver las excepciones, web request, la información del sistema en el momento que ejecutaste el trace, la lista de threads que se dispararon y los modulos que se cargaron (.dll)

image

image

image

image

image

Para mayor información: http://msdn.microsoft.com/en-us/library/vstudio/hh398365.aspx

http://blogs.msdn.com/b/visualstudioalm/archive/2012/12/11/debugging-sharepoint-apps-with-intellitrace-in-visual-studio.aspx

jueves, 1 de enero de 2015

Troubleshooting problemas de performance de SQL Server para Sharepoint–Parte 1

Voy a arrancar una serie de post relacionados al troubleshooting de problemas de performance de SQL Server para Sharepoint. Anteriormente había creado una serie de post sobre las mejores prácticas de SQL Server para Sharepoint:

Parte 1: Optimización de los servidores de SQL Server

Parte 2: Optimización de la instancia de SQL Server

Parte 3: Mantenimiento de SQL Server

En este caso, me voy a enfocar especificamente en los problemas de performance (lentitud de consultas, consumo alto de RAM o CPU, etc).

Hoy voy a revisar el parámetro “Page Life Expectancy” (PLE). El cual es el tiempo esperado, en segundos, que una página de un data file es sacada (pushed out) del buffer pool (in-memory cache de data files pages) para hacer espacio para otra página diferente de un data file. En resumen, indica la presión sobre el buffer pool para leer páginas de data files. Un número alto es mejor, ya que si no hay memoria suficiente en el sistema, se sacan más rapidamente las páginas del buffer pool.

Microsoft recomendaba que este contador supere los 300 ms (>). Si nuestro ambiente. nos da que PLE ronda los 300 ms, significa que el buffer pool completo se saca (flushed) y se leer de forma completa cada 5 minutos. Este valor fue cambiando con los sistemas actuales, que tienen muchos GB de RAM.

La fórmula correcta para evaluar este parámetro es: ( Buffer pool memory in GB / 4 ) x 300

Con la siguiente query, puedo saber el valor de este contador.

SELECT object_name, counter_name, cntr_value
FROM sys.dm_os_performance_counters
WHERE [object_name] LIKE '%Buffer Manager%'
AND [counter_name] = 'Page life expectancy'

image

Recomiendo ejecutar este comando cada 6 horas, para tener una certeza más correcta de este comando. Ya que hay operaciones tales como DBCC CHECKDB o index rebuilds pueden afectar el valor de este contador.

En este caso, ejecuté el comando sobre un servidor con 16 GB de RAM (SQL Server 2012).

Para saber el tamaño del buffer pool memory, ejecuto el siguiente comando

select DB_NAME(database_id) Database_Name, count(*) Pages
from sys.dm_os_buffer_descriptors
group by database_id 
order by Pages desc

El cual nos devuelve todas las bases de datos que tienen páginas en el buffer

image

Un punto importante, para ver mediante esta consulta, es que nos da una idea de que bases de datos tienen más páginas en el buffer, con lo cual nos da un parámetro para saber que bases de Sharepoint son las que más actividad tienen. En la imagen superior, la base de contenido “WSS_Content_SPS_2” tiene casi 9 GB de datos cargados en la RAM (1146634*8/1024), lo cual es demasiado para una base. En este caso recomiendo crear otra base de contenidos y mover algunos sites collection a esa base, para bajar este número. Más adelante daré otros tips para subir el PLE lo cual puede mejorar la cantidad de páginas para esta base de contenido.

La suma de todas las páginas (de todas las bases) es : 1347406

(1347406*8)/1024 =~ 10526.61 –> 10.28 GB.

Agrego este valor a la fórmula anterior, y evaluo el resultado

(10.28GB /4) *300= 771 lo cual es un valor adecuado para el contador PLE.

Si este contador nos da demasiado bajo, podemos revisar lo siguiente:

  • Índices no actualizados
  • Estadísticas no actualizados
  • Fragmentación de datafiles

La base de search en general tiene bastantes páginas en el buffer, ya que en general se obtienen datos random de las queries.

Una manera de revisar que queries son las que causan más lecturas, es ejecutando la siguiente query.

SELECT TOP 25 cp.usecounts AS [execution_count]
      ,qs.total_worker_time AS CPU
      ,qs.total_elapsed_time AS ELAPSED_TIME
      ,qs.total_logical_reads AS LOGICAL_READS
      ,qs.total_logical_writes AS LOGICAL_WRITES
      ,qs.total_physical_reads AS PHYSICAL_READS
      ,SUBSTRING(text,
                   CASE WHEN statement_start_offset = 0
                          OR statement_start_offset IS NULL 
                           THEN 1 
                           ELSE statement_start_offset/2 + 1 END,
                   CASE WHEN statement_end_offset = 0
                          OR statement_end_offset = -1 
                          OR statement_end_offset IS NULL 
                           THEN LEN(text) 
                           ELSE statement_end_offset/2 END -
                     CASE WHEN statement_start_offset = 0
                            OR statement_start_offset IS NULL
                             THEN 1 
                             ELSE statement_start_offset/2  END + 1
                  )  AS [Statement]       
FROM sys.dm_exec_query_stats qs 
   join sys.dm_exec_cached_plans cp on qs.plan_handle = cp.plan_handle
   CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
ORDER BY qs.total_physical_reads DESC;

En este caso, veo que la query

SELECT          SUBSTRING(ADS.Content, @Offset, @Length)      FROM          TVF_AllDocStreams_SiteDocIdInternalVersion(@SiteId, @DocId, @InternalVersion) AS ADS     

image

AllDocStreams es la tabla donde se almacenan los documentos de Sharepoint.

Otra query para saber el tamaño en MB de las páginas que están en el buffer pool

SELECT count(*)*8/1024 AS 'Data Cache Size(MB)' ,CASE database_id WHEN 32767 THEN 'RESOURCEDB' ELSE db_name(database_id) END AS 'DatabaseName' FROM sys.dm_os_buffer_descriptors GROUP BY db_name(database_id) ,database_id ORDER BY 'Data Cache Size(MB)' DESC

Hay mucha información sobre PLE en Internet, la idea es mostrarle un par de consultas y parámetros para ayudarlos en algún problema que tengan con su SQL de Sharepoint.

Popups (SP.UI.ModalDialog.showModalDialog) en una página WIKI en Sharepoint 2013

Creo una página Wiki

image

Inserto un Script Editor (Embed Code)

image

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<script language="javascript">
 
  function openBasicDialog(tUrl, tTitle) {
         var options = {
             url: tUrl,
             title: tTitle
         };
         SP.UI.ModalDialog.showModalDialog(options);
     }
    
</script>
</head>
<body>
<input type="button" value="Página de Microsoft" onclick="openBasicDialog('http://www.microsoft.com','Microsoft Page');"/>
</body>
</html>

image

Al hacer click en el botón, me lanza un PopUp modal

image

Este script también nos permite mostrar el formulario de NewItems para Listas o el formulario de Upload para Librerias.

Por ej: si utilizo la url de upload de una Librería con el parámetro IsDlg, el cual permite mostrar un form preparado para PopUp (sin barras de desplazamiento, tamaño más reducido, etc). Por ejemplo la siguiente URL

http://URLSite/_layouts/15/Upload.aspx?List={ID_Lista}&RootFolder=&IsDlg=1

image

Entonces lo único que debo hacer es cambiar en el button, la url

<input type="button" value="Agregar Nuevo Documento" onclick="openBasicDialog('http://URLSite/_layouts/15/Upload.aspx?List={ID_Lista}&RootFolder=&IsDlg=1','Librería de Documentos');"/>

Lo cual resulta en

image

image

lunes, 8 de diciembre de 2014

Simple tip LogParser: obtener todos los usuarios que accedieron a la home page de tu sitio

SELECT DISTINCT cs-username AS Hits FROM 'Folder de tus logs\*log' where cs-uri-stem like '%nombreSiteCollection/SitePages/Inicio.aspx%'

Reemplaza 'Folder de tus logs\*log' con la dirección donde están los logs de tu IIS, y reemplaza nombreSiteCollection con la url del site donde quieres hacer la consulta.

Usa Log Parser Studio para realizar las queries.

https://gallery.technet.microsoft.com/office/Log-Parser-Studio-cd458765

Problemas de versiones al tratar de obtener datos del tenant de Office 365

Al tratar de ejecutar la consola de .NET, me lanzaba el siguiente error al iniciar la app.

image

An unhandled exception of type 'System.Security.VerificationException' occurred in Office365.exe

Additional information: Method Microsoft.SharePoint.Client.ClientRuntimeContext.Load: type argument 'Microsoft.Online.SharePoint.TenantAdministration.SPOSitePropertiesEnumerable' violates the constraint of type parameter 'T'.

Revisando las versiones de las dll, veo que las versiones de Microsoft.SharePoint.Client.Runtime y Microsoft.SharePoint.Client era la 16.0.0.0

image

En cambio la versión de la dll Microsoft.Online.SharePoint.Client.Tenant era la 15.0.4641.1002

image

Para solucionarlo, la mejor manera es utilizar el proyecto https://github.com/OfficeDev/PnP  (Office365 Developer Patterns and Practices) para descargar las dlls correctas.

Cuando bajo el proyecto y los descomprimo, veo que tiene dos carpetas de versiones. Para Office 365 uso la versión 16

image

Recuerda setear en el proyecto, la propiedad “Copy Local” a true para las tres librerías.

image

lunes, 1 de diciembre de 2014

Customize el Public WebSite de Office 365

Cuando compramos una subscripción de Office 365, la misma nos permite crear un sitio llamado “Public Website” (por default crea uno al iniciar la subscripción), el cual permite ser un lugar donde se puede mostrar lo que se  ofrece, información de contacto, etc, todo lo relacionado a información pública. Una de las características de este site es que permite customizar muy facilmente el mismo.

image

image

En la home principal, podemos ver un tab adicional llamado “Sitio”

Ribbon on public website Site tab, showing buttons for Change the Look, Edit Title, and Change Logo

Por ejemplo algunas configuraciones útiles:

  • Ocultar el search box del sitio

image

  • Editar el css de forma interactiva

image

  • Cambiar elementos del sitio (footer, header, etc)

image

image

  • Editar el menu del sitio

image

  • Cambiar el logo

image

  • Cambiar los elementos del sitio

image

image

Para mayor información puede consultar el siguiente link: https://support.office.com/en-us/article/Public-Website-help-for-Office-365-d63eadcf-2642-44ae-93cf-a55642f9d0f7?ui=en-US&rs=en-US&ad=US

sábado, 29 de noviembre de 2014

Agregar/Actualizar un campo Date mediante client object

Supongamos que tenemos una variable llamada submital que es de tipo Date Time. La parte en amarillo es la parte más importanet. Convertitmos la fecha en un formato ISO8601

using (ClientContext clientContext = new ClientContext(urlSharepointList))
{
    clientContext.AuthenticationMode = ClientAuthenticationMode.Default;
    Microsoft.SharePoint.Client.List list = clientContext.Web.Lists.GetByTitle("CRM");
    DateTime NewSubmittal = new DateTime();
    ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
    ListItem newItem = list.AddItem(itemCreateInfo);
    newItem["Title"] = opportunity.Name;
   newItem["Submital"] = string.Format("{0:0000}-{1:00}-{2:00}T{3:00}:{4:00}:{5:00}Z",
                                        NewSubmittal.Year,
                                        NewSubmittal.Month,
                                        NewSubmittal.Day,
                                        NewSubmittal.Hour,
                                        NewSubmittal.Minute,
                                        NewSubmittal.Second);
   
   
    newItem.Update();
    clientContext.ExecuteQuery();

}

Más post relacionados a ISO8601: http://todosharepoint.blogspot.com.ar/search/label/ISO%208601

martes, 25 de noviembre de 2014

The request uses too many resources–CSOM

Al tratar de insertar un item en una lista de Sharepoint 2013, me lanzaba el error: The request uses too many resources

{Microsoft.SharePoint.Client.ServerException: The request uses too many resources.
   at Microsoft.SharePoint.Client.ClientRequest.ProcessResponseStream(Stream responseStream)
   at Microsoft.SharePoint.Client.ClientRequest.ProcessResponse()
   at Microsoft.SharePoint.Client.ClientRequest.ExecuteQueryToServer(ChunkStringBuilder sb)
   at Microsoft.SharePoint.Client.ClientRequest.ExecuteQuery()
   at Microsoft.SharePoint.Client.ClientRuntimeContext.ExecuteQuery()
   at Microsoft.SharePoint.Client.ClientContext.ExecuteQuery()

hrresult --> –2146233088

Esto se debe a que Sharepoint setea el número máximo de object-paths que pueden ser usados en un request a 256. Un “Object-Path” trackea cómo un objeto cliente es creado en la clase “ClientRuntimeContext”, de esta manera el objeto puede crearse en el server. Cada SP-Object (por ejemplo un site) genera un object-path-object en el request. Es decir, en palabras simples setea un límite de 256 objetos en una llamada ExecuteQueryAsync.

Para solucionarlo, puedo hacer dos cosas: reducir los object-paths en el request, por ejemplo dividiendo la consulta en consultas más pequeñas o cambiando la propiedad maxObjectPaths.

$webApp = Get-SPWebApplication "htt://ur_webapplication"
$webApp.ClientCallableSettings.MaxObjectPaths = 5000
$webApp.Update()

domingo, 9 de noviembre de 2014

Tip: 5 causas de performance lenta

  • Navegación estructural: por ejemplo si tienes varios sub-sitios (deep navigation), y deseas mostrarlos todos en el menú superior. Es este caso puedes utilizar Managed Navigation para mejorar la performance. Más info en el siguiente link

image

  • Content Rollup: en general son queries muy costosas. Ej: recorrer cada sitio, cada listas y renderizar algo de contenido.

image 

  • Archivos grandes: Ej: tener imágenes grandes o videos, archivos .js gigantes.
  • Tener muchos request: .js, .css e imágenes.
  • Tener muchos web parts en la página:

Simple tip para verificar la performance de nuestro servidor: response headers de la solicitud de una página

Cuando realizamos una solicitud a Sharepoint de una página, en el header de la solicitud de HTTP podemos ver varios datos útiles relacionados a la performance de la plataforma.

Para verificarlas podemos usar las herramientas de desarrollo de IE, fiddler u otra herramienta similar (HTTPWatch). En el IE presionamos F12, y elegimos la sección de Network, y presionamos Play.

image

Realizamos un refresh de la página, y en la solicitud principal, hacemos doble click sobre la misma.

image

image

En los headers de la respuesta tenemos, algunas claves útiles, tales como:

SPRequestDuration: tiene un valor de 2805 milisegundos, lo cual quiere decir que Sharepoint tardo ese tiempo para procesar la solicitud (página) del lado del servidor.  Este header está en cada página de Sharepoint. Tiempos excesivos indican que se hizo mucho trabajo para renderizar la página o el servidor está unhealthy (en español sería “poco sano”). Para verificar si el servidor está unhealthy, Sharepoint también otra header para verificar, “X-SharepointHealthScore”, este tiene un valor entre 0 y 10. 10 es cuando está unhealthy (algún problema) o está sobrecargado (high load y throttling request para mantener ell throughput). Más info en el siguiente link

image

Si este header tiene 0 y tienes alta latencia en el SPRequestDuration, claramente Sharepoint está haciendo mucho trabajo para renderizar la página.

SPIisLatency: es el queue time de la solicitud. Cuando un servidor está sobrecargado, empieza a “encolar” las solicitudes.

miércoles, 5 de noviembre de 2014

Variable de configuración del workflow de aprobación: “CancelonRejection”

La variable “CancelonRejection” define si se cancela el workflow en el PRIMER RECHAZO de una tarea de un workflow.

En un workflow Out the Box, esta configuración se puede hacer desde el mismo UI

image

En cambio cuando se hace un workflow custom con Sharepoint Designer, se tiene que setear la variable mediante la action “Set Variable”

image

Si se revisa la conducta de una tarea en el workflow, encontrarán que al completar una tarea, hay un pequeño IF

image

Cancelation es igual a Yes, se finaliza el proceso de tareas.

image

miércoles, 22 de octubre de 2014

Error al borrar un content type “The content type is in use.”

Al trata de borrar un content type, me lanzaba el error: Sorry, something went wrong, The content type is in use.

image

Para poder eliminar un content type, revisa lo siguiente:

  • Papelera de reciclaje: busca en la papelera (primer y segundo nivel) si hay algún item que tenga relación con el content type.

_layouts/15/AdminRecycleBin.aspx

_layouts/15/AdminRecycleBin.aspx?View=2

  • Listas y Librerías: busca si no hay alguna lista o librería que tenga asociado este content type.

image

sábado, 18 de octubre de 2014

Storage SQL Server capacity planning para Sharepoint 2013

En general para Sharepoint 2010 se usaba la fórmula:

  • Crawl: 0.046 × (sum of content databases)
  • Property: 0.015 × (sum of content databases)

Pero para 2013, no tenemos la base de Property, ahora tenemos 4 bases dedicadas para el servicio de Search:

  • Search Administration: The Search Administration database hosts the Search service application configuration and access control list (ACL) for the crawl component.

  • Analytics Reporting: The Analytics Reporting database stores the results for usage analysis reports and extracts information from the Link database when needed.

  • Crawl: The Crawl database stores the state of the crawled data and the crawl history.

  • Link: The Link database stores the information that is extracted by the content processing component and the click through information.

image

En general se recomienda la siguiente tabla

image

Cómo pueden ver la de analytics depende mucho del uso de la plataforma y la configuración de retención. Por ej: con 14 días de retención, más o menos se llega a los 8 GB de datos.

Es posible limitar en la base de analitycs algunos componentes de Analytics a un tamaño específico. Ej: page request

$SPUsageDefinition = Get-SPUsageDefinition -Identity "Page Requests"
$SPUsageDefinition.MaxTotalSizeInBytes = 12884901888
$SPUsageDefinition.Update()

Links útiles

http://technet.microsoft.com/en-us/library/ff608068(v=office.15).aspx

http://sharepoint2013dbdocs.codeplex.com/

http://technet.microsoft.com/en-us/library/cc298801(v=office.15).aspx