Browse Source

UDC: use system time only on startup and then work with timespans relative to that. This ensures we don't collect confusing data if the system time changes while SharpDevelop is running.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5926 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Daniel Grunwald 15 years ago
parent
commit
65860bf555
  1. 38
      src/AddIns/Misc/UsageDataCollector/UsageDataCollector/UsageDataSessionWriter.cs

38
src/AddIns/Misc/UsageDataCollector/UsageDataCollector/UsageDataSessionWriter.cs

@ -35,6 +35,8 @@ namespace ICSharpCode.UsageDataCollector
SQLiteConnection connection; SQLiteConnection connection;
long sessionID; long sessionID;
Timer timer; Timer timer;
DateTime startTime;
Stopwatch stopwatch;
/// <summary> /// <summary>
/// Opens/Creates the database and starts writing a new session to it. /// Opens/Creates the database and starts writing a new session to it.
@ -172,10 +174,13 @@ namespace ICSharpCode.UsageDataCollector
void StartSession() void StartSession()
{ {
startTime = DateTime.UtcNow;
stopwatch = Stopwatch.StartNew();
using (SQLiteTransaction transaction = this.connection.BeginTransaction()) { using (SQLiteTransaction transaction = this.connection.BeginTransaction()) {
using (SQLiteCommand cmd = this.connection.CreateCommand()) { using (SQLiteCommand cmd = this.connection.CreateCommand()) {
cmd.CommandText = "INSERT INTO Sessions (startTime) VALUES (datetime('now'));" + cmd.CommandText = "INSERT INTO Sessions (startTime) VALUES (?);" +
"SELECT last_insert_rowid();"; "SELECT last_insert_rowid();";
cmd.Parameters.Add(new SQLiteParameter { Value = TimeToString(startTime) });
sessionID = (long)cmd.ExecuteScalar(); sessionID = (long)cmd.ExecuteScalar();
} }
AddEnvironmentData(GetDefaultEnvironmentData()); AddEnvironmentData(GetDefaultEnvironmentData());
@ -183,12 +188,18 @@ namespace ICSharpCode.UsageDataCollector
} }
} }
DateTime GetNow()
{
return startTime + stopwatch.Elapsed;
}
void EndSession() void EndSession()
{ {
using (SQLiteTransaction transaction = this.connection.BeginTransaction()) { using (SQLiteTransaction transaction = this.connection.BeginTransaction()) {
FlushOutstandingChanges(); FlushOutstandingChanges();
using (SQLiteCommand cmd = this.connection.CreateCommand()) { using (SQLiteCommand cmd = this.connection.CreateCommand()) {
cmd.CommandText = "UPDATE Sessions SET endTime = datetime('now') WHERE id = ?;"; cmd.CommandText = "UPDATE Sessions SET endTime = ? WHERE id = ?;";
cmd.Parameters.Add(new SQLiteParameter { Value = TimeToString(GetNow()) });
cmd.Parameters.Add(new SQLiteParameter { Value = sessionID }); cmd.Parameters.Add(new SQLiteParameter { Value = sessionID });
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
@ -239,7 +250,7 @@ namespace ICSharpCode.UsageDataCollector
lock (lockObj) { lock (lockObj) {
if (isDisposed) if (isDisposed)
throw new ObjectDisposedException(GetType().Name); throw new ObjectDisposedException(GetType().Name);
FeatureUse featureUse = new FeatureUse(this); FeatureUse featureUse = new FeatureUse(this, GetNow());
featureUse.name = featureName; featureUse.name = featureName;
featureUse.activation = activationMethod; featureUse.activation = activationMethod;
delayedStart.Enqueue(featureUse); delayedStart.Enqueue(featureUse);
@ -252,11 +263,16 @@ namespace ICSharpCode.UsageDataCollector
lock (lockObj) { lock (lockObj) {
if (isDisposed) if (isDisposed)
return; return;
featureUse.endTime = DateTime.UtcNow; featureUse.endTime = GetNow();
delayedEnd.Enqueue(featureUse); delayedEnd.Enqueue(featureUse);
} }
} }
static string TimeToString(DateTime time)
{
return time.ToString("yyyy-MM-dd hh:mm:ss", CultureInfo.InvariantCulture);
}
void FlushOutstandingChanges() void FlushOutstandingChanges()
{ {
//Console.WriteLine("Flushing {0} starts and {1} ends", delayedStart.Count, delayedEnd.Count); //Console.WriteLine("Flushing {0} starts and {1} ends", delayedStart.Count, delayedEnd.Count);
@ -275,7 +291,7 @@ namespace ICSharpCode.UsageDataCollector
cmd.Parameters.Add(activationMethod = new SQLiteParameter()); cmd.Parameters.Add(activationMethod = new SQLiteParameter());
while (delayedStart.Count > 0) { while (delayedStart.Count > 0) {
FeatureUse use = delayedStart.Dequeue(); FeatureUse use = delayedStart.Dequeue();
time.Value = use.startTime.ToString("yyyy-MM-dd hh:mm:ss", CultureInfo.InvariantCulture); time.Value = TimeToString(use.startTime);
feature.Value = use.name; feature.Value = use.name;
activationMethod.Value = use.activation; activationMethod.Value = use.activation;
@ -291,7 +307,7 @@ namespace ICSharpCode.UsageDataCollector
cmd.Parameters.Add(id = new SQLiteParameter()); cmd.Parameters.Add(id = new SQLiteParameter());
while (delayedEnd.Count > 0) { while (delayedEnd.Count > 0) {
FeatureUse use = delayedEnd.Dequeue(); FeatureUse use = delayedEnd.Dequeue();
endTime.Value = use.endTime.ToString("yyyy-MM-dd hh:mm:ss", CultureInfo.InvariantCulture); endTime.Value = TimeToString(use.endTime);
id.Value = use.rowId; id.Value = use.rowId;
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
} }
@ -424,8 +440,9 @@ namespace ICSharpCode.UsageDataCollector
// first, insert the exception (it's most important to have) // first, insert the exception (it's most important to have)
using (SQLiteCommand cmd = this.connection.CreateCommand()) { using (SQLiteCommand cmd = this.connection.CreateCommand()) {
cmd.CommandText = "INSERT INTO Exceptions (session, time, type, stackTrace)" + cmd.CommandText = "INSERT INTO Exceptions (session, time, type, stackTrace)" +
" VALUES (?, datetime('now'), ?, ?);"; " VALUES (?, ?, ?, ?);";
cmd.Parameters.Add(new SQLiteParameter { Value = sessionID }); cmd.Parameters.Add(new SQLiteParameter { Value = sessionID });
cmd.Parameters.Add(new SQLiteParameter { Value = TimeToString(GetNow()) });
cmd.Parameters.Add(new SQLiteParameter { Value = exceptionType }); cmd.Parameters.Add(new SQLiteParameter { Value = exceptionType });
cmd.Parameters.Add(new SQLiteParameter { Value = stacktrace }); cmd.Parameters.Add(new SQLiteParameter { Value = stacktrace });
cmd.ExecuteNonQuery(); cmd.ExecuteNonQuery();
@ -458,14 +475,15 @@ namespace ICSharpCode.UsageDataCollector
/// </summary> /// </summary>
public sealed class FeatureUse public sealed class FeatureUse
{ {
internal readonly DateTime startTime = DateTime.UtcNow; internal readonly DateTime startTime;
internal DateTime endTime; internal DateTime endTime;
internal string name, activation; internal string name, activation;
internal long rowId; internal long rowId;
UsageDataSessionWriter writer; readonly UsageDataSessionWriter writer;
internal FeatureUse(UsageDataSessionWriter writer) internal FeatureUse(UsageDataSessionWriter writer, DateTime startTime)
{ {
this.startTime = startTime;
this.writer = writer; this.writer = writer;
} }

Loading…
Cancel
Save