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

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

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

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

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

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

【问题讨论】:

    标签: wcf azure azure-storage azure-table-storage


    【解决方案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 诊断数据而构建。

    【讨论】:

    【解决方案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 事件日志的表。

    【讨论】:

      猜你喜欢
      • 2016-10-29
      • 2013-06-02
      • 2016-12-17
      • 2018-04-02
      • 1970-01-01
      • 1970-01-01
      • 2021-08-05
      • 2018-01-14
      • 1970-01-01
      相关资源
      最近更新 更多