diff --git a/Influxer/ExtensionMethods.cs b/Influxer/ExtensionMethods.cs index 8a4d8a6..2465030 100644 --- a/Influxer/ExtensionMethods.cs +++ b/Influxer/ExtensionMethods.cs @@ -7,23 +7,7 @@ namespace AdysTech.Influxer { - internal static class EpochHelper - { - private static readonly DateTime Origin = new DateTime (1970, 1, 1); - - public static long ToEpochMs(this DateTime time) - { - TimeSpan t = time - Origin; - return (long) ( t.TotalSeconds * 1000 ); - } - - public static long ToEpoch(this DateTime time) - { - TimeSpan t = time - Origin; - return (long) ( t.TotalSeconds ); - } - } - + public static class StringExtensionMethods { public static string Replace(this string s, char[] separators, string newValue) diff --git a/Influxer/FailureTracker.cs b/Influxer/FailureTracker.cs new file mode 100644 index 0000000..fec0b44 --- /dev/null +++ b/Influxer/FailureTracker.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AdysTech.Influxer +{ + class FailureTracker + { + public Type ExceptionType { get; set; } + public int Count { get; set; } + public string Message { get; set; } + } +} diff --git a/Influxer/Influxer.csproj b/Influxer/Influxer.csproj index 1d8142b..768aa04 100644 --- a/Influxer/Influxer.csproj +++ b/Influxer/Influxer.csproj @@ -48,6 +48,10 @@ + + False + .\AdysTech.InfluxDB.Client.Net.dll + @@ -59,6 +63,7 @@ + diff --git a/Influxer/Program.cs b/Influxer/Program.cs index 9e27289..a017c07 100644 --- a/Influxer/Program.cs +++ b/Influxer/Program.cs @@ -12,6 +12,7 @@ using System.Diagnostics; using System.Globalization; using System.Net.Http.Headers; +using AdysTech.InfluxDB.Client.Net; namespace AdysTech.Influxer { @@ -43,10 +44,12 @@ enum FileFormats const string TableNameSwitch = "-table"; const string FilterSwitch = "-filter"; const string ColumnsSwitch = "-columns"; - const string UtcOffsetSwitch = "-gmtoffset"; + const string UtcOffsetSwitch = "-utcoffset"; + const string TimePrecisionSwitch = "-precision"; + private static string influxUrl; - private static string influxDB; + private static string influxDBName; private static string influxDBUserName; private static string influxDBPassword; private static string tags; @@ -59,6 +62,7 @@ enum FileFormats private static Filters filter; private static string filteredColumns; private static int utcOffsetMin = 0; + private static TimePrecision timePrecision; private static char[] influxIdentifiers = new char[] { ' ', ';', '_', '(', ')', '%', '#', '.', '/', '[', ']', '{', '}', '"' }; private static char[] whiteSpace = new char[] { '_' }; @@ -82,6 +86,7 @@ static int Main(string[] args) Console.WriteLine ("-filter : supported:measurement, field, columns."); Console.WriteLine ("-columns : Comma seperated list of columns from input files"); Console.WriteLine ("-utcoffset : supported:measurement, field, columns.Offset in minutes to UTC. Applicable to Generic format only"); + Console.WriteLine ("-precision : supported:Hours<1>,Minutes<2>,Seconds<3>,MilliSeconds<4>,MicroSeconds<5>,NanoSeconds<6>"); Console.WriteLine ("-filter-measurement or field is to restrict the input file to only measurements or fileds that already present in the database"); Console.WriteLine ("-filter-columns is to restrict to only few columns from the input irrespective of existing data in database"); @@ -110,7 +115,7 @@ static int Main(string[] args) if ( cmdArgs.ContainsKey (InfluxDBSwitch) ) - influxDB = cmdArgs[InfluxDBSwitch]; + influxDBName = cmdArgs[InfluxDBSwitch]; else throw new Exception ("Influx DB name is a must!!"); @@ -151,7 +156,7 @@ static int Main(string[] args) { if ( !Enum.TryParse (cmdArgs[FileFormatSwitch], true, out fileFormat) || !Enum.IsDefined (typeof (FileFormats), fileFormat) ) { - Console.WriteLine ("Not supported format{0}!!", cmdArgs[FileFormatSwitch]); + Console.WriteLine ("Not supported format {0}!!", cmdArgs[FileFormatSwitch]); return 1; } } @@ -209,25 +214,30 @@ static int Main(string[] args) utcOffsetMin = int.Parse (cmdArgs[UtcOffsetSwitch]); } + if ( cmdArgs.ContainsKey (TimePrecisionSwitch) ) + { + if ( !Enum.TryParse (cmdArgs[TimePrecisionSwitch], true, out timePrecision) || !Enum.IsDefined (typeof (TimePrecision), timePrecision) ) + { + Console.WriteLine ("Not supported format {0}!!", cmdArgs[TimePrecisionSwitch]); + return 1; + } + } + else + { + timePrecision = TimePrecision.Seconds; + } + #endregion try { Stopwatch stopwatch = new Stopwatch (); stopwatch.Start (); - HttpClientHandler handler = new HttpClientHandler (); - handler.UseDefaultCredentials = true; - handler.PreAuthenticate = true; - handler.Proxy = WebRequest.DefaultWebProxy; - WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultNetworkCredentials; + var client = new InfluxDBClient (influxUrl, influxDBUserName, influxDBPassword); - var client = new HttpClient (handler); - if ( !( String.IsNullOrWhiteSpace (influxDBUserName) && String.IsNullOrWhiteSpace (influxDBPassword) ) ) - client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue ("Basic", Convert.ToBase64String (System.Text.ASCIIEncoding.ASCII.GetBytes (string.Format ("{0}:{1}", influxDBUserName, influxDBPassword)))); - - if ( !VerifyDatabaseAsync (client, influxDB).Result ) + if ( !VerifyDatabaseAsync (client, influxDBName).Result ) { - Console.WriteLine ("Unable to create DB {0}", influxDB); + Console.WriteLine ("Unable to create DB {0}", influxDBName); return -1; } @@ -254,175 +264,45 @@ static int Main(string[] args) } catch ( AggregateException e ) { - Console.WriteLine (e.InnerException.Message); - Debug.WriteLine (e.InnerException.Message); + Console.WriteLine ("Error!! {0}:{1} - {2}", e.InnerException.GetType ().Name, e.InnerException.Message, e.InnerException.StackTrace); return -1; } - return 0; - } - - private static async Task VerifyDatabaseAsync(HttpClient client, string DBName) - { - var influxAddress = new Uri (influxUrl + "/query?"); - - //verify DB exists, create if not - var dbNames = await GetInfluxDBNamesAsync (client, influxAddress); - if ( dbNames == null ) return false; - - if ( dbNames.Contains (DBName) ) - return true; - else - { - if ( filter == Filters.Measurement || filter == Filters.Field ) - { - Console.WriteLine ("Measurement/Field filtering is not applicable for new database!!"); - filter = Filters.None; - } - return await CreateInfluxDBAsync (client, DBName, influxAddress); - } - } - - private static async Task> GetInfluxDBNamesAsync(HttpClient client, Uri InfluxPath) - { - try - { - var builder = new UriBuilder (InfluxPath); - //builder.UserName = influxDBUserName; - //builder.Password = influxDBPassword; - builder.Query = await new FormUrlEncodedContent (new[] { - new KeyValuePair("u",influxDBUserName) , - new KeyValuePair("p", influxDBPassword) , - new KeyValuePair("q", "SHOW DATABASES") - }).ReadAsStringAsync (); - HttpResponseMessage response = await client.GetAsync (builder.Uri); - - if ( response.StatusCode == HttpStatusCode.OK ) - { - var content = await response.Content.ReadAsStringAsync (); - return Regex.Matches (content, "([a-zA-Z0-9]+)").Cast ().Select (match => match.Value).SkipWhile (p => p != "values").Skip (1).ToList (); - } - } - catch ( HttpRequestException e ) + catch ( Exception e ) { - return null; + Console.WriteLine ("Error!! {0}:{1} - {2}", e.GetType ().Name, e.Message, e.StackTrace); + return -1; } - return null; + return 0; } - private static async Task>> GetInfluxDBStructureAsync(HttpClient client, Uri InfluxPath, string dbName) + private static async Task VerifyDatabaseAsync(InfluxDBClient client, string DBName) { - var dbStructure = new Dictionary> (); try { - var builder = new UriBuilder (InfluxPath); - //builder.UserName = influxDBUserName; - //builder.Password = influxDBPassword; - builder.Query = await new FormUrlEncodedContent (new[] { - new KeyValuePair("u",influxDBUserName) , - new KeyValuePair("p", influxDBPassword) , - new KeyValuePair("db", dbName) , - new KeyValuePair("q", "SHOW FIELD KEYS") - }).ReadAsStringAsync (); - HttpResponseMessage response = await client.GetAsync (builder.Uri); - - if ( response.StatusCode == HttpStatusCode.OK ) + //verify DB exists, create if not + var dbNames = await client.GetInfluxDBNamesAsync (); + if ( dbNames.Contains (DBName) ) + return true; + else { - var content = await response.Content.ReadAsStringAsync (); - var values = Regex.Matches (content, "([a-zA-Z0-9_]+)").Cast ().Select (match => match.Value).ToList (); - string measurement; - //one pass loop through the entries in returned structure. Each new measurement starts with "name",measurement name, "columns","fieldKey","values",list of columns - //we will search for name, and once found grab measurement name, skip 3 lines, and grab column names - for ( int i = 0; i < values.Count; i++ ) + if ( filter == Filters.Measurement || filter == Filters.Field ) { - if ( values[i] != "name" ) - continue; - if ( values[i] == "name" ) - { - if ( ++i == values.Count ) - throw new InvalidDataException ("Invalid data returned from InfluxDB"); - //i is incremented - measurement = values[i]; - dbStructure.Add (measurement, new List ()); - for ( int j = i + 4; j < values.Count; j++ ) - { - if ( values[j] == "name" ) - { - i = j - 1; - break; - } - dbStructure[measurement].Add (values[j]); - } - } + Console.WriteLine ("Measurement/Field filtering is not applicable for new database!!"); + filter = Filters.None; } + return await client.CreateDatabaseAsync (DBName); } } - catch ( HttpRequestException e ) - { - - } - - return dbStructure; - } - - - private static async Task CreateInfluxDBAsync(HttpClient client, string dbName, Uri InfluxPath) - { - try - { - var builder = new UriBuilder (InfluxPath); - //builder.UserName = influxDBUserName; - //builder.Password = influxDBPassword; - builder.Query = await new FormUrlEncodedContent (new[] { - new KeyValuePair("u",influxDBUserName) , - new KeyValuePair("p", influxDBPassword) , - new KeyValuePair("q", "CREATE DATABASE "+ dbName) - }).ReadAsStringAsync (); - HttpResponseMessage response = await client.GetAsync (builder.Uri); - - if ( response.StatusCode == HttpStatusCode.OK ) - { - var content = await response.Content.ReadAsStringAsync (); - return true; - } - } - catch ( HttpRequestException e ) + catch ( Exception e ) { - return false; + Console.WriteLine ("Unexpected exception of type {0} caught: {1}", + e.GetType (), e.Message); } return false; } - private static async Task PostToInfluxAsync(HttpClient client, Uri InfluxPath, string content) - { - ByteArrayContent requestContent = new ByteArrayContent (Encoding.UTF8.GetBytes (content)); - try - { - HttpResponseMessage response = await client.PostAsync (InfluxPath, requestContent); - - if ( response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.BadGateway || ( response.StatusCode == HttpStatusCode.InternalServerError && response.ReasonPhrase == "INKApi Error" ) ) //502 Connection refused - throw new UnauthorizedAccessException ("InfluxDB needs authentication. Check uname, pwd parameters"); - //if(response.StatusCode==HttpStatusCode.NotFound) - - else if ( response.StatusCode == HttpStatusCode.NoContent ) - return true; - else - return false; - } - catch ( HttpRequestException ex ) - { - return false; - } - catch ( Exception e ) - { - if ( e is UnauthorizedAccessException ) - throw e; - return false; - } - - } - - private static async Task ProcessPerfMonLog(string InputFileName, HttpClient client) + private static async Task ProcessPerfMonLog(string InputFileName, InfluxDBClient client) { try @@ -431,12 +311,11 @@ private static async Task ProcessPerfMonLog(string InputFileName, HttpClie var lineCount = 0; var failedCount = 0; StringBuilder content = new StringBuilder (); + var failureReasons = new Dictionary (); Stopwatch stopwatch = new Stopwatch (); stopwatch.Start (); - var influxAddress = new Uri (influxUrl + "/write?db=" + influxDB + "&precision=s"); - var firstLine = File.ReadLines (InputFileName).FirstOrDefault (); @@ -464,7 +343,7 @@ private static async Task ProcessPerfMonLog(string InputFileName, HttpClie IEnumerable> perfGroup; if ( filter != Filters.None ) { - dbStructure = await GetInfluxDBStructureAsync (client, new Uri (influxUrl + "/query?"), influxDB); + dbStructure = await client.GetInfluxDBStructureAsync (influxDBName); perfGroup = FilterPerfmonLogColumns (pecrfCounters, filterColumns, dbStructure).GroupBy (p => p.PerformanceObject); } else @@ -477,38 +356,42 @@ private static async Task ProcessPerfMonLog(string InputFileName, HttpClie { try { - if ( !await ProcessPerfmonLogLine (line, perfGroup, minOffset, pattern, client, influxAddress) ) + if ( !await ProcessPerfmonLogLine (line, perfGroup, minOffset, pattern, client) ) failedCount++; - lineCount++; - - if ( failedCount > 0 ) - Console.Write ("\r{0} Processed {1}, Failed - {2} ", stopwatch.Elapsed.ToString (@"hh\:mm\:ss"), lineCount, failedCount); - else - Console.Write ("\r{0} Processed {1} ", stopwatch.Elapsed.ToString (@"hh\:mm\:ss"), lineCount); } catch ( Exception e ) { - Console.WriteLine (e.InnerException.Message); - Debug.WriteLine (e.InnerException.Message); - break; + failedCount++; + var type = e.GetType (); + if ( failureReasons.ContainsKey (type) ) + failureReasons[type].Count++; + else + failureReasons.Add (type, new FailureTracker () { ExceptionType = type, Count = 1, Message = e.Message }); } - } + lineCount++; - stopwatch.Stop (); - //Debug.WriteLine("Done Async Processing, Time elapsed: {0}", stopwatch.Elapsed); + if ( failedCount > 0 ) + Console.Write ("\r{0} Processed {1}, Failed - {2} ", stopwatch.Elapsed.ToString (@"hh\:mm\:ss"), lineCount, failedCount); + else + Console.Write ("\r{0} Processed {1} ", stopwatch.Elapsed.ToString (@"hh\:mm\:ss"), lineCount); + } lineCount = 0; pecrfCounters.Clear (); - - - Console.Write ("\n Done!! Processed{0}, failed to insert{1}", lineCount, failedCount); + stopwatch.Stop (); + if ( failedCount > 0 ) + { + Console.WriteLine ("\n Done!! Processed {0}, failed to insert {1}", lineCount, failedCount); + foreach ( var f in failureReasons.Values ) + Console.WriteLine ("{0}:{1} - {2}", f.ExceptionType, f.Message, f.Count); + } } catch ( Exception e ) { - Console.WriteLine ("\rError Processing, Exception:{0}", e.Message); - Debug.WriteLine ("\rError Processing, Exception:{0}", e.Message); + Console.WriteLine ("\rError!! {0}:{1} - {2}", e.GetType ().Name, e.Message, e.StackTrace); + Console.WriteLine ("Error!! {0}:{1} - {2}", e.GetType ().Name, e.Message, e.StackTrace); return false; } return true; @@ -547,136 +430,138 @@ private static List FilterPerfmonLogColumns(List return columns; } - private static async Task ProcessPerfmonLogLine(string line, IEnumerable> perfGroup, int minOffset, Regex pattern, HttpClient client, Uri InfluxPath) + private static async Task ProcessPerfmonLogLine(string line, IEnumerable> perfGroup, int minOffset, Regex pattern, InfluxDBClient client) { StringBuilder content = new StringBuilder (); DateTime timeStamp; - try - { - var columns = pattern.Split (line.Replace ("\"", "")); - var columnCount = columns.Count (); - if ( !DateTime.TryParseExact (columns[0], timeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out timeStamp) ) - throw new FormatException ("Couldn't parse " + columns[0] + " using format " + timeFormat + ", check -timeformat argument"); - var epoch = timeStamp.AddMinutes (minOffset).ToEpoch (); + var columns = pattern.Split (line.Replace ("\"", "")); + var columnCount = columns.Count (); + + if ( !DateTime.TryParseExact (columns[0], timeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out timeStamp) ) + throw new FormatException ("Couldn't parse " + columns[0] + " using format " + timeFormat + ", check -timeformat argument"); + var epoch = timeStamp.AddMinutes (minOffset).ToEpoch (timePrecision); - double value = 0.0; - content.Clear (); - var lineStartIndex = 0; + double value = 0.0; + content.Clear (); + var lineStartIndex = 0; - foreach ( var group in perfGroup ) + foreach ( var group in perfGroup ) + { + foreach ( var hostGrp in group.GroupBy (p => p.Host) ) { - foreach ( var hostGrp in group.GroupBy (p => p.Host) ) - { - lineStartIndex = content.Length; - content.AppendFormat ("{0},Host={1}", group.Key, hostGrp.Key); + lineStartIndex = content.Length; + content.AppendFormat ("{0},Host={1}", group.Key, hostGrp.Key); - if ( tags != null ) - content.AppendFormat (",{0} ", tags); - else - content.Append (" "); + if ( tags != null ) + content.AppendFormat (",{0} ", tags); + else + content.Append (" "); - var useCounter = false; + var useCounter = false; - foreach ( var counter in hostGrp ) + foreach ( var counter in hostGrp ) + { + if ( !String.IsNullOrWhiteSpace (columns[counter.ColumnIndex]) && Double.TryParse (columns[counter.ColumnIndex], out value) ) { - if ( !String.IsNullOrWhiteSpace (columns[counter.ColumnIndex]) && Double.TryParse (columns[counter.ColumnIndex], out value) ) - { - content.AppendFormat ("{0}={1:0.00},", counter.CounterName, value); - useCounter = true; - - } - } + content.AppendFormat ("{0}={1:0.00},", counter.CounterName, value); + useCounter = true; - if ( useCounter ) - content.AppendFormat (" {0}\n", epoch); - else - { - content.Length = lineStartIndex; } } - } - //each group will have an ending comma which is not needed - content.Replace (", ", " "); - //remove last \n - content.Remove (content.Length - 1, 1); - //synchronous processing - if ( await PostToInfluxAsync (client, InfluxPath, content.ToString ()) ) - return true; - else - { - return false; + if ( useCounter ) + content.AppendFormat (" {0}\n", epoch); + else + { + content.Length = lineStartIndex; + } } } - catch ( UnauthorizedAccessException e ) - { - throw e; - } - catch ( Exception e ) + + //each group will have an ending comma which is not needed + content.Replace (", ", " "); + //remove last \n + content.Remove (content.Length - 1, 1); + //synchronous processing + if ( await client.PostRawValueAsync (influxDBName, TimePrecision.Seconds, content.ToString ()) ) + return true; + else { - Debug.WriteLine (e.Message); + return false; } - return false; + } - private static async Task ProcessGenericFile(string InputFileName, string tableName, HttpClient client) + private static async Task ProcessGenericFile(string InputFileName, string tableName, InfluxDBClient client) { try { StringBuilder content = new StringBuilder (); var lineCount = 0; var failedCount = 0; + Stopwatch stopwatch = new Stopwatch (); + stopwatch.Start (); - var influxAddress = new Uri (influxUrl + "/write?db=" + influxDB + "&precision=s"); - List columnHeaders; var firstLine = File.ReadLines (InputFileName).FirstOrDefault (); - var index = 0; columnHeaders = ParseGenericColumns (firstLine); Dictionary> dbStructure; - IEnumerable> perfGroup; if ( filter != Filters.None ) { var filterColumns = ParseGenericColumns (filteredColumns); - dbStructure = await GetInfluxDBStructureAsync (client, new Uri (influxUrl + "/query?"), influxDB); + dbStructure = await client.GetInfluxDBStructureAsync (influxDBName); columnHeaders = FilterGenericColumns (columnHeaders, filterColumns, dbStructure); } + var failureReasons = new Dictionary (); + + //Parallel.ForEach (File.ReadLines (inputFileName).Skip (1), (string line) => foreach ( var line in File.ReadLines (InputFileName).Skip (1) ) { try { - if ( !await ProcessGenericLine (line, columnHeaders, pattern, client, influxAddress) ) + if ( !await ProcessGenericLine (line, columnHeaders, pattern, client) ) failedCount++; - - lineCount++; - - if ( failedCount > 0 ) - Console.Write ("\r Processed {0}, Failed - {1} ", lineCount, failedCount); - else - Console.Write ("\r Processed {0} ", lineCount); - } catch ( Exception e ) { - Console.WriteLine (e.InnerException.Message); - Debug.WriteLine (e.InnerException.Message); - break; + failedCount++; + var type = e.GetType (); + if ( failureReasons.ContainsKey (type) ) + failureReasons[type].Count++; + else + failureReasons.Add (type, new FailureTracker () { ExceptionType = type, Count = 1, Message = e.Message }); } + + lineCount++; + + if ( failedCount > 0 ) + Console.Write ("\r{0} Processed {1}, Failed - {2} ", stopwatch.Elapsed.ToString (@"hh\:mm\:ss"), lineCount, failedCount); + else + Console.Write ("\r{0} Processed {1} ", stopwatch.Elapsed.ToString (@"hh\:mm\:ss"), lineCount); + } lineCount = 0; - Console.Write ("\n Done!! Processed{0}, failed to insert{1}", lineCount, failedCount); + + stopwatch.Stop (); + if ( failedCount > 0 ) + { + Console.WriteLine ("\n Done!! Processed {0}, failed to insert {1}", lineCount, failedCount); + foreach ( var f in failureReasons.Values ) + Console.WriteLine ("{0}:{1} - {2}", f.ExceptionType, f.Message, f.Count); + } + } catch ( Exception e ) { - Console.WriteLine ("\rError Processing, Exception:{0}", e.Message); - Debug.WriteLine ("\rError Processing, Exception:{0}", e.Message); + Console.WriteLine ("\rError!! {0}:{1} - {2}", e.GetType ().Name, e.Message, e.StackTrace); + Console.WriteLine ("Error!! {0}:{1} - {2}", e.GetType ().Name, e.Message, e.StackTrace); return false; } return true; @@ -686,7 +571,7 @@ private static List ParseGenericColumns(string headerLine) { var columns = new List (); int index = 0; - columns.AddRange (pattern.Split (headerLine).Select (s => new GenericColumn () {ColumnIndex=index++, ColumnHeader = s.Replace (influxIdentifiers, "_") })); + columns.AddRange (pattern.Split (headerLine).Select (s => new GenericColumn () { ColumnIndex = index++, ColumnHeader = s.Replace (influxIdentifiers, "_") })); return columns; } @@ -704,55 +589,45 @@ private static List FilterGenericColumns(List colu return columns; } - private async static Task ProcessGenericLine(string line, List columnHeaders, Regex pattern, HttpClient client, Uri InfluxPath) + private async static Task ProcessGenericLine(string line, List columnHeaders, Regex pattern, InfluxDBClient client) { - StringBuilder content = new StringBuilder (); + Dictionary values = new Dictionary (); + StringBuilder tagsCollection = new StringBuilder (); + DateTime timeStamp; - try - { - var columns = pattern.Split (line.Replace ("\"", "")); - var columnCount = columns.Count (); - if ( !DateTime.TryParseExact (columns[0], timeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out timeStamp) ) - throw new FormatException ("Couldn't parse " + columns[0] + " using format " + timeFormat + ", check -timeformat argument"); - var epoch = timeStamp.AddMinutes (utcOffsetMin).ToEpoch (); + var columns = pattern.Split (line.Replace ("\"", "")); + var columnCount = columns.Count (); - double value = 0.0; - content.AppendFormat ("{0}", tableName); - if ( tags != null ) - content.AppendFormat (",{0} ", tags); - else - content.Append (" "); + if ( !DateTime.TryParseExact (columns[0], timeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out timeStamp) ) + throw new FormatException ("Couldn't parse " + columns[0] + " using format " + timeFormat + ", check -timeformat argument"); + var epoch = timeStamp.AddMinutes (utcOffsetMin).ToEpoch (timePrecision); - foreach ( var c in columnHeaders ) + double value = 0.0; + + foreach ( var c in columnHeaders.Skip(1) ) + { + if ( Double.TryParse (columns[c.ColumnIndex], out value) ) { - if ( Double.TryParse (columns[c.ColumnIndex], out value) ) - content.AppendFormat ("{0}={1:0.00},", c.ColumnHeader, value); + values.Add (c.ColumnHeader, Math.Round(value,2)); + //break; } - - content.AppendFormat (" {0}\n", epoch); - //each group will have an ending comma which is not needed - content.Replace (", ", " "); - - //remove last \n - content.Remove (content.Length - 1, 1); - //synchronous processing - if ( await PostToInfluxAsync (client, InfluxPath, content.ToString ()) ) - return true; else - { - return false; - } - } - catch ( UnauthorizedAccessException e ) - { - throw e; + tagsCollection.AppendFormat ("{0}={1},", c.ColumnHeader, columns[c.ColumnIndex].Replace (influxIdentifiers, "_")); } - catch ( Exception e ) + + if ( tags != null ) + tagsCollection.Append (tags); + else + tagsCollection.Remove (tagsCollection.Length - 1, 1); + + if ( await client.PostValuesAsync (influxDBName, tableName, epoch, timePrecision, tagsCollection.ToString (), values) ) + return true; + else { - Debug.WriteLine (e.Message); + return false; } - return false; + } } } diff --git a/Influxer/Properties/AssemblyInfo.cs b/Influxer/Properties/AssemblyInfo.cs index cad9131..49db87d 100644 --- a/Influxer/Properties/AssemblyInfo.cs +++ b/Influxer/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration ("")] [assembly: AssemblyCompany ("Adys Tech")] [assembly: AssemblyProduct ("Influxer")] -[assembly: AssemblyCopyright ("Copyright © 2015")] +[assembly: AssemblyCopyright ("AdysTech © 2015")] [assembly: AssemblyTrademark ("")] [assembly: AssemblyCulture ("")]