我正在WADLogsTable中查看我的Azure日志,并希望过滤结果,但我不知道如何这样做。有一个文本框写着:
"输入WCF数据服务过滤器以限制返回的实体"
"WCF数据服务过滤器"的语法是什么?下面给了我一个InvalidValueType错误,说"指定的值无效"。:
Timestamp gt '2011-04-20T00:00'
我还差吗?有方便的语法参考吗?
这个查询的格式应该是:
Timestamp gt datetime'2011-04-20T00:00:00'
记住把datetime
放在这里是重要的位。
我每次都会遇到这个问题,所以我使用OData概述作为参考。
添加到knightffhor的响应,您当然可以编写一个查询,通过时间戳过滤,但这不是推荐的方法,因为查询"时间戳"属性将导致全表扫描。而是在PartitionKey属性上查询该表。我在这里复制我从其他线程的响应(我可以远程捕获Azure Web/Worker角色的性能计数器…):
"这里的关键之一是理解如何有效地查询这个表(以及其他诊断表)。我们希望从诊断表中获取特定时间段的数据。我们的本能反应是根据Timestamp属性查询该表。然而,这是一个糟糕的设计选择,因为你知道在Azure表中,数据是在PartitionKey和RowKey上索引的。查询任何其他属性都将导致全表扫描,这将在表包含大量数据时产生问题。这些日志表的好处是PartitionKey值在某种程度上表示收集数据点的日期/时间。基本上,PartitionKey是通过使用DateTime的高阶位创建的。Ticks (UTC)。因此,如果您要获取某个日期/时间范围的数据,首先您需要计算您的范围(在UTC中)的Ticks,然后在其前面加上"0"并在查询中使用这些值。如果你使用REST API查询,你会使用这样的语法:PartitionKey '0'和PartitionKey '0'。"
我写了一篇关于如何编写针对表存储的WCF查询的博客文章,您可能会觉得有用:http://blog.cerebrata.com/specifying-filter-criteria-when-querying-azure-table-storage-using-rest-api/
如果你正在寻找一个第三方工具来查看和管理诊断数据,我建议你看看我们的产品Azure诊断管理器:/Products/AzureDiagnosticsManager。此工具是专门为显示和管理Windows Azure Diagnostics数据而构建的。
我接受的答案极大地帮助了我通过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回答中的性能提示,在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事件日志的表。