66using LocalNetAppChat . Server . Domain . Messaging . MessageProcessing ;
77using LocalNetAppChat . Server . Domain . Security ;
88using LocalNetAppChat . Server . Domain . StoringFiles ;
9+ using Serilog ;
10+ using Serilog . Events ;
911
1012var parser = new Parser (
1113 new ICommandLineOption [ ] {
3941 $ "\n \n [Usage]\n \n " +
4042 $ "\n { string . Join ( "\n " , commandsWithDescription ) } ") ;
4143
42- Console . WriteLine ( "\n \n Examples:\r \n \r \n – Start the server with the default settings\r \n $ LocalNetAppChat.Server\r \n - Start the server in HTTPS mode\r \n $ LocalNetAppChat.Server --https\r \n - Start the server with different ip and port and custom key\r \n $ LocalNetAppChat.Server --listenOn \" 54.15.12.1\" --port \" 54822\" --https --key \" HeythereGithubExample\" " ) ;
44+ Console . WriteLine ( "\n \n Examples:\r \n \r \n � Start the server with the default settings\r \n $ LocalNetAppChat.Server\r \n - Start the server in HTTPS mode\r \n $ LocalNetAppChat.Server --https\r \n - Start the server with different ip and port and custom key\r \n $ LocalNetAppChat.Server --listenOn \" 54.15.12.1\" --port \" 54822\" --https --key \" HeythereGithubExample\" " ) ;
4345
4446 return ;
4547}
4648
47- var serverKey = parser . TryGetOptionWithValue < string > ( "--key" ) ;
48- var accessControl = new KeyBasedAccessControl ( serverKey ?? string . Empty ) ;
49+ // Configure Serilog
50+ var logsDirectory = Path . Combine ( Directory . GetCurrentDirectory ( ) , "logs" ) ;
51+ Directory . CreateDirectory ( logsDirectory ) ;
52+
53+ Log . Logger = new LoggerConfiguration ( )
54+ . MinimumLevel . Information ( )
55+ . MinimumLevel . Override ( "Microsoft.AspNetCore" , LogEventLevel . Warning )
56+ . Enrich . FromLogContext ( )
57+ . WriteTo . Console ( outputTemplate : "[{Timestamp:yyyy-MM-dd HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}" )
58+ . WriteTo . File (
59+ Path . Combine ( logsDirectory , "lnac-server-.log" ) ,
60+ rollingInterval : RollingInterval . Day ,
61+ retainedFileCountLimit : 14 ,
62+ outputTemplate : "[{Timestamp:yyyy-MM-dd HH:mm:ss}] [{Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception}" )
63+ . CreateLogger ( ) ;
64+
65+ try
66+ {
67+ Log . Information ( "Starting LocalNetAppChat Server" ) ;
68+
69+ var serverKey = parser . TryGetOptionWithValue < string > ( "--key" ) ;
70+ var accessControl = new KeyBasedAccessControl ( serverKey ?? string . Empty ) ;
71+
72+ var messagingServiceProvider = new MessagingServiceProvider (
73+ accessControl ,
74+ MessageProcessorFactory . Get (
75+ new ThreadSafeCounter ( ) ,
76+ new DateTimeProvider ( ) )
77+ ) ;
4978
50- var messagingServiceProvider = new MessagingServiceProvider (
51- accessControl ,
52- MessageProcessorFactory . Get (
53- new ThreadSafeCounter ( ) ,
54- new DateTimeProvider ( ) )
55- ) ;
79+ var storageServiceProvider = new StorageServiceProvider (
80+ accessControl ,
81+ Path . Combine ( Directory . GetCurrentDirectory ( ) , "data" ) ) ;
5682
57- var storageServiceProvider = new StorageServiceProvider (
58- accessControl ,
59- Path . Combine ( Directory . GetCurrentDirectory ( ) , "data" ) ) ;
83+ var hostingUrl = HostingUrlGenerator . GenerateUrl (
84+ parser . GetOptionWithValue < string > ( "--listenOn" ) ?? "" ,
85+ parser . GetOptionWithValue < int > ( "--port" ) ,
86+ parser . GetBoolOption ( "--https" ) ) ;
6087
61- var hostingUrl = HostingUrlGenerator . GenerateUrl (
62- parser . GetOptionWithValue < string > ( "--listenOn" ) ?? "" ,
63- parser . GetOptionWithValue < int > ( "--port" ) ,
64- parser . GetBoolOption ( "--https" ) ) ;
88+ Log . Information ( "Server configured to listen on {HostingUrl} with key authentication" , hostingUrl ) ;
6589
66- var builder = WebApplication . CreateBuilder ( new [ ] { "--urls" , hostingUrl } ) ;
90+ var builder = WebApplication . CreateBuilder ( new [ ] { "--urls" , hostingUrl } ) ;
91+ builder . Host . UseSerilog ( ) ;
6792var app = builder . Build ( ) ;
6893
69- app . MapGet ( "/" , ( ) => "LocalNetAppChat Server!" ) ;
94+ // Add Serilog request logging
95+ app . UseSerilogRequestLogging ( options =>
96+ {
97+ options . MessageTemplate = "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms" ;
98+ } ) ;
99+
100+ app . MapGet ( "/" , ( ) => "LocalNetAppChat Server!" ) ;
70101
71102app . MapGet ( "/receive" , ( string key , string clientName ) =>
72103{
104+ Log . Debug ( "Client {ClientName} requesting messages" , clientName ) ;
73105 var result = messagingServiceProvider . GetMessages ( key , clientName ) ;
74106
75107 if ( ! result . IsSuccess )
76108 {
109+ Log . Warning ( "Failed to get messages for client {ClientName}: {Error}" , clientName , result . Error ) ;
77110 return result . Error ;
78111 }
79112
113+ Log . Information ( "Delivered {MessageCount} messages to client {ClientName}" , result . Value . Length , clientName ) ;
80114 return JsonSerializer . Serialize ( result . Value ) ;
81115} ) ;
82116
83117app . MapPost ( "/send" , ( string key , LnacMessage message ) =>
84118{
119+ Log . Information ( "Received message from {ClientName}: {MessageText}" , message . Name , message . Text ) ;
85120 var result = messagingServiceProvider . SendMessage ( key , message ) ;
86121
87122 if ( ! result . IsSuccess )
88123 {
124+ Log . Warning ( "Failed to send message from {ClientName}: {Error}" , message . Name , result . Error ) ;
89125 return result . Error ;
90126 }
91127
128+ Log . Debug ( "Message from {ClientName} successfully queued" , message . Name ) ;
92129 return result . Value ;
93130} ) ;
94131
95132app . MapPost ( "/upload" , async ( HttpRequest request , string key ) =>
96133{
97134 if ( ! request . HasFormContentType )
135+ {
136+ Log . Warning ( "Upload request received without form content type" ) ;
98137 return Results . BadRequest ( ) ;
138+ }
99139
100140 var form = await request . ReadFormAsync ( ) ;
101141
102142 if ( form . Files . Any ( ) == false )
143+ {
144+ Log . Warning ( "Upload request received without files" ) ;
103145 return Results . BadRequest ( "There are no files" ) ;
146+ }
104147
105148 var file = form . Files . FirstOrDefault ( ) ;
106149
107150 if ( file is null || file . Length == 0 )
151+ {
152+ Log . Warning ( "Upload request received with empty file" ) ;
108153 return Results . BadRequest ( "File cannot be empty" ) ;
154+ }
109155
156+ Log . Information ( "Uploading file {FileName} ({FileSize} bytes)" , file . FileName , file . Length ) ;
110157 var result = await storageServiceProvider . Upload ( key ,
111158 file . FileName , file . OpenReadStream ( ) ) ;
112159
113160 if ( ! result . IsSuccess )
161+ {
162+ Log . Error ( "Failed to upload file {FileName}: {Error}" , file . FileName , result . Error ) ;
114163 return Results . BadRequest ( result . Error ) ;
164+ }
115165
166+ Log . Information ( "Successfully uploaded file {FileName}" , file . FileName ) ;
116167 return Results . Content ( result . Value ) ;
117168} ) ;
118169
119170
120171app . MapGet ( "/listallfiles" , ( string key ) =>
121172{
173+ Log . Debug ( "Listing all files request received" ) ;
122174 var result = storageServiceProvider . GetFiles ( key ) ;
123175
124176 if ( ! result . IsSuccess )
177+ {
178+ Log . Warning ( "Failed to list files: {Error}" , result . Error ) ;
125179 return Results . BadRequest ( result . Error ) ;
180+ }
126181
182+ Log . Information ( "Listed {FileCount} files" , result . Value . Length ) ;
127183 return Results . Json ( result . Value ) ;
128184} ) ;
129185
130186app . MapGet ( "/download" , async ( HttpRequest _ , string key , string filename ) =>
131187{
188+ Log . Information ( "Download request for file {FileName}" , filename ) ;
132189 var result = await storageServiceProvider . Download ( key , filename ) ;
133190
134191 if ( ! result . IsSuccess )
192+ {
193+ Log . Warning ( "Failed to download file {FileName}: {Error}" , filename , result . Error ) ;
135194 return Results . BadRequest ( result . Error ) ;
195+ }
136196
197+ Log . Information ( "Successfully downloaded file {FileName}" , filename ) ;
137198 return Results . File ( result . Value , fileDownloadName : filename ) ;
138199} ) ;
139200
140201app . MapPost ( "/deletefile" , ( HttpRequest _ , string filename , string key ) =>
141202{
203+ Log . Information ( "Delete request for file {FileName}" , filename ) ;
142204 var result = storageServiceProvider . Delete ( key , filename ) ;
143205
144206 if ( ! result . IsSuccess )
207+ {
208+ Log . Warning ( "Failed to delete file {FileName}: {Error}" , filename , result . Error ) ;
145209 return Results . BadRequest ( result . Error ) ;
210+ }
146211
212+ Log . Information ( "Successfully deleted file {FileName}" , filename ) ;
147213 return Results . Content ( result . Value ) ;
148214} ) ;
149215
150- app . Run ( ) ;
216+ Log . Information ( "Server started successfully" ) ;
217+ app . Run ( ) ;
218+ }
219+ catch ( Exception ex )
220+ {
221+ Log . Fatal ( ex , "Server terminated unexpectedly" ) ;
222+ }
223+ finally
224+ {
225+ Log . CloseAndFlush ( ) ;
226+ }
0 commit comments