Configuration du suivi de workflows avec le SQLTrackingService
Date de publication : 20/10/2008 , Date de mise à jour : 20/10/2008
Par
Dieudonne N'Tamack (dnt91) (Blog)
0. Mise en place du service SQLTrackingService
I. Utilisation du service SQLTrackingService dans nos applications
I-A. Créer des profils de suivi
II. Conclusion
WF est livré avec un service de Tracking qui permet d'enregistrer les données de suivi directement depuis une base de données SQL Server.
0. Mise en place du service SQLTrackingService
Pour mettre en place ce service, il nous faut au préalable créer une base de données :
Ensuite, il nous faut récupérer et exécuter les scripts livrés avec le Framework 3.0 ; ces derniers se trouvent ici > C:\Windows\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\EN (remplacer éventuellement EN par FR).
Commençons par exécuter le script Tracking_Schema.sql ; Ce dernier va créer toutes les tables & vues nécessaires.
Ensuite exécutons le script Tracking_Logic.sql ; ce dernier va créer toutes les procédures stockées permettant d'interagir directement avec la base de données de Tracking.
Ca y'est, c'est terminé !
Maintenant, il ne nous reste plus qu'à voir comment utiliser ce service depuis notre workflow.
I. Utilisation du service SQLTrackingService dans nos applications
Pour cela, il nous suffit de rajouter un fichier de configuration à notre projet de workflow,
Et d'y rajouter les entrées suivantes, en fonction de vos informations de connexion :
< ? xml version= " 1.0 " encoding= " utf-8 " ? >
< configuration>
< connectionStrings>
< add name= " SQLTrackingService " connectionString= " Data Source=.;Initial Catalog=WFTrackingDB;Integrated Security=True " / >
< / connectionStrings>
< / configuration>
|
Puis d'ajouter le service de Tracking dans notre code, comme ceci :
[ autres directives using ]
using System. Configuration;
using System. Workflow. Runtime. Tracking;
namespace Coforcert. WF. Certif. WFChanges {
class Program {
static void Main (string [ ] args) {
string connectionString = ConfigurationManager. ConnectionStrings[ " SQLTrackingService " ] . ConnectionString;
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime ())
{
workflowRuntime. AddService (new SqlTrackingService (connectionString));
[ Le reste du code ici]
Console. Read ();
}
}
}
|
Si vous exécutez le code, puis que vous analysez vos tables, vous verrez que ces dernières comportent un certain nombre d'informations.
Jusqu'à présent, WF enregistre toutes les données concernant les actions de nos utilisateurs, nos workflow et nos activités ; cependant, nous pouvons décider par exemple de ne conserver qu'un sous ensemble de ces informations ; pour cela, nous allons utiliser les profils de suivi ou Tracking Profiles.
I-A. Créer des profils de suivi
Les profils de suivi vont donc nous permettre de configurer notre service de Tracking pour n'enregistrer qu'un sous ensemble des informations que WF peut analyser dans notre datastore.
Pour cela, nous allons travailler essentiellement avec 3 objets : le TrackingProfile, le {Activity|User|Workflow}TrackingLocation et enfin le {Activity|User|Workflow}TrackPoint.
Le TrackingProfile va représenter notre profil à proprement parlé.
Le TrackingLocation va nous permettre de définir ce que nous voulons enregistrer ; par exemple, l'exemple suivant précise que nous ne souhaitons enregistrer que les activités qui sont en cours d'exécution ou qui sont fermées.
ActivityTrackingLocation activityLocation = new ActivityTrackingLocation (typeof (Activity));
activityLocation. ExecutionStatusEvents. Add (ActivityExecutionStatus. Executing);
activityLocation. ExecutionStatusEvents. Add (ActivityExecutionStatus. Closed);
|
Le TrackPoint quant à lui va être chargé de rassembler les TrackingLocation en vue de les transmettre au TrackingProfile, par exemple comme ci-dessous
ActivityTrackPoint activityPoint = new ActivityTrackPoint ();
activityPoint. MatchingLocations. Add (activityLocation);
Profile. ActivityTrackPoints. Add (activityPoint);
|
Voici le code complet de notre méthode de création de profil.
static void CreateTrackingProfile (out TrackingProfile Profile) {
Profile = new TrackingProfile ();
Profile. Version = new Version (" 1.0.0.0 " );
ActivityTrackingLocation activityLocation = new
ActivityTrackingLocation (typeof (Activity));
activityLocation. MatchDerivedTypes = true ;
activityLocation. ExecutionStatusEvents. Add (
ActivityExecutionStatus. Executing);
activityLocation. ExecutionStatusEvents. Add (
ActivityExecutionStatus. Closed);
ActivityTrackPoint activityPoint = new ActivityTrackPoint ();
activityPoint. MatchingLocations. Add (activityLocation);
Profile. ActivityTrackPoints. Add (activityPoint);
}
|
De même, les profils sont stockés en base.
Si vous observez les procédures stockées créées via les scripts fournis pour le service SQLTracking, vous remarquerez la présence de 2 procédures stockées, UpdateDefaultTrackingProfile et UpdateTrackingProfile, indiquant la présence de 2 tables pour gérer les informations de profil (DefaultTrackingProfile pour gérer le profil par défaut et TrackingProfile pour gérer les autres profils).
Il nous faut donc à présent enregistrer notre profil dans la base de données.
Malheureusement, WF ne fournit pas de structure prête à l'emploi pour réaliser ces actions, nous allons donc devoir utiliser nos bonnes veilles méthodes Ado.net.
Voici le code qui réalise ces opérations.
static void UpdateTrackingProfile (
TrackingProfile Profile, string ConnectionString) {
#region Sérialisation de notre Profil
string trackingprofile = string . Empty;
TrackingProfileSerializer serializer = new TrackingProfileSerializer ();
using (StringWriter writer = new StringWriter (
new StringBuilder (), CultureInfo. InvariantCulture)){
serializer. Serialize (writer, Profile);
trackingprofile = writer. ToString ();
}
#endregion
#region Enregistrement des données dans la base
if (string . IsNullOrEmpty (ConnectionString))
throw new Exception (" la chaine de connexion ne peut être vide " );
using (SqlConnection connection = new SqlConnection (ConnectionString)) {
SqlCommand uspUpdate =
new SqlCommand (" dbo.UpdateTrackingProfile " , connection);
uspUpdate. CommandType = CommandType. StoredProcedure;
SqlParameter typeFullName =
new SqlParameter (" @TypeFullName " , SqlDbType. NVarChar, 128 );
typeFullName. Direction = ParameterDirection. Input;
typeFullName. Value = typeof (Coforcert. WF. Certif. WFChanges. Workflow1);
SqlParameter assemblyFullName =
new SqlParameter (" @AssemblyFullName " , SqlDbType. NVarChar, 256 );
assemblyFullName. Direction = ParameterDirection. Input;
assemblyFullName. Value =
typeof (Coforcert. WF. Certif. WFChanges. Workflow1). Assembly. FullName;
SqlParameter version =
new SqlParameter (" @Version " , SqlDbType. VarChar, 32 ;
version. Direction = ParameterDirection. Input;
version. Value = " 1.0.0.0 " ;
SqlParameter trackingProfileXml =
new SqlParameter (" @TrackingProfileXml " , SqlDbType. NText);
trackingProfileXml. Direction = ParameterDirection. Input;
trackingProfileXml. Value = trackingprofile;
uspUpdate. Parameters. Add (typeFullName);
uspUpdate. Parameters. Add (assemblyFullName);
uspUpdate. Parameters. Add (version);
uspUpdate. Parameters. Add (trackingProfileXml);
connection. Open (); uspUpdate. ExecuteNonQuery ();
connection. Close ();
}
#endregion
}
|
Il ne nous reste plus qu'à créer notre Profile depuis la méthode Main ; pour cela, ajouton du code au début de la méthode, avant de créer notre workflow
static void Main (string [ ] args) {
string connectionString = ConfigurationManager.
ConnectionStrings[ " SQLTrackingService " ] . ConnectionString;
#region Création de notre profil perso
TrackingProfile Profile = null ;
CreateTrackingProfile (out Profile);
UpdateTrackingProfile (Profile, connectionString);
#region Le reste du code se trouve ici
[ . . . ]
#endregion
}
|
Avant d'exécuter ce code, voici le résultat que nous avions
Et après
Comme nous pouvons le constater, seuls les événements définis au niveau de notre profil sont enregistrés.
Pour récupérer les données depuis la base de données de suivi, WF nous fournit des objets très pratique comme le SQLTrackingQuery et les {Activity|Workflow|user}TrackingRecord, que nous avons utilisé comme ceci :
SqlTrackingQuery query = new SqlTrackingQuery (connectionString);
SqlTrackingWorkflowInstance trackingInstance = null ;
if (query. TryGetWorkflow (instance. InstanceId, out trackingInstance)) {
#region Activity tracking
Console. WriteLine (" ***Activity Tracking*** " );
foreach (ActivityTrackingRecord record in
trackingInstance. ActivityEvents) {
Console. WriteLine (" Activity Name : {0} " , record. QualifiedName);
Console. WriteLine (" Activity Event Date Time : {0} " ,
record. EventDateTime. ToString ());
Console. WriteLine (" Activity Type : {0} " ,
record. ActivityType. ToString ());
Console. WriteLine (" Activity Status : {0} " ,
record. ExecutionStatus. ToString ());
}
Console. WriteLine (" ***************************************** " );
#endregion
#region Workflow tracking
Console. WriteLine (" ***Workflow Tracking*** " );
foreach (WorkflowTrackingRecord record in
trackingInstance. WorkflowEvents) {
Console. WriteLine (" Activity Name : {0} " ,
record. TrackingWorkflowEvent. ToString ());
Console. WriteLine (" Activity Event Date Time : {0} " ,
record. EventDateTime. ToString ());
}
Console. WriteLine (" ***************************************** " );
#endregion
#region Activity tracking
Console. WriteLine (" ***User Tracking*** " );
foreach (UserTrackingRecord record in trackingInstance. UserEvents) {
Console. WriteLine (" Activity Name : {0} " , record. QualifiedName);
Console. WriteLine (" Activity Event Date Time : {0} " ,
record. EventDateTime. ToString ());
Console. WriteLine (" Activity Type : {0} " ,
record. ActivityType. ToString ());
}
Console. WriteLine (" ***************************************** " );
#endregion
|
II. Conclusion
Comme vous avez pu le constater au travers de cet article, il va être facile de mettre en place un service de Tracking, en utilisant le service SQLTrackingService.
De même, nous pouvons cibler de manière plus spécifique les données que nous allons analyser en utilisant les TrackingProfile.
Et enfin, pour monitorer nos données, nous pouvons faire appel aux objets SQLTrackingQuery et {Activity|Workflow|user}TrackingRecord nous exposent diverses méthodes/propriétés pour gérer nos données enregistrées.
Télécharger le fichier projet Visual Studio :
ICI
Copyright © 2008 Dieudonné N'Tamack.
Aucune reproduction, même partielle, ne peut être faite
de ce site ni de l'ensemble de son contenu : textes, documents, images, etc.
sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à
trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.