public async Task <IEnumerable <T> > GetItemsPropertyEquals(string partitionKey, string value, params string[] propertyNames) { //Table var table = await GetTableAsync(); //Query var query = new TableQuery <T>() .Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey)); var ors = new TableQuery <T>(); foreach (var propertyName in propertyNames) { ors.OrWhere(TableQuery.GenerateFilterCondition(propertyName, QueryComparisons.Equal, value)); } query.AndWhere(ors.FilterString); var results = new List <T>(); TableContinuationToken continuationToken = null; do { var queryResults = await table.ExecuteQuerySegmentedAsync(query, continuationToken); continuationToken = queryResults.ContinuationToken; results.AddRange(queryResults.Results); } while (continuationToken != null); return(results); }
/// <summary> /// /// </summary> /// <param name="appenderName"></param> /// <param name="partitionKey">index name, eg. host_name</param> /// <returns></returns> internal IEnumerable <IndexTableEntity> ReadIndexTableEntities(string appenderName, string partitionKey) { CloudTable cloudTable = this.GetCloudTable(appenderName); if (cloudTable != null) { TableQuery <IndexTableEntity> tableQuery = new TableQuery <IndexTableEntity>(); tableQuery.AndWhere(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey)); return(cloudTable.ExecuteQuery(tableQuery)); } return(Enumerable.Empty <IndexTableEntity>()); // fallback }
public static TableQuery <T> AndWhere <T>(this TableQuery <T> @this, TableQuery <T> filter) where T : ITableEntity, new() { return(@this.AndWhere(filter.FilterString)); }
/// <summary> /// Attempts to perform an Azure table query /// https://azure.microsoft.com/en-gb/documentation/articles/storage-dotnet-how-to-use-tables/ /// Gets a collection of LogTableEntity objs suitable for casting to LogItemInto /// </summary> /// <param name="appenderName"></param> /// <param name="partitionKey">null or the last known partition key</param> /// <param name="rowKey">null or the last known row key</param> /// <param name="minLevel"></param> /// <param name="loggerName">if set, looks for an exact match</param> /// <param name="hostName">if set, looks for an exact match</param> /// <returns>a collection of log items matching the supplied filter criteria</returns> private IEnumerable <LogTableEntity> ReadLogTableEntities(string appenderName, string partitionKey, string rowKey, Level minLevel, string loggerName, string hostName, string sessionId) { CloudTable cloudTable = this.GetCloudTable(appenderName); if (cloudTable != null) { TableQuery <LogTableEntity> tableQuery = new TableQuery <LogTableEntity>() .Select(new string[] { // reduce data fields returned from Azure "Level", "LoggerName", "Message", "EventTimeStamp", "log4net_HostName" }); if (!string.IsNullOrWhiteSpace(partitionKey)) { tableQuery.AndWhere(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.GreaterThanOrEqual, partitionKey)); } if (!string.IsNullOrWhiteSpace(rowKey)) { tableQuery.AndWhere(TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThan, rowKey)); } if (minLevel != Level.DEBUG) { // a number comparrison would be better, but log4net level and enum level don't match switch (minLevel) { case Level.INFO: // show all except debug tableQuery.AndWhere(TableQuery.GenerateFilterCondition("Level", QueryComparisons.NotEqual, Level.DEBUG.ToString())); break; case Level.WARN: // show all except debug and info tableQuery.AndWhere(TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("Level", QueryComparisons.NotEqual, Level.DEBUG.ToString()), TableOperators.And, TableQuery.GenerateFilterCondition("Level", QueryComparisons.NotEqual, Level.INFO.ToString()))); break; case Level.ERROR: // show if error or fatal tableQuery.AndWhere(TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("Level", QueryComparisons.Equal, Level.ERROR.ToString()), TableOperators.Or, TableQuery.GenerateFilterCondition("Level", QueryComparisons.Equal, Level.FATAL.ToString()))); break; case Level.FATAL: // show fatal only tableQuery.AndWhere(TableQuery.GenerateFilterCondition("Level", QueryComparisons.Equal, Level.FATAL.ToString())); break; } } if (!string.IsNullOrWhiteSpace(loggerName)) { tableQuery.AndWhere(TableQuery.GenerateFilterCondition("LoggerName", QueryComparisons.Equal, loggerName)); } else { // HACK: ensure index entities are not returned tableQuery.AndWhere(TableQuery.GenerateFilterCondition("LoggerName", QueryComparisons.NotEqual, string.Empty)); } if (!string.IsNullOrWhiteSpace(hostName)) { tableQuery.AndWhere(TableQuery.GenerateFilterCondition("log4net_HostName", QueryComparisons.Equal, hostName)); } if (!string.IsNullOrWhiteSpace(sessionId)) { tableQuery.AndWhere(TableQuery.GenerateFilterCondition("sessionId", QueryComparisons.Equal, sessionId)); } return(cloudTable.ExecuteQuery( tableQuery, new TableRequestOptions() { ServerTimeout = new TimeSpan(0, 0, 2) })); } return(Enumerable.Empty <LogTableEntity>()); // fallback }
/// <summary> /// Queries Azure table storage until results are returned or a timeout is thown /// </summary> /// <param name="appenderName">name of the log4net appender</param> /// <param name="partitionKey">a partional key to begin search from (can be null)</param> /// <param name="rowKey">a row key to begin search from (can be null)</param> /// <param name="hostName">host name to filter on</param> /// <param name="loggerName">logger name to filter on</param> /// <param name="minLevel">logger level to filter</param> /// <param name="message">message text to filter</param> /// <param name="sessionId">session id to filter</param> /// <returns></returns> internal LogTableEntity[] ReadLogTableEntities(string appenderName, string partitionKey, string rowKey, string hostName, string loggerName, Level minLevel, string message, string sessionId) { LogTableEntity[] logTableEntities = new LogTableEntity[] { }; // default return value CloudTable cloudTable = this.GetCloudTable(appenderName); if (cloudTable == null) { return(logTableEntities); } int take = 50; // default take for Azure query bool hostNameWildcardFiltering = !string.IsNullOrWhiteSpace(hostName) && !IndexService.Instance.GetMachineNames(appenderName).Any(x => x == hostName); bool loggerNameWildcardFiltering = !string.IsNullOrWhiteSpace(loggerName) && !IndexService.Instance.GetLoggerNames(appenderName).Any(x => x == loggerName); // local filtering function applied to returned Azure table results Func <LogTableEntity, bool> customFiltering = (x) => { return(true); }; // default empty method (no custom filtering performed) // check to see if custom filtering (in c#) is required in addition to the Azure query if (hostNameWildcardFiltering || loggerNameWildcardFiltering || !string.IsNullOrWhiteSpace(message)) // message filtering always done in c# { customFiltering = (x) => { return((string.IsNullOrWhiteSpace(hostName) || x.log4net_HostName != null && x.log4net_HostName.IndexOf(hostName, StringComparison.InvariantCultureIgnoreCase) > -1) && (string.IsNullOrWhiteSpace(loggerName) || x.LoggerName != null && x.LoggerName.IndexOf(loggerName, StringComparison.InvariantCultureIgnoreCase) > -1) && (string.IsNullOrWhiteSpace(message) || x.Message != null && x.Message.IndexOf(message, StringComparison.InvariantCultureIgnoreCase) > -1)); }; // increase take, to account for customFiltering further reducing dataset take = 1000; } // build the Azure table query TableQuery <LogTableEntity> tableQuery = new TableQuery <LogTableEntity>() .Select(new string[] { // reduce data fields returned from Azure "Level", "LoggerName", "Message", "EventTimeStamp", "log4net_HostName" }); if (!string.IsNullOrWhiteSpace(partitionKey)) { tableQuery.AndWhere(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.GreaterThanOrEqual, partitionKey)); } if (!string.IsNullOrWhiteSpace(rowKey)) { tableQuery.AndWhere(TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThan, rowKey)); } if (minLevel != Level.DEBUG) { // a number comparrison would be better, but log4net level and enum level don't match switch (minLevel) { case Level.INFO: // show all except debug tableQuery.AndWhere(TableQuery.GenerateFilterCondition("Level", QueryComparisons.NotEqual, Level.DEBUG.ToString())); break; case Level.WARN: // show all except debug and info tableQuery.AndWhere(TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("Level", QueryComparisons.NotEqual, Level.DEBUG.ToString()), TableOperators.And, TableQuery.GenerateFilterCondition("Level", QueryComparisons.NotEqual, Level.INFO.ToString()))); break; case Level.ERROR: // show if error or fatal tableQuery.AndWhere(TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("Level", QueryComparisons.Equal, Level.ERROR.ToString()), TableOperators.Or, TableQuery.GenerateFilterCondition("Level", QueryComparisons.Equal, Level.FATAL.ToString()))); break; case Level.FATAL: // show fatal only tableQuery.AndWhere(TableQuery.GenerateFilterCondition("Level", QueryComparisons.Equal, Level.FATAL.ToString())); break; } } if (!loggerNameWildcardFiltering && !string.IsNullOrWhiteSpace(loggerName)) { tableQuery.AndWhere(TableQuery.GenerateFilterCondition("LoggerName", QueryComparisons.Equal, loggerName)); } else { // HACK: ensure index entities are not returned tableQuery.AndWhere(TableQuery.GenerateFilterCondition("LoggerName", QueryComparisons.NotEqual, string.Empty)); } if (!hostNameWildcardFiltering && !string.IsNullOrWhiteSpace(hostName)) { tableQuery.AndWhere(TableQuery.GenerateFilterCondition("log4net_HostName", QueryComparisons.Equal, hostName)); } if (!string.IsNullOrWhiteSpace(sessionId)) { tableQuery.AndWhere(TableQuery.GenerateFilterCondition("sessionId", QueryComparisons.Equal, sessionId)); } tableQuery.Take(take); TableContinuationToken tableContinuationToken = null; TableQuerySegment <LogTableEntity> response; do { // single Azure table storage requsest response = cloudTable.ExecuteQuerySegmented(tableQuery, tableContinuationToken); // blocking logTableEntities = response.Results.Where(x => customFiltering(x)).ToArray(); tableContinuationToken = response.ContinuationToken; } while (!logTableEntities.Any() && tableContinuationToken != null); return(logTableEntities); }