如何为 Dummies 筛选 Azure 日志或 WCF 数据服务筛选器

Posted

技术标签:

【中文标题】如何为 Dummies 筛选 Azure 日志或 WCF 数据服务筛选器【英文标题】:How to filter Azure logs, or WCF Data Services filters for Dummies 【发布时间】:2011-08-09 21:20:57 【问题描述】:

我正在 WADLogsTable 中查看我的 Azure 日志,并希望筛选结果,但我不知道如何执行此操作。有一个文本框说:

“输入 WCF 数据服务过滤器以限制返回的实体”

“WCF 数据服务过滤器”的语法是什么?下面给我一个 InvalidValueType 错误,说“指定的值无效。”:

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

我什至接近吗?有没有方便的语法参考?

【问题讨论】:

【参考方案1】:

此查询应采用以下格式:

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

记住把datetime 放在那里是很重要的。

这每次都让我很头疼,所以我使用OData overview 作为参考。

【讨论】:

谢谢!这行得通,但我需要先对其进行一些调整。我不得不添加秒部分。一定是天蓝色的怪癖。 添加秒数后即可使用。 knightpfhor 你能编辑一下回复吗? +1,Timestamp 也必须大写,否则结果总是空的。 这不会去任何地方,但合取运算符是 and 而不是&符号,我很难找到它。 @knightpfhor 感谢您提供指向 OData 标准的链接。【参考方案2】:

添加到 knightffhor 的响应中,您当然可以编写一个按 Timstamp 过滤的查询,但不推荐这种方法,因为查询“Timestamp”属性会导致全表扫描。而是在 PartitionKey 属性上查询此表。我从这里的其他线程复制我的回复(Can I capture Performance Counters for an Azure Web/Worker Role remotely...?):

“这里的关键之一是了解如何有效地查询该表(和其他诊断表)。我们希望从诊断表中获取的数据之一是时间。我们的本能是在 Timestamp 属性上查询此表。但是,这是一个糟糕的设计选择,因为您知道在 Azure 表中,数据在 PartitionKey 和 RowKey 上建立索引。查询任何其他属性将导致全表扫描,这将当您的表包含大量数据时会产生问题。这些日志表的好处是 PartitionKey 值在某种程度上代表了收集数据点的日期/时间。基本上 PartitionKey 是通过使用 DateTime 的高位创建的。 Ticks (in UTC). 因此,如果您要获取某个日期/时间范围的数据,首先您需要计算您的范围内的 Ticks(以 UTC 为单位),然后在其前面添加一个“0”并使用查询中的这些值。 如果您使用 REST API 进行查询,您将使用如下语法: PartitionKey ge '0' and PartitionKey le '0'."

我写了一篇关于如何针对表存储编写 WCF 查询的博文,您可能会觉得这很有用:http://blog.cerebrata.com/specifying-filter-criteria-when-querying-azure-table-storage-using-rest-api/

此外,如果您正在寻找用于查看和管理诊断数据的第三方工具,我建议您看看我们的产品 Azure 诊断管理器:/Products/AzureDiagnosticsManager。此工具专为显示和管理 Windows Azure 诊断数据而构建。

【讨论】:

您也可以查看此讨论:social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/…。底线,除非您还受到索引列(分区/行键)的约束,否则不要查询时间戳 Cerebrata 博客链接已失效,该帖子还在某处可用吗? 用正确的链接更新了答案:blog.cerebrata.com/….【参考方案3】:

answer I accepted 极大地帮助了我通过 Visual Studio 直接查询表。然而,最终我需要一个更强大的解决方案。我使用在这里获得的技巧在 C# 中开发了一些类,让我可以使用 LINQ 来查询表。如果它对查看此问题的其他人有用,以下是我现在查询 Azure 日志的大致方式。

创建一个继承自Microsoft.WindowsAzure.StorageClient.TableServiceEntity的类来表示“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);
        
    

创建一个继承自Microsoft.WindowsAzure.StorageClient.TableServiceContext的类并引用新定义的数据对象类:

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");
        
    

我有一个从配置设置创建CloudStorageAccount 的辅助方法:

public CloudStorageAccount GetStorageAccount()

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

我从CloudStorageAccount 创建了一个AzureDiagnosticContext 并使用它来查询我的日志:

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;

此方法利用Gaurav's answer 中的性能提示来过滤PartitionKey 而不是Timestamp

如果您想过滤的结果不仅仅是日期,您可以过滤返回的IEnumerable。但是,您可能会通过过滤IQueryable 获得更好的性能。您可以在您的方法中添加一个过滤器参数并在IQueryable.Where() 中调用它。例如,

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));
    ...

最后,我实际上将这些类中的大多数进一步抽象为基类,以便重用查询其他表的功能,例如存储 Windows 事件日志的表。

【讨论】:

以上是关于如何为 Dummies 筛选 Azure 日志或 WCF 数据服务筛选器的主要内容,如果未能解决你的问题,请参考以下文章