41 votes

Comment filtrer les journaux Azure, ou les filtres des services de données WCF pour les Nuls

Je consulte mes journaux Azure dans la table WADLogsTable et j'aimerais filtrer les résultats, mais je ne sais pas comment faire. Il y a une zone de texte qui dit :

"Entrez un filtre WCF Data Services pour limiter les entités retournées".

Quelle est la syntaxe d'un "filtre WCF Data Services" ? Ce qui suit me donne une erreur InvalidValueType disant "La valeur spécifiée est invalide" :

Timestamp gt '2011-04-20T00:00'

Est-ce que j'en suis proche ? Existe-t-il une référence syntaxique pratique quelque part ?

72voto

knightpfhor Points 6242

Cette requête doit être au format :

Timestamp gt datetime'2011-04-20T00:00:00'

Se souvenir de mettre ce datetime là-dedans, c'est la partie importante.

Cela me fait trébucher à chaque fois, alors j'utilise la fonction Aperçu d'OData pour référence.

12voto

Gaurav Mantri Points 19423

En complément de la réponse de knightffhor, vous pouvez certainement écrire une requête qui filtre par Timstamp mais ce n'est pas une approche recommandée car une requête sur l'attribut "Timestamp" entraînera un balayage complet de la table. Interrogez plutôt cette table sur l'attribut PartitionKey. Je copie ici ma réponse d'un autre fil de discussion ( Puis-je capturer les compteurs de performance d'un rôle Azure Web/Worker à distance ? ) :

"L'une des choses essentielles ici est de comprendre comment interroger efficacement cette table (et d'autres tables de diagnostic). L'une des choses que nous voulons obtenir de la table de diagnostic est de récupérer les données pour une certaine période de temps. Notre instinct naturel serait d'interroger cette table sur l'attribut Timestamp. Cependant, c'est un MAUVAIS choix de conception car vous savez que dans une table Azure, les données sont indexées sur PartitionKey et RowKey. Une requête sur tout autre attribut entraînera un balayage complet de la table, ce qui posera un problème si votre table contient beaucoup de données. Le point positif de ces tables de journaux est que la valeur PartitionKey représente en quelque sorte la date/heure à laquelle le point de données a été collecté. En fait, PartitionKey est créé en utilisant les bits d'ordre supérieur de DateTime.Ticks (en UTC). Ainsi, si vous souhaitez récupérer les données pour une certaine plage de dates/heures, vous devez d'abord calculer les Ticks pour votre plage (en UTC), puis ajouter un "0" devant et utiliser ces valeurs dans votre requête. Si vous effectuez une requête à l'aide de l'API REST, vous utiliserez la syntaxe suivante : PartitionKey ge '0<from date/time ticks in UTC>' et PartitionKey le '0<to date/time in UTC>'."

J'ai écrit un article de blog sur la façon d'écrire des requêtes WCF contre le stockage de tables qui peut vous être utile : http://blog.cerebrata.com/specifying-filter-criteria-when-querying-azure-table-storage-using-rest-api/

Par ailleurs, si vous recherchez un outil tiers pour afficher et gérer les données de diagnostic, je vous suggère de jeter un coup d'œil à notre produit Azure Diagnostics Manager : /Produits/AzureDiagnosticsManager. Cet outil est conçu spécifiquement pour afficher et gérer les données de diagnostic de Windows Azure.

4voto

gilly3 Points 33285

El réponse que j'ai acceptée m'a énormément aidé à interroger directement la table via Visual Studio. Cependant, j'ai fini par avoir besoin d'une solution plus robuste. J'ai utilisé les conseils que j'ai obtenus ici pour développer quelques classes en C# qui me permettent d'utiliser LINQ pour interroger les tables. Au cas où cela serait utile à d'autres personnes consultant cette question, voici en gros comment j'interroge maintenant mes journaux Azure.

Créez une classe qui hérite de Microsoft.WindowsAzure.StorageClient.TableServiceEntity pour représenter toutes les données de la table "WADLogsTable" :

public class AzureDiagnosticEntry : TableServiceEntity
{
    public long EventTickCount { get; set; }
    public string DeploymentId { get; set; }
    public string Role { get; set; }
    public string RoleInstance { get; set; }
    public int EventId { get; set; }
    public int Level { get; set; }
    public int Pid { get; set; }
    public int Tid { get; set; }
    public string Message { get; set; }
    public DateTime EventDateTime
    {
        get
        {
            return new DateTime(EventTickCount, DateTimeKind.Utc);
        }
    }
}

Créez une classe qui hérite de Microsoft.WindowsAzure.StorageClient.TableServiceContext et fait référence à la classe d'objets de données nouvellement définie :

public class AzureDiagnosticContext : TableServiceContext
{
    public AzureDiagnosticContext(string baseAddress, StorageCredentials credentials)
        : base(baseAddress, credentials)
    {
        this.ResolveType = s => typeof(AzureDiagnosticEntry);
    }

    public AzureDiagnosticContext(CloudStorageAccount storage)
        : this(storage.TableEndpoint.ToString(), storage.Credentials) { }

    // Helper method to get an IQueryable.  Hard code "WADLogsTable" for this class
    public IQueryable<AzureDiagnosticEntry> Logs
    {
        get
        {
            return CreateQuery<AzureDiagnosticEntry>("WADLogsTable");
        }
    }
}

J'ai une méthode d'aide qui crée un CloudStorageAccount à partir des paramètres de configuration :

public CloudStorageAccount GetStorageAccount()
{
    CloudStorageAccount.SetConfigurationSettingPublisher(
        (name, setter) => setter(RoleEnvironment.GetConfigurationSettingValue(name)));
    string configKey = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString";
    return CloudStorageAccount.FromConfigurationSetting(configKey);
}

Je crée un AzureDiagnosticContext de la CloudStorageAccount et l'utiliser pour interroger mes journaux :

public IEnumerable<AzureDiagnosticEntry> GetAzureLog(DateTime start, DateTime end)
{
    CloudStorageAccount storage = GetStorageAccount();
    AzureDiagnosticContext context = new AzureDiagnosticContext(storage);
    string startTicks = "0" + start.Ticks;
    string endTicks = "0" + end.Ticks;
    IQueryable<AzureDiagnosticEntry> query = context.Logs.Where(
        e => e.PartitionKey.CompareTo(startTicks) > 0 &&
             e.PartitionKey.CompareTo(endTicks) < 0);
    CloudTableQuery<AzureDiagnosticEntry> tableQuery = query.AsTableServiceQuery();
    IEnumerable<AzureDiagnosticEntry> results = tableQuery.Execute();
    return results;
}

Cette méthode tire profit de l'astuce de performance dans La réponse de Gaurav pour filtrer sur PartitionKey plutôt que Timestamp .

Si vous vouliez filtrer les résultats en fonction d'autres critères que la date, vous pourriez filtrer les données retournées par l'option IEnumerable . Mais, vous obtiendrez probablement de meilleures performances en filtrant le fichier IQueryable . Vous pourriez ajouter un paramètre de filtrage à votre méthode et l'appeler au sein de la méthode IQueryable.Where() . Eg,

public IEnumerable<AzureDiagnosticEntry> GetAzureLog(
    DateTime start, DateTime end, Func<AzureDiagnosticEntry, bool> filter)
{
    ...
    IQueryable<AzureDiagnosticEntry> query = context.Logs.Where(
        e => e.PartitionKey.CompareTo(startTicks) > 0 &&
             e.PartitionKey.CompareTo(endTicks) < 0 &&
             filter(e));
    ...
}

Au final, j'ai encore plus abstrait la plupart de ces classes en classes de base afin de réutiliser la fonctionnalité pour interroger d'autres tables, comme celle qui stocke le journal des événements de Windows.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X