1
- using Exceptionless . Core . Configuration ;
1
+ using Exceptionless . Core . Configuration ;
2
2
using Exceptionless . Core . Extensions ;
3
3
using Exceptionless . Core . Mail ;
4
4
using Exceptionless . Core . Models ;
@@ -52,7 +52,7 @@ protected override async Task<JobResult> ProcessQueueEntryAsync(QueueEntryContex
52
52
53
53
bool shouldLog = ev . ProjectId != _appOptions . InternalProjectId ;
54
54
int sent = 0 ;
55
- if ( shouldLog ) _logger . LogTrace ( "Process notification: project={ProjectId} event={id } stack={stack }" , ev . ProjectId , ev . Id , ev . StackId ) ;
55
+ if ( shouldLog ) _logger . LogTrace ( "Process notification: project={ProjectId} event={Id } stack={Stack }" , ev . ProjectId , ev . Id , ev . StackId ) ;
56
56
57
57
var project = await _projectRepository . GetByIdAsync ( ev . ProjectId , o => o . Cache ( ) ) ;
58
58
if ( project is null )
@@ -63,79 +63,79 @@ protected override async Task<JobResult> ProcessQueueEntryAsync(QueueEntryContex
63
63
if ( shouldLog ) _logger . LogTrace ( "Loaded project: name={ProjectName}" , project . Name ) ;
64
64
65
65
// after the first 2 occurrences, don't send a notification for the same stack more then once every 30 minutes
66
- var lastTimeSentUtc = await _cache . GetAsync < DateTime > ( String . Concat ( "notify:stack-throttle:" , ev . StackId ) , DateTime . MinValue ) ;
67
- if ( wi is { TotalOccurrences : > 2 , IsRegression : false } && lastTimeSentUtc != DateTime . MinValue && lastTimeSentUtc > SystemClock . UtcNow . AddMinutes ( - 30 ) )
68
- {
69
- if ( shouldLog ) _logger . LogInformation ( "Skipping message because of stack throttling: last sent={LastSentUtc} occurrences={TotalOccurrences}" , lastTimeSentUtc , wi . TotalOccurrences ) ;
70
- return JobResult . Success ;
71
- }
66
+ var lastTimeSentUtc = await _cache . GetAsync < DateTime > ( String . Concat ( "notify:stack-throttle:" , ev . StackId ) , DateTime . MinValue ) ;
67
+ if ( wi is { TotalOccurrences : > 2 , IsRegression : false } && lastTimeSentUtc != DateTime . MinValue && lastTimeSentUtc > SystemClock . UtcNow . AddMinutes ( - 30 ) )
68
+ {
69
+ if ( shouldLog ) _logger . LogInformation ( "Skipping message because of stack throttling: last sent={LastSentUtc} occurrences={TotalOccurrences}" , lastTimeSentUtc , wi . TotalOccurrences ) ;
70
+ return JobResult . Success ;
71
+ }
72
+
73
+ if ( context . CancellationToken . IsCancellationRequested )
74
+ return JobResult . Cancelled ;
72
75
73
- if ( context . CancellationToken . IsCancellationRequested )
74
- return JobResult . Cancelled ;
76
+ // don't send more than 10 notifications for a given project every 30 minutes
77
+ var projectTimeWindow = TimeSpan . FromMinutes ( 30 ) ;
78
+ string cacheKey = String . Concat ( "notify:project-throttle:" , ev . ProjectId , "-" , SystemClock . UtcNow . Floor ( projectTimeWindow ) . Ticks ) ;
79
+ double notificationCount = await _cache . IncrementAsync ( cacheKey , 1 , projectTimeWindow ) ;
80
+ if ( notificationCount > 10 && ! wi . IsRegression )
81
+ {
82
+ if ( shouldLog ) _logger . LogInformation ( "Skipping message because of project throttling: count={NotificationCount}" , notificationCount ) ;
83
+ return JobResult . Success ;
84
+ }
75
85
76
- // don't send more than 10 notifications for a given project every 30 minutes
77
- var projectTimeWindow = TimeSpan . FromMinutes ( 30 ) ;
78
- string cacheKey = String . Concat ( "notify:project-throttle:" , ev . ProjectId , "-" , SystemClock . UtcNow . Floor ( projectTimeWindow ) . Ticks ) ;
79
- double notificationCount = await _cache . IncrementAsync ( cacheKey , 1 , projectTimeWindow ) ;
80
- if ( notificationCount > 10 && ! wi . IsRegression )
86
+ foreach ( var kv in project . NotificationSettings )
87
+ {
88
+ var settings = kv . Value ;
89
+ if ( shouldLog ) _logger . LogTrace ( "Processing notification: {Key}" , kv . Key ) ;
90
+
91
+ bool isCritical = ev . IsCritical ( ) ;
92
+ bool shouldReportNewError = settings . ReportNewErrors && wi . IsNew && ev . IsError ( ) ;
93
+ bool shouldReportCriticalError = settings . ReportCriticalErrors && isCritical && ev . IsError ( ) ;
94
+ bool shouldReportRegression = settings . ReportEventRegressions && wi . IsRegression ;
95
+ bool shouldReportNewEvent = settings . ReportNewEvents && wi . IsNew ;
96
+ bool shouldReportCriticalEvent = settings . ReportCriticalEvents && isCritical ;
97
+ bool shouldReport = shouldReportNewError || shouldReportCriticalError || shouldReportRegression || shouldReportNewEvent || shouldReportCriticalEvent ;
98
+
99
+ if ( shouldLog )
81
100
{
82
- if ( shouldLog ) _logger . LogInformation ( "Skipping message because of project throttling: count={NotificationCount} ", notificationCount ) ;
83
- return JobResult . Success ;
101
+ _logger . LogTrace ( "Settings: new error={ReportNewErrors} critical error={ReportCriticalErrors} regression={ReportEventRegressions} new={ReportNewEvents} critical={ReportCriticalEvents} ", settings . ReportNewErrors , settings . ReportCriticalErrors , settings . ReportEventRegressions , settings . ReportNewEvents , settings . ReportCriticalEvents ) ;
102
+ _logger . LogTrace ( "Should process: new error={ShouldReportNewError} critical error={ShouldReportCriticalError} regression={ShouldReportRegression} new={ShouldReportNewEvent} critical={ShouldReportCriticalEvent}" , shouldReportNewError , shouldReportCriticalError , shouldReportRegression , shouldReportNewEvent , shouldReportCriticalEvent ) ;
84
103
}
85
-
86
- foreach ( var kv in project . NotificationSettings )
104
+ var request = ev . GetRequestInfo ( ) ;
105
+ // check for known bots if the user has elected to not report them
106
+ if ( shouldReport && ! String . IsNullOrEmpty ( request ? . UserAgent ) )
87
107
{
88
- var settings = kv . Value ;
89
- if ( shouldLog ) _logger . LogTrace ( "Processing notification: {Key}" , kv . Key ) ;
90
-
91
- bool isCritical = ev . IsCritical ( ) ;
92
- bool shouldReportNewError = settings . ReportNewErrors && wi . IsNew && ev . IsError ( ) ;
93
- bool shouldReportCriticalError = settings . ReportCriticalErrors && isCritical && ev . IsError ( ) ;
94
- bool shouldReportRegression = settings . ReportEventRegressions && wi . IsRegression ;
95
- bool shouldReportNewEvent = settings . ReportNewEvents && wi . IsNew ;
96
- bool shouldReportCriticalEvent = settings . ReportCriticalEvents && isCritical ;
97
- bool shouldReport = shouldReportNewError || shouldReportCriticalError || shouldReportRegression || shouldReportNewEvent || shouldReportCriticalEvent ;
98
-
99
- if ( shouldLog )
100
- {
101
- _logger . LogTrace ( "Settings: new error={ReportNewErrors} critical error={ReportCriticalErrors} regression={ReportEventRegressions} new={ReportNewEvents} critical={ReportCriticalEvents}" , settings . ReportNewErrors , settings . ReportCriticalErrors , settings . ReportEventRegressions , settings . ReportNewEvents , settings . ReportCriticalEvents ) ;
102
- _logger . LogTrace ( "Should process: new error={ShouldReportNewError} critical error={ShouldReportCriticalError} regression={ShouldReportRegression} new={ShouldReportNewEvent} critical={ShouldReportCriticalEvent}" , shouldReportNewError , shouldReportCriticalError , shouldReportRegression , shouldReportNewEvent , shouldReportCriticalEvent ) ;
103
- }
104
- var request = ev . GetRequestInfo ( ) ;
105
- // check for known bots if the user has elected to not report them
106
- if ( shouldReport && ! String . IsNullOrEmpty ( request ? . UserAgent ) )
107
- {
108
- var botPatterns = project . Configuration . Settings . GetStringCollection ( SettingsDictionary . KnownKeys . UserAgentBotPatterns ) . ToList ( ) ;
109
-
110
- var info = await _parser . ParseAsync ( request . UserAgent ) ;
111
- if ( info is not null && info . Device . IsSpider || request . UserAgent . AnyWildcardMatches ( botPatterns ) )
112
- {
113
- shouldReport = false ;
114
- if ( shouldLog ) _logger . LogInformation ( "Skipping because event is from a bot {UserAgent}" , request . UserAgent ) ;
115
- }
116
- }
108
+ var botPatterns = project . Configuration . Settings . GetStringCollection ( SettingsDictionary . KnownKeys . UserAgentBotPatterns ) . ToList ( ) ;
117
109
118
- if ( ! shouldReport )
119
- continue ;
120
-
121
- bool processed = kv . Key switch
110
+ var info = await _parser . ParseAsync ( request . UserAgent ) ;
111
+ if ( info is not null && info . Device . IsSpider || request . UserAgent . AnyWildcardMatches ( botPatterns ) )
122
112
{
123
- Project . NotificationIntegrations . Slack => await _slackService
124
- . SendEventNoticeAsync ( ev , project , wi . IsNew , wi . IsRegression )
125
- ,
126
- _ => await SendEmailNotificationAsync ( kv . Key , project , ev , wi , shouldLog )
127
- } ;
128
-
129
- if ( shouldLog ) _logger . LogTrace ( "Finished processing notification: {Key}" , kv . Key ) ;
130
- if ( processed )
131
- sent ++ ;
113
+ shouldReport = false ;
114
+ if ( shouldLog ) _logger . LogInformation ( "Skipping because event is from a bot {UserAgent}" , request . UserAgent ) ;
115
+ }
132
116
}
133
117
134
- // if we sent any notifications, mark the last time a notification for this stack was sent.
135
- if ( sent > 0 )
118
+ if ( ! shouldReport )
119
+ continue ;
120
+
121
+ bool processed = kv . Key switch
136
122
{
123
+ Project . NotificationIntegrations . Slack => await _slackService
124
+ . SendEventNoticeAsync ( ev , project , wi . IsNew , wi . IsRegression )
125
+ ,
126
+ _ => await SendEmailNotificationAsync ( kv . Key , project , ev , wi , shouldLog )
127
+ } ;
128
+
129
+ if ( shouldLog ) _logger . LogTrace ( "Finished processing notification: {Key}" , kv . Key ) ;
130
+ if ( processed )
131
+ sent ++ ;
132
+ }
133
+
134
+ // if we sent any notifications, mark the last time a notification for this stack was sent.
135
+ if ( sent > 0 )
136
+ {
137
137
await _cache . SetAsync ( String . Concat ( "notify:stack-throttle:" , ev . StackId ) , SystemClock . UtcNow , SystemClock . UtcNow . AddMinutes ( 15 ) ) ;
138
- if ( shouldLog ) _logger . LogInformation ( "Notifications sent: event={id } stack={stack } count={SentCount}" , ev . Id , ev . StackId , sent ) ;
138
+ if ( shouldLog ) _logger . LogInformation ( "Notifications sent: event={Id } stack={Stack } count={SentCount}" , ev . Id , ev . StackId , sent ) ;
139
139
}
140
140
}
141
141
return JobResult . Success ;
@@ -164,7 +164,7 @@ private async Task<bool> SendEmailNotificationAsync(string userId, Project proje
164
164
165
165
if ( ! user . OrganizationIds . Contains ( project . OrganizationId ) )
166
166
{
167
- if ( shouldLog ) _logger . LogError ( "Unauthorized user: project={ProjectId} user={UserId} organization={organization } event={id }" , project . Id , userId , project . OrganizationId , ev . Id ) ;
167
+ if ( shouldLog ) _logger . LogError ( "Unauthorized user: project={ProjectId} user={UserId} organization={Organization } event={Id }" , project . Id , userId , project . OrganizationId , ev . Id ) ;
168
168
return false ;
169
169
}
170
170
0 commit comments