I've created an application that exports data from a SQL database to Splunk over HTTP, and it works great. I've attempted to port it over to a CLR function so that I can run it as a SQL Stored Procedure, and it returns an interesting error when trying to log on to the management port:
Msg 6549, Level 16, State 1, Procedure DataExporter, Line 0
A .NET Framework error occurred during execution of user defined routine or aggregate 'DataExporter':
System.ArgumentException: The path is not of a legal form.
System.ArgumentException:
at System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength, Boolean expandShortPaths)
at System.IO.Path.GetFullPath(String path)
at System.Diagnostics.FileVersionInfo.GetFullPathWithAssert(String fileName)
at System.Diagnostics.FileVersionInfo.GetVersionInfo(String fileName)
at Splunk.HttpService.Send(String path, RequestMessage request)
at Splunk.Service.Login(String username, String password)
at DataExporter.Exporter.SplunkExport(List`1 messages)
at DataExporter.Exporter.DoExport(List`1 messages)
at DataExporter.GetRecordsAndExport.ExportJSON(Exporter export, SqlDataReader r, StringBuilder sb, StringWriter sw, String& returnvalue, Int32& recCount, List`1 messages)
at DataExporter.GetRecordsAndExport.DoIt(String QueryName, Database db, Exporter export)
at DataExporter.ExportType.Export(Database db)
at DataExporter.ExportData.Export360Data(Int32 ProfileID, SqlString dbName)
. User transaction, if any, will be rolled back.
Here is the code that makes the connection and sends the data:
public bool SplunkExport(List<string> messages)
{
Logger log = new Logger();
ServiceArgs svcArgs = new ServiceArgs();
svcArgs.App = splunkapp;
svcArgs.Host = ip;
svcArgs.Port = Convert.ToInt32(port);
Service splunkService = new Service(svcArgs);
try
{
splunkService.Login(user, pass);
Receiver splunkReceiver = new Receiver(splunkService);
var args = new Args();
args.Add("host", host);
args.Add("sourcetype", type);
args.Add("source", "Spector360");
using (var stream = splunkReceiver.Attach(args))
{
foreach (var message in messages)
{
log.WriteErrorMessage(message.ToString());
var bytes = Encoding.UTF8.GetBytes(message + "\r\n");
stream.Write(bytes, 0, bytes.Length);
stream.Flush();
}
}
return true;
}
catch (Exception e)
{
log.WriteErrorMessage(e.Message);
return false;
}
}
All the variables get the correct values, and this exact same code works when used in my forms application. The SDK documentation is kind of sparse. I am only trying to send data to Splunk over http. Is there something I am missing here, or a better way to do this?
Thanks in advance!
I've come up with a solution to this. I removed the SDK and used HttpWebRequest. Looks like the SDK targets .NET 4.5, and SQL Server does not seem to like it.
I've come up with a solution to this. I removed the SDK and used HttpWebRequest. Looks like the SDK targets .NET 4.5, and SQL Server does not seem to like it.
Here's the code I used:
public bool SplunkExport(List<string> messages)
{
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);
string baseuri = "https://" + ip + ":" + port;
string uri = "/services/collector";
HttpWebRequest client = (HttpWebRequest)WebRequest.Create((baseuri + uri));
client.ContentType = "application/json; charset=utf-8";
client.Method = "POST";
client.Headers["Authorization"] = "Splunk " + SplunkToken;
client.Headers["x-splunk-input-mode"] = "streaming";
try
{
using (Stream streamWriter = client.GetRequestStream())
{
foreach (var message in messages)
{
var m = "{\"sourcetype\":\"" + type + "\", \"host\":\"" + host + "\",\"event\": " + message + "}";
byte[] bytes = Encoding.UTF8.GetBytes(m);
streamWriter.Write(bytes, 0, bytes.Length);
streamWriter.Flush();
}
var httpResponse = (HttpWebResponse)client.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
return true;
}
catch
{
return false;
}
}
The messages list is a list of events in JSON format.