/// <summary> /// Convert the Influx Series JSON objects to InfluxSeries /// </summary> /// <param name="precision"></param> /// <param name="series"></param> /// <returns></returns> private static InfluxSeries GetInfluxSeries(TimePrecision precision, Series series) { var result = new InfluxSeries() { HasEntries = false }; result.SeriesName = series.Name; result.Tags = series.Tags; var entries = new List <dynamic>(); for (var row = 0; row < series?.Values?.Count; row++) { result.HasEntries = true; dynamic entry = new ExpandoObject(); entries.Add(entry); for (var col = 0; col < series.Columns.Count; col++) { var header = char.ToUpper(series.Columns[col][0]) + series.Columns[col].Substring(1); if (header == "Time") { ((IDictionary <string, object>)entry).Add(header, EpochHelper.FromEpoch(series.Values[row][col], precision)); } else { ((IDictionary <string, object>)entry).Add(header, series.Values[row][col]); } } } result.Entries = entries; return(result); }
/// <summary> /// Queries Influx DB and gets a time series data back. Ideal for fetching measurement values. /// The return list is of InfluxSeries, and each element in there will have properties named after columns in series /// </summary> /// <param name="dbName">Name of the database</param> /// <param name="measurementQuery">Query text, Only results with single series are supported for now</param> /// <param name="precision">epoch precision of the data set</param> /// <returns>List of InfluxSeries</returns> /// <seealso cref="InfluxSeries"/> public async Task <List <IInfluxSeries> > QueryMultiSeriesAsync(string dbName, string measurementQuery, TimePrecision precision = TimePrecision.Nanoseconds) { var response = await GetAsync(new Dictionary <string, string>() { { "db", dbName }, { "q", measurementQuery }, { "epoch", precisionLiterals[(int)precision] } }); if (response == null) { throw new ServiceUnavailableException(); } if (response.StatusCode == HttpStatusCode.OK) { var results = new List <IInfluxSeries>(); var rawResult = JsonConvert.DeserializeObject <InfluxResponse>(await response.Content.ReadAsStringAsync()); if (rawResult?.Results?.Count > 1) { throw new ArgumentException("The query is resulting in a format, which is not supported by this method yet"); } if (rawResult?.Results[0]?.Series != null) { foreach (var series in rawResult?.Results[0]?.Series) { InfluxSeries result = GetInfluxSeries(precision, series); results.Add(result); } } return(results); } return(null); }
/// <summary> /// Queries Influx DB and gets a time series data back. Ideal for fetching measurement values. /// The return list is of InfluxSeries, and each element in there will have properties named after columns in series /// THis uses Chunking support from InfluxDB. It returns results in streamed batches rather than as a single response /// Responses will be chunked by series or by every ChunkSize points, whichever occurs first. /// </summary> /// <param name="dbName">Name of the database</param> /// <param name="measurementQuery">Query text, Only results with single series are supported for now</param> /// <param name="ChunkSize">Maximum Number of points in a chunk</param> /// <param name="precision">epoch precision of the data set</param> /// <returns>List of InfluxSeries</returns> /// <seealso cref="InfluxSeries"/> public async Task <List <IInfluxSeries> > QueryMultiSeriesAsync(string dbName, string measurementQuery, int ChunkSize, string retentionPolicy = null, TimePrecision precision = TimePrecision.Nanoseconds) { var endPoint = new Dictionary <string, string>() { { "db", dbName }, { "q", measurementQuery }, { "chunked", "true" }, { "chunk_size", ChunkSize.ToString() }, { "epoch", precisionLiterals[(int)precision] } }; if (retentionPolicy != null) { endPoint.Add("rp", retentionPolicy); } var response = await GetAsync(endPoint, HttpCompletionOption.ResponseHeadersRead); if (response == null) { throw new ServiceUnavailableException(); } if (response.StatusCode == HttpStatusCode.OK) { var results = new List <IInfluxSeries>(); var stream = await response.Content.ReadAsStreamAsync(); using (var reader = new StreamReader(stream)) { do { var str = await reader.ReadLineAsync(); var rawResult = JsonConvert.DeserializeObject <InfluxResponse>(str); var partialResult = rawResult?.Results?.Any(r => r.Partial == true); if (rawResult?.Results[0]?.Series != null) { foreach (var series in rawResult?.Results[0]?.Series) { InfluxSeries result = GetInfluxSeries(precision, series, partialResult); results.Add(result); } } if (!rawResult.Results[0].Partial) { break; } } while (!reader.EndOfStream); } return(results); } return(null); }
/// <summary> /// Queries Influx DB and gets a time series data back. Ideal for fetching measurement values. /// The return list is of InfluxSeries, and each element in there will have properties named after columns in series /// </summary> /// <param name="dbName">Name of the database</param> /// <param name="measurementQuery">Query text, Only results with single series are supported for now</param> /// <param name="precision">epoch precision of the data set</param> /// <returns>List of InfluxSeries</returns> /// <seealso cref="InfluxSeries"/> public async Task <List <IInfluxSeries> > QueryMultiSeriesAsync(string dbName, string measurementQuery, TimePrecision precision = TimePrecision.Nanoseconds) { var response = await GetAsync(new Dictionary <string, string> () { { "db", dbName }, { "q", measurementQuery }, { "epoch", precisionLiterals[(int)precision] } }); if (response.StatusCode == HttpStatusCode.OK) { var results = new List <IInfluxSeries> (); var rawResult = JsonConvert.DeserializeObject <InfluxResponse> (await response.Content.ReadAsStringAsync()); if (rawResult?.Results?.Count > 1) { throw new ArgumentException("The query is resulting in a format, which is not supported by this method yet"); } if (rawResult?.Results[0]?.Series != null) { foreach (var series in rawResult?.Results[0]?.Series) { var result = new InfluxSeries(); result.HasEntries = false; results.Add(result); result.SeriesName = series.Name; result.Tags = series.Tags; var entries = new List <dynamic> (); for (var row = 0; row < series?.Values?.Count; row++) { result.HasEntries = true; dynamic entry = new ExpandoObject(); entries.Add(entry); for (var col = 0; col < series.Columns.Count; col++) { var header = char.ToUpper(series.Columns[col][0]) + series.Columns[col].Substring(1); if (header == "Time") { ((IDictionary <string, object>)entry).Add(header, EpochHelper.FromEpoch(series.Values[row][col], precision)); } else { ((IDictionary <string, object>)entry).Add(header, series.Values[row][col]); } } } result.Entries = entries; } } return(results); } return(null); }
/// <summary> /// Convert the Influx Series JSON objects to InfluxSeries /// </summary> /// <param name="precision"></param> /// <param name="series"></param> /// <param name="partialResult"></param> /// <param name="SafePropertyNames">If true the first letter of each property name will be Capital, making them safer to use in C#</param> /// <returns></returns> private static InfluxSeries GetInfluxSeries(TimePrecision precision, Series series, bool?partialResult, bool SafePropertyNames = true) { var result = new InfluxSeries() { HasEntries = false }; result.SeriesName = series.Name; result.Tags = series.Tags; result.Partial = partialResult ?? false; var entries = new List <dynamic>(); for (var row = 0; row < series?.Values?.Count; row++) { result.HasEntries = true; dynamic entry = new ExpandoObject(); entries.Add(entry); for (var col = 0; col < series.Columns.Count; col++) { string header; if (SafePropertyNames) { header = char.ToUpper(series.Columns[col][0]) + series.Columns[col].Substring(1); } else { header = series.Columns[col]; } if (String.Equals(header, "Time", StringComparison.OrdinalIgnoreCase)) { ((IDictionary <string, object>)entry).Add(header, EpochHelper.FromEpoch(series.Values[row][col], precision)); } else { ((IDictionary <string, object>)entry).Add(header, series.Values[row][col]); } } } result.Entries = entries; return(result); }
/// <summary> /// Queries Influx DB and gets a time series data back. Ideal for fetching measurement values. /// The return list is of InfluxSeries, and each element in there will have properties named after columns in series /// THis uses Chunking support from InfluxDB. It returns results in streamed batches rather than as a single response /// Responses will be chunked by series or by every ChunkSize points, whichever occurs first. /// </summary> /// <param name="dbName">Name of the database</param> /// <param name="measurementQuery">Query text, Only results with single series are supported for now</param> /// <param name="ChunkSize">Maximum Number of points in a chunk</param> /// <param name="precision">epoch precision of the data set</param> /// <returns>List of InfluxSeries</returns> /// <seealso cref="InfluxSeries"/> public async Task <List <IInfluxSeries> > QueryMultiSeriesAsync(string dbName, string measurementQuery, int ChunkSize, TimePrecision precision = TimePrecision.Nanoseconds) { var response = await GetAsync(new Dictionary <string, string>() { { "db", dbName }, { "q", measurementQuery }, { "chunked", "true" }, { "chunk_size", ChunkSize.ToString() }, { "epoch", precisionLiterals[(int)precision] } }); if (response == null) { throw new ServiceUnavailableException(); } if (response.StatusCode == HttpStatusCode.OK) { var results = new List <IInfluxSeries>(); //Hack for https://github.com/influxdata/influxdb/issues/8212 foreach (var str in (await response.Content.ReadAsStringAsync()).Split('\n')) { var rawResult = JsonConvert.DeserializeObject <InfluxResponse>(str); if (rawResult?.Results[0]?.Series != null) { foreach (var series in rawResult?.Results[0]?.Series) { InfluxSeries result = GetInfluxSeries(precision, series); results.Add(result); } } if (!rawResult.Results[0].Partial) { break; } } return(results); } return(null); }
/// <summary> /// Queries Influx DB and gets a time series data back. Ideal for fetching measurement values. /// The return list is of InfluxSeries, and each element in there will have properties named after columns in series /// </summary> /// <param name="dbName">Name of the database</param> /// <param name="measurementQuery">Query text, Only results with single series are supported for now</param> /// <param name="precision">epoch precision of the data set</param> /// <returns>List of InfluxSeries</returns> /// <seealso cref="InfluxSeries"/> public async Task<List<IInfluxSeries>> QueryMultiSeriesAsync (string dbName, string measurementQuery, TimePrecision precision = TimePrecision.Nanoseconds) { var response = await GetAsync (new Dictionary<string, string> () { { "db", dbName }, { "q", measurementQuery }, { "epoch", precisionLiterals[(int) precision] } }); if (response.StatusCode == HttpStatusCode.OK) { var results = new List<IInfluxSeries> (); var rawResult = JsonConvert.DeserializeObject<InfluxResponse> (await response.Content.ReadAsStringAsync ()); if (rawResult?.Results?.Count > 1) throw new ArgumentException ("The query is resulting in a format, which is not supported by this method yet"); if (rawResult?.Results[0]?.Series != null) { foreach (var series in rawResult?.Results[0]?.Series) { var result = new InfluxSeries (); result.HasEntries = false; results.Add (result); result.SeriesName = series.Name; result.Tags = series.Tags; var entries = new List<dynamic> (); for (var row = 0; row < series?.Values?.Count; row++) { result.HasEntries = true; dynamic entry = new ExpandoObject (); entries.Add (entry); for (var col = 0; col < series.Columns.Count; col++) { var header = char.ToUpper (series.Columns[col][0]) + series.Columns[col].Substring (1); if (header == "Time") ((IDictionary<string, object>) entry).Add (header, EpochHelper.FromEpoch (series.Values[row][col], precision)); else ((IDictionary<string, object>) entry).Add (header, series.Values[row][col]); } } result.Entries = entries; } } return results; } return null; }