Skip to content

Commit 9fa9008

Browse files
Use TrackException for errors (#206)
1 parent 8e36261 commit 9fa9008

File tree

4 files changed

+63
-32
lines changed

4 files changed

+63
-32
lines changed

src/Microsoft.Azure.WebJobs.Extensions.Sql.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
</PropertyGroup>
2424

2525
<ItemGroup>
26-
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.19.0" />
26+
<PackageReference Include="Microsoft.ApplicationInsights" Version="2.17.0" />
2727
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.*" />
2828
<PackageReference Include="Microsoft.Data.SqlClient" Version="3.0.*" />
2929
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.*" PrivateAssets="All" />

src/SqlAsyncCollector.cs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ public async Task FlushAsync(CancellationToken cancellationToken = default)
125125
this._rows.Clear();
126126
}
127127
}
128+
catch (Exception ex)
129+
{
130+
TelemetryInstance.TrackException(TelemetryErrorName.FlushAsync, ex);
131+
throw;
132+
}
128133
finally
129134
{
130135
this._rowLock.Release();
@@ -177,7 +182,7 @@ private async Task UpsertRowsAsync(IEnumerable<T> rows, SqlAttribute attribute,
177182
{
178183
string message = $"The following properties in {typeof(T)} do not exist in the table {fullTableName}: {string.Join(", ", extraProperties.ToArray())}.";
179184
var ex = new InvalidOperationException(message);
180-
TelemetryInstance.TrackError(TelemetryErrorName.PropsNotExistOnTable, ex, props);
185+
TelemetryInstance.TrackException(TelemetryErrorName.PropsNotExistOnTable, ex, props);
181186
throw ex;
182187
}
183188

@@ -214,12 +219,12 @@ private async Task UpsertRowsAsync(IEnumerable<T> rows, SqlAttribute attribute,
214219
{
215220
try
216221
{
217-
TelemetryInstance.TrackError(TelemetryErrorName.Upsert, ex, props);
222+
TelemetryInstance.TrackException(TelemetryErrorName.Upsert, ex, props);
218223
transaction.Rollback();
219224
}
220225
catch (Exception ex2)
221226
{
222-
TelemetryInstance.TrackError(TelemetryErrorName.UpsertRollback, ex2, props);
227+
TelemetryInstance.TrackException(TelemetryErrorName.UpsertRollback, ex2, props);
223228
string message2 = $"Encountered exception during upsert and rollback.";
224229
throw new AggregateException(message2, new List<Exception> { ex, ex2 });
225230
}
@@ -467,7 +472,7 @@ public static async Task<TableInformation> RetrieveTableInformationAsync(SqlConn
467472
// Since this doesn't rethrow make sure we stop here too (don't use finally because we want the execution time to be the same here and in the
468473
// overall event but we also only want to send the GetCaseSensitivity event if it succeeds)
469474
caseSensitiveSw.Stop();
470-
TelemetryInstance.TrackError(TelemetryErrorName.GetCaseSensitivity, ex, sqlConnProps);
475+
TelemetryInstance.TrackException(TelemetryErrorName.GetCaseSensitivity, ex, sqlConnProps);
471476
logger.LogWarning($"Encountered exception while retrieving database collation: {ex}. Case insensitive behavior will be used by default.");
472477
}
473478

@@ -490,7 +495,7 @@ public static async Task<TableInformation> RetrieveTableInformationAsync(SqlConn
490495
}
491496
catch (Exception ex)
492497
{
493-
TelemetryInstance.TrackError(TelemetryErrorName.GetColumnDefinitions, ex, sqlConnProps);
498+
TelemetryInstance.TrackException(TelemetryErrorName.GetColumnDefinitions, ex, sqlConnProps);
494499
// Throw a custom error so that it's easier to decipher.
495500
string message = $"Encountered exception while retrieving column names and types for table {table}. Cannot generate upsert command without them.";
496501
throw new InvalidOperationException(message, ex);
@@ -500,7 +505,7 @@ public static async Task<TableInformation> RetrieveTableInformationAsync(SqlConn
500505
{
501506
string message = $"Table {table} does not exist.";
502507
var ex = new InvalidOperationException(message);
503-
TelemetryInstance.TrackError(TelemetryErrorName.GetColumnDefinitionsTableDoesNotExist, ex, sqlConnProps);
508+
TelemetryInstance.TrackException(TelemetryErrorName.GetColumnDefinitionsTableDoesNotExist, ex, sqlConnProps);
504509
throw ex;
505510
}
506511

@@ -521,7 +526,7 @@ public static async Task<TableInformation> RetrieveTableInformationAsync(SqlConn
521526
}
522527
catch (Exception ex)
523528
{
524-
TelemetryInstance.TrackError(TelemetryErrorName.GetPrimaryKeys, ex, sqlConnProps);
529+
TelemetryInstance.TrackException(TelemetryErrorName.GetPrimaryKeys, ex, sqlConnProps);
525530
// Throw a custom error so that it's easier to decipher.
526531
string message = $"Encountered exception while retrieving primary keys for table {table}. Cannot generate upsert command without them.";
527532
throw new InvalidOperationException(message, ex);
@@ -531,7 +536,7 @@ public static async Task<TableInformation> RetrieveTableInformationAsync(SqlConn
531536
{
532537
string message = $"Did not retrieve any primary keys for {table}. Cannot generate upsert command without them.";
533538
var ex = new InvalidOperationException(message);
534-
TelemetryInstance.TrackError(TelemetryErrorName.NoPrimaryKeys, ex, sqlConnProps);
539+
TelemetryInstance.TrackException(TelemetryErrorName.NoPrimaryKeys, ex, sqlConnProps);
535540
throw ex;
536541
}
537542

@@ -548,7 +553,7 @@ public static async Task<TableInformation> RetrieveTableInformationAsync(SqlConn
548553
{
549554
string message = $"All primary keys for SQL table {table} need to be found in '{typeof(T)}.' Missing primary keys: [{string.Join(",", missingPrimaryKeysFromPOCO)}]";
550555
var ex = new InvalidOperationException(message);
551-
TelemetryInstance.TrackError(TelemetryErrorName.MissingPrimaryKeys, ex, sqlConnProps);
556+
TelemetryInstance.TrackException(TelemetryErrorName.MissingPrimaryKeys, ex, sqlConnProps);
552557
throw ex;
553558
}
554559

src/SqlConverters.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public SqlCommand Convert(SqlAttribute attribute)
5555
{
5656
{ TelemetryPropertyName.Type.ToString(), ConvertType.SqlCommand.ToString() }
5757
};
58-
TelemetryInstance.TrackError(TelemetryErrorName.Convert, ex, props);
58+
TelemetryInstance.TrackException(TelemetryErrorName.Convert, ex, props);
5959
throw;
6060
}
6161
}
@@ -103,7 +103,7 @@ public async Task<IEnumerable<T>> ConvertAsync(SqlAttribute attribute, Cancellat
103103
{
104104
{ TelemetryPropertyName.Type.ToString(), ConvertType.IEnumerable.ToString() }
105105
};
106-
TelemetryInstance.TrackError(TelemetryErrorName.Convert, ex, props);
106+
TelemetryInstance.TrackException(TelemetryErrorName.Convert, ex, props);
107107
throw;
108108
}
109109
}
@@ -133,7 +133,7 @@ async Task<string> IAsyncConverter<SqlAttribute, string>.ConvertAsync(SqlAttribu
133133
{
134134
{ TelemetryPropertyName.Type.ToString(), ConvertType.Json.ToString() }
135135
};
136-
TelemetryInstance.TrackError(TelemetryErrorName.Convert, ex, props);
136+
TelemetryInstance.TrackException(TelemetryErrorName.Convert, ex, props);
137137
throw;
138138
}
139139
}
@@ -174,7 +174,7 @@ IAsyncEnumerable<T> IConverter<SqlAttribute, IAsyncEnumerable<T>>.Convert(SqlAtt
174174
{
175175
{ TelemetryPropertyName.Type.ToString(), ConvertType.IAsyncEnumerable.ToString() }
176176
};
177-
TelemetryInstance.TrackError(TelemetryErrorName.Convert, ex, props);
177+
TelemetryInstance.TrackException(TelemetryErrorName.Convert, ex, props);
178178
throw;
179179
}
180180
}

src/Telemetry/Telemetry.cs

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,30 @@ public void TrackEvent(TelemetryEventName eventName, IDictionary<string, string>
109109
}
110110
}
111111

112+
public void TrackException(TelemetryErrorName errorName, Exception exception, IDictionary<string, string> properties = null,
113+
IDictionary<string, double> measurements = null)
114+
{
115+
try
116+
{
117+
if (!this._initialized || !this.Enabled)
118+
{
119+
return;
120+
}
121+
this._logger.LogInformation($"Sending exception event: {exception.Message}");
122+
properties ??= new Dictionary<string, string>();
123+
properties.Add(TelemetryPropertyName.ErrorName.ToString(), errorName.ToString());
124+
//continue task in existing parallel thread
125+
this._trackEventTask = this._trackEventTask.ContinueWith(
126+
x => this.TrackExceptionTask(exception, properties, measurements)
127+
);
128+
}
129+
catch (Exception ex)
130+
{
131+
// We don't want errors sending telemetry to break the app, so just log and move on
132+
Debug.Fail($"Error sending exception event : {ex.Message}");
133+
}
134+
}
135+
112136
/// <summary>
113137
/// Sends an event with the specified duration added as a measurement
114138
/// </summary>
@@ -176,31 +200,32 @@ public void TrackConvert(ConvertType type, IDictionary<string, string> propertie
176200
}
177201
}
178202

179-
/// <summary>
180-
/// Sends an error event for the given exception information
181-
/// </summary>
182-
/// <param name="errorName">A generic name identifying where the error occured (e.g. Upsert)</param>
183-
/// <param name="properties"></param>
184-
/// <param name="measurements"></param>
185-
public void TrackError(TelemetryErrorName errorName, Exception ex, IDictionary<string, string> properties = null,
186-
IDictionary<string, double> measurements = null)
203+
private void TrackEventTask(
204+
string eventName,
205+
IDictionary<string, string> properties,
206+
IDictionary<string, double> measurements)
187207
{
208+
if (this._client is null)
209+
{
210+
return;
211+
}
212+
188213
try
189214
{
190-
properties ??= new Dictionary<string, string>();
191-
properties.Add(TelemetryPropertyName.ErrorName.ToString(), errorName.ToString());
192-
properties.AddExceptionProps(ex);
193-
this.TrackEvent(TelemetryEventName.Error, properties, measurements);
215+
Dictionary<string, string> eventProperties = this.GetEventProperties(properties);
216+
Dictionary<string, double> eventMeasurements = this.GetEventMeasures(measurements);
217+
218+
this._client.TrackEvent($"{EventsNamespace}/{eventName}", eventProperties, eventMeasurements);
219+
this._client.Flush();
194220
}
195-
catch (Exception ex2)
221+
catch (Exception e)
196222
{
197-
// We don't want errors sending telemetry to break the app, so just log and move on
198-
Debug.Fail($"Error sending error event {errorName} : {ex2.Message}");
223+
Debug.Fail(e.ToString());
199224
}
200225
}
201226

202-
private void TrackEventTask(
203-
string eventName,
227+
private void TrackExceptionTask(
228+
Exception exception,
204229
IDictionary<string, string> properties,
205230
IDictionary<string, double> measurements)
206231
{
@@ -214,7 +239,7 @@ private void TrackEventTask(
214239
Dictionary<string, string> eventProperties = this.GetEventProperties(properties);
215240
Dictionary<string, double> eventMeasurements = this.GetEventMeasures(measurements);
216241

217-
this._client.TrackEvent($"{EventsNamespace}/{eventName}", eventProperties, eventMeasurements);
242+
this._client.TrackException(exception, eventProperties, eventMeasurements);
218243
this._client.Flush();
219244
}
220245
catch (Exception e)
@@ -329,6 +354,7 @@ public enum TelemetryMeasureName
329354
public enum TelemetryErrorName
330355
{
331356
Convert,
357+
FlushAsync,
332358
GetCaseSensitivity,
333359
GetColumnDefinitions,
334360
GetColumnDefinitionsTableDoesNotExist,

0 commit comments

Comments
 (0)