11using System ;
22using System . Data ;
3+ using System . Diagnostics ;
34using System . Threading ;
45using System . Threading . Tasks ;
56using Hangfire ;
67using Hangfire . Annotations ;
78using Hangfire . Client ;
89using Hangfire . Common ;
10+ using Hangfire . Diagnostics ;
11+ using Hangfire . InMemory ;
912using Hangfire . Server ;
1013using Hangfire . SqlServer ;
1114using Hangfire . States ;
15+ using Microsoft . AspNetCore . Mvc . Infrastructure ;
16+ using Microsoft . Extensions . Configuration ;
1217using Microsoft . Extensions . DependencyInjection ;
1318using Microsoft . Extensions . DependencyInjection . Extensions ;
1419using Microsoft . Extensions . Hosting ;
1520using Microsoft . Extensions . Logging ;
21+ using OpenTelemetry . Trace ;
1622
1723namespace NetCoreSample
1824{
1925 class Program
2026 {
27+ // To use in-memory store instead of database:
28+ // dotnet run -- --UseInMemory true
29+
30+ // To show trace console exporter output:
31+ // dotnet run -- --TraceConsoleExporter true
32+
33+ public static readonly ActivitySource ActivitySource = new ActivitySource ( nameof ( NetCoreSample ) ) ;
34+
2135 static async Task Main ( string [ ] args )
2236 {
23- var host = new HostBuilder ( )
24- . ConfigureLogging ( x => x . AddConsole ( ) . SetMinimumLevel ( LogLevel . Information ) )
37+ var host = Host . CreateDefaultBuilder ( args )
38+ . ConfigureLogging ( x => x
39+ . AddSimpleConsole ( )
40+ . SetMinimumLevel ( LogLevel . Information ) )
2541 . ConfigureServices ( ( hostContext , services ) =>
2642 {
2743 services . Configure < HostOptions > ( option =>
@@ -49,19 +65,40 @@ static async Task Main(string[] args)
4965 services . TryAddSingleton < IBackgroundJobStateChanger > ( x => new CustomBackgroundJobStateChanger (
5066 new BackgroundJobStateChanger ( x . GetRequiredService < IJobFilterProvider > ( ) ) ) ) ;
5167
52- services . AddHangfire ( ( provider , configuration ) => configuration
68+ var useInMemory = hostContext . Configuration . GetValue < bool > ( "UseInMemory" ) ;
69+ services . AddHangfire ( ( provider , configuration ) => {
70+ configuration
5371 . SetDataCompatibilityLevel ( CompatibilityLevel . Version_170 )
54- . UseSimpleAssemblyNameTypeSerializer ( )
55- . UseSqlServerStorage (
56- @"Server=.\;Database=Hangfire.Sample;Trusted_Connection=True;" ,
57- provider . GetRequiredService < SqlServerStorageOptions > ( ) ) ) ;
72+ . UseSimpleAssemblyNameTypeSerializer ( ) ;
73+ if ( useInMemory ) {
74+ configuration . UseInMemoryStorage ( ) ;
75+ }
76+ else
77+ {
78+ configuration . UseSqlServerStorage (
79+ @"Server=.\;Database=Hangfire.Sample;Trusted_Connection=True;" ,
80+ provider . GetRequiredService < SqlServerStorageOptions > ( ) ) ;
81+ }
82+ } ) ;
5883
5984 services . AddHostedService < RecurringJobsService > ( ) ;
85+ services . AddHostedService < BackgroundJobsService > ( ) ;
6086 services . AddHangfireServer ( options =>
6187 {
6288 options . StopTimeout = TimeSpan . FromSeconds ( 15 ) ;
6389 options . ShutdownTimeout = TimeSpan . FromSeconds ( 30 ) ;
6490 } ) ;
91+
92+ var traceConsoleExporter = hostContext . Configuration . GetValue < bool > ( "TraceConsoleExporter" ) ;
93+ services . AddOpenTelemetry ( )
94+ . WithTracing ( tracing => {
95+ tracing . AddSource ( DiagnosticHeaders . DefaultListenerName ) ;
96+ tracing . AddSource ( nameof ( NetCoreSample ) ) ;
97+ if ( traceConsoleExporter )
98+ {
99+ tracing . AddConsoleExporter ( ) ;
100+ }
101+ } ) ;
65102 } )
66103 . Build ( ) ;
67104
@@ -123,24 +160,35 @@ internal class RecurringJobsService : BackgroundService
123160 {
124161 private readonly IBackgroundJobClient _backgroundJobs ;
125162 private readonly IRecurringJobManager _recurringJobs ;
126- private readonly ILogger < RecurringJobScheduler > _logger ;
163+ private readonly ILogger < RecurringJobsService > _logger ;
164+ private readonly ILoggerFactory _loggerFactory ;
127165
128166 public RecurringJobsService (
129167 [ NotNull ] IBackgroundJobClient backgroundJobs ,
130168 [ NotNull ] IRecurringJobManager recurringJobs ,
131- [ NotNull ] ILogger < RecurringJobScheduler > logger )
169+ [ NotNull ] ILogger < RecurringJobsService > logger ,
170+ ILoggerFactory loggerFactory )
132171 {
133172 _backgroundJobs = backgroundJobs ?? throw new ArgumentNullException ( nameof ( backgroundJobs ) ) ;
134173 _recurringJobs = recurringJobs ?? throw new ArgumentNullException ( nameof ( recurringJobs ) ) ;
135174 _logger = logger ?? throw new ArgumentNullException ( nameof ( logger ) ) ;
175+ _loggerFactory = loggerFactory ;
136176 }
137177
138178 protected override Task ExecuteAsync ( CancellationToken stoppingToken )
139179 {
140180 try
141181 {
142- _recurringJobs . AddOrUpdate ( "seconds" , ( ) => Console . WriteLine ( "Hello, seconds!" ) , "*/15 * * * * *" ) ;
143- _recurringJobs . AddOrUpdate ( "minutely" , ( ) => Console . WriteLine ( "Hello, world!" ) , Cron . Minutely ) ;
182+ _logger . LogInformation ( "Creating recurring jobs" ) ;
183+
184+ _recurringJobs . AddOrUpdate ( "seconds" , ( ) => Hello ( "seconds" ) , "*/15 * * * * *" ) ;
185+
186+ using ( var activity = Program . ActivitySource . StartActivity ( "enqueue" ) )
187+ {
188+ _logger . LogInformation ( "Creating job minutely (hello world), trace_id={ActivityTraceId}" , activity . TraceId ) ;
189+ _recurringJobs . AddOrUpdate ( "minutely" , ( ) => Hello ( "world" ) , Cron . Minutely ) ;
190+ }
191+
144192 _recurringJobs . AddOrUpdate ( "hourly" , ( ) => Console . WriteLine ( "Hello" ) , "25 15 * * *" ) ;
145193 _recurringJobs . AddOrUpdate ( "neverfires" , ( ) => Console . WriteLine ( "Can only be triggered" ) , "0 0 31 2 *" ) ;
146194
@@ -161,5 +209,71 @@ protected override Task ExecuteAsync(CancellationToken stoppingToken)
161209
162210 return Task . CompletedTask ;
163211 }
212+
213+ public void Hello ( string name )
214+ {
215+ Console . WriteLine ( $ "Hello, { name } !") ;
216+ var logger = _loggerFactory . CreateLogger < RecurringJobsService > ( ) ;
217+ logger . LogInformation ( "Hello, {Name}! trace_id={ActivityTraceId}" , name , Activity . Current ? . TraceId ) ;
218+ }
219+ }
220+
221+ internal class BackgroundJobsService : BackgroundService
222+ {
223+ private readonly IBackgroundJobClient _backgroundJobs ;
224+ private readonly ILogger _logger ;
225+ private readonly ILoggerFactory _loggerFactory ;
226+
227+ public BackgroundJobsService (
228+ [ NotNull ] IBackgroundJobClient backgroundJobs ,
229+ [ NotNull ] ILogger < BackgroundJobsService > logger ,
230+ ILoggerFactory loggerFactory )
231+ {
232+ _backgroundJobs = backgroundJobs ?? throw new ArgumentNullException ( nameof ( backgroundJobs ) ) ;
233+ _logger = logger ?? throw new ArgumentNullException ( nameof ( logger ) ) ;
234+ _loggerFactory = loggerFactory ;
235+ }
236+
237+ protected override Task ExecuteAsync ( CancellationToken stoppingToken )
238+ {
239+ try
240+ {
241+ _logger . LogInformation ( "Creating backgriound jobs" ) ;
242+
243+ using ( var activity = Program . ActivitySource . StartActivity ( "enqueue" ) )
244+ {
245+ _logger . LogInformation ( "Creating job 10, trace_id={ActivityTraceId}" , activity . TraceId ) ;
246+ var jobId1 = _backgroundJobs . Enqueue ( ( ) => Job ( 10 ) ) ;
247+ }
248+ using ( var activity = Program . ActivitySource . StartActivity ( "schedule" ) )
249+ {
250+ _logger . LogInformation ( "Scheduling job 20, continue with 30, trace_id={ActivityTraceId}" , activity . TraceId ) ;
251+ var jobId2 = _backgroundJobs . Schedule ( ( ) => Job ( 20 ) , TimeSpan . FromSeconds ( 30 ) ) ;
252+ var jobId3 = _backgroundJobs . ContinueJobWith ( jobId2 , ( ) => Job ( 30 ) ) ;
253+ }
254+ using ( var activity = Program . ActivitySource . StartActivity ( "error" ) )
255+ {
256+ _logger . LogInformation ( "Scheduling error job 40, trace_id={ActivityTraceId}" , activity . TraceId ) ;
257+ var jobId4 = _backgroundJobs . Schedule ( ( ) => Job ( 40 ) , TimeSpan . FromSeconds ( 60 ) ) ;
258+ }
259+ }
260+ catch ( Exception e )
261+ {
262+ _logger . LogError ( e , "An exception occurred while creating recurring jobs." ) ;
263+ }
264+
265+ return Task . CompletedTask ;
266+ }
267+
268+ public void Job ( int counter ) {
269+ Console . WriteLine ( "Hello, job {0}!" , counter ) ;
270+ var logger = _loggerFactory . CreateLogger < BackgroundJobsService > ( ) ;
271+ logger . LogInformation ( "Hello, job {Counter} trace_id={ActivityTraceId}" , counter , Activity . Current ? . TraceId ) ;
272+ if ( counter == 40 )
273+ {
274+ throw new InvalidOperationException ( "Counter 40 is invalid." ) ;
275+ }
276+ }
164277 }
278+
165279}
0 commit comments