ASP.NET लॉगिंग के लिए Seq SerilogTracing के साथ - ट्रैसिंग
परिचय
पिछले भाग में मैंने आपको दिखाया था कि कैसे सेटअप एसपीएफ़ का उपयोग कर सीक्यू के लिए स्वयं कोربه . अब हम इसे सेटअप किया है यह करने के लिए यह अधिक का उपयोग करने की समय-' हमारे नए Seq इंस्टैंस का उपयोग करते हुए अधिक पूर्ण लॉगिंग अनुमति देने के लिए ' सुविधाएँ
ट्रेसिंग
ट्रेसिंग लॉगिंग की तरह है. यह आपको अपने अनुप्रयोग में क्या होता है के बारे में एक अतिरिक्त परत सूचना देता है. इस साइट में मैं यह समस्याओं को तेजी से खोजने के लिए उपयोग करता हूँ।
सेरिलॉग सेटअप कर रहा है
सेरिलॉग के साथ ट्रैसिंग सेटअप करना वास्तव में काफी सरल है सेरिलॉग ट्रेसिंग पैकेज
यहाँ हम भी कन्सोल सिंक और सेक सिंक जोड़ें
dotnet add package SerilogTracing
dotnet add package SerilogTracing.Expressions
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.Seq
कंसोल डिबगिंग के लिए हमेशा उपयोगी है और सेक क्या हम 'के लिए यहाँ कर रहे हैं
"Serilog": {
"Enrich": ["FromLogContext", "WithThreadId", "WithThreadName", "WithProcessId", "WithProcessName", "FromLogContext"],
"MinimumLevel": "Warning",
"WriteTo": [
{
"Name": "Seq",
"Args":
{
"serverUrl": "http://seq:5341",
"apiKey": ""
}
},
{
"Name": "Console"
},
{
"Name": "File",
"Args": {
"path": "logs/applog-.txt",
"rollingInterval": "Day"
}
}
],
"Properties": {
"ApplicationName": "mostlylucid"
}
}
इन समृद्धकर्ताओं का उपयोग करने के लिए आप अपने में उन्हें जोड़ने की जरूरत है Serilog अपने में कॉन्फ़िगरेशन appsettings.json You also need to install all the separate enrichers using Nuget
यह Serilog के बारे में एक अच्छी और बुरी बातें है। यहाँ'को mine

इन सब bombined के साथ मैं एक बहुत अच्छा लॉग आउटपुट सेक में मिलता है

यहाँ आप इस त्रुटि संदेश को देख सकते हैं
एक बात नोट करने के लिए है कि I'ने सेट किया है "MinimumLevel": "Warning", मेरे appsettings.json फ़ाइल. इसका मतलब है कि केवल चेतावनी और ऊपर से Seq में लॉग किया जाएगा
परन्तु सेक में आप इसे एपी कुंजी के लिए भी निर्दिष्ट कर सकते हैं Information या यदि आप वास्तव में उत्साही हैं Debugलॉगिंग यहाँ सेट करें और क्या Seq वास्तव में API कुंजी द्वारा कैप्चर करता है सीमा

नोट: आप अभी भी एप्लिकेशन ओवरहेड है सेक सिंक अधिक जानकारी के लिए
{
"Serilog":
{
"LevelSwitches": { "$controlSwitch": "Information" },
"MinimumLevel": { "ControlledBy": "$controlSwitch" },
"WriteTo":
[{
"Name": "Seq",
"Args":
{
"serverUrl": "http://localhost:5341",
"apiKey": "yeEZyL3SMcxEKUijBjN",
"controlLevelSwitch": "$controlSwitch"
}
}]
}
}
ट्रेसिंग
अब हम सेरीलॉग का उपयोग करके फिर से ट्रेसिंग जोड़ें यह ट्रेस करने के लिए एक नया सिंक जोड़ते हैं
dotnet add package SerilogTracing
dontet add package SerilogTracing.Expressions
dotnet add SerilogTracing.Instrumentation.AspNetCore
हम भी एक अतिरिक्त पैकेज जोड़ने के लिए अधिक विस्तृत aspnet कोर सूचना लॉग
में सेटअप करें Program.cs
अब हम वास्तव में ट्रैसिंग का उपयोग शुरू कर सकते हैं Program.cs फ़ाइल.
using var listener = new ActivityListenerConfiguration()
.Instrument.HttpClientRequests().Instrument
.AspNetCoreRequests()
.TraceToSharedLogger();
ट्रैकिंग का प्रयोग करता है 'अभिक्रियाएँ' जो कार्य की एक इकाई का प्रतिनिधित्व करते हैं।
इस मामले में हम HttpClient अनुरोधों और AspNetCore अनुरोधों के लिए अतिरिक्त खोज जोड़ते हैं TraceToSharedLogger जो हमारे अनुप्रयोग के बाकी के साथ एक ही लॉगर में क्रियाकलाप लॉग करेगा
किसी सेवा में ट्रैसिंग का उपयोग करना
अब हम ट्रैसिंग सेटअप किया है हम अपने अनुप्रयोग में इसका उपयोग शुरू कर सकते हैं
public async Task<PostListViewModel> GetPostsByCategory(string category, int page = 1, int pageSize = 10,
string language = MarkdownBaseService.EnglishLanguage)
{
using var activity = Log.Logger.StartActivity("GetPostsByCategory {Category}, {Page}, {PageSize}, {Language}",
new { category, page, pageSize, language });
try
{
var count = await NoTrackingQuery()
.Where(x => x.Categories.Any(c => c.Name == category) && x.LanguageEntity.Name == language)
.CountAsync();
var posts = await PostsQuery()
.Where(x => x.Categories.Any(c => c.Name == category) && x.LanguageEntity.Name == language)
.OrderByDescending(x => x.PublishedDate.DateTime)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
var languages = await GetLanguagesForSlugs(posts.Select(x => x.Slug).ToList());
var postListViewModel = new PostListViewModel
{
Page = page,
PageSize = pageSize,
TotalItems = count,
Posts = posts.Select(x => x.ToListModel(
languages.FirstOrDefault(entry => entry.Key == x.Slug).Value.ToArray())).ToList()
};
activity.Complete();
return postListViewModel;
}
catch (Exception e)
{
activity.Complete(LogEventLevel.Error, e);
}
return new PostListViewModel();
}
यहाँ महत्वपूर्ण लाइनें हैं
using var activity = Log.Logger.StartActivity("GetPostsByCategory {Category}, {Page}, {PageSize}, {Language}",
new { category, page, pageSize, language });
यह एक नया आरंभ करता है 'कार्यता' जो कार्य की एक इकाई है। चूंकि हम इसे एक उपयोग कथन में wrapped किया है यह हमारे विधि के अंत पर पूरा और निपटान करेगा लेकिन यह स्पष्ट रूप से इसे पूरा करने के लिए अच्छी पद्धति है
activity.Complete();
हमारे अपवाद handling catch में हम भी क्रियाकलाप को पूरा करते हैं लेकिन एक त्रुटि स्तर और अपवाद के साथ
ट्रेस का उपयोग करते हुए
अब हम सभी इस सेटअप है हम इसे उपयोग शुरू कर सकते हैं

यह आपको एकल मार्कडाउन पोस्ट का अनुवाद दिखाता है. आप एकल पोस्ट के लिए कई चरण और सभी HttpClient अनुरोधों और समयावधि को देख सकते हैं
नोट मैं अपने डाटाबेस के लिए Postgres का उपयोग करता हूँ।
"@t": "2024-08-31T15:23:31.0872838Z",
"@mt": "mostlylucid",
"@m": "mostlylucid",
"@i": "3c386a9a",
"@tr": "8f9be07e41f7121cbf2866c6cd886a90",
"@sp": "8d716c5f01ad07a0",
"@st": "2024-08-31T15:23:31.0706848Z",
"@ps": "622f1c86a8b33304",
"@sk": "Client",
"ActionId": "91f5105d-93fa-4e7f-9708-b1692e046a8a",
"ActionName": "Mostlylucid.Controllers.HomeController.Index (Mostlylucid)",
"ApplicationName": "mostlylucid",
"ConnectionId": "0HN69PVEQ9S7C",
"ProcessId": 30496,
"ProcessName": "Mostlylucid",
"RequestId": "0HN69PVEQ9S7C:00000015",
"RequestPath": "/",
"SourceContext": "Npgsql",
"ThreadId": 47,
"ThreadName": ".NET TP Worker",
"db.connection_id": 1565,
"db.connection_string": "Host=localhost;Database=mostlylucid;Port=5432;Username=postgres;Application Name=mostlylucid",
"db.name": "mostlylucid",
"db.statement": "SELECT t.\"Id\", t.\"ContentHash\", t.\"HtmlContent\", t.\"LanguageId\", t.\"Markdown\", t.\"PlainTextContent\", t.\"PublishedDate\", t.\"SearchVector\", t.\"Slug\", t.\"Title\", t.\"UpdatedDate\", t.\"WordCount\", t.\"Id0\", t0.\"BlogPostId\", t0.\"CategoryId\", t0.\"Id\", t0.\"Name\", t.\"Name\"\r\nFROM (\r\n SELECT b.\"Id\", b.\"ContentHash\", b.\"HtmlContent\", b.\"LanguageId\", b.\"Markdown\", b.\"PlainTextContent\", b.\"PublishedDate\", b.\"SearchVector\", b.\"Slug\", b.\"Title\", b.\"UpdatedDate\", b.\"WordCount\", l.\"Id\" AS \"Id0\", l.\"Name\", b.\"PublishedDate\" AT TIME ZONE 'UTC' AS c\r\n FROM mostlylucid.\"BlogPosts\" AS b\r\n INNER JOIN mostlylucid.\"Languages\" AS l ON b.\"LanguageId\" = l.\"Id\"\r\n WHERE l.\"Name\" = @__language_0\r\n ORDER BY b.\"PublishedDate\" AT TIME ZONE 'UTC' DESC\r\n LIMIT @__p_2 OFFSET @__p_1\r\n) AS t\r\nLEFT JOIN (\r\n SELECT b0.\"BlogPostId\", b0.\"CategoryId\", c.\"Id\", c.\"Name\"\r\n FROM mostlylucid.blogpostcategory AS b0\r\n INNER JOIN mostlylucid.\"Categories\" AS c ON b0.\"CategoryId\" = c.\"Id\"\r\n) AS t0 ON t.\"Id\" = t0.\"BlogPostId\"\r\nORDER BY t.c DESC, t.\"Id\", t.\"Id0\", t0.\"BlogPostId\", t0.\"CategoryId\"",
"db.system": "postgresql",
"db.user": "postgres",
"net.peer.ip": "::1",
"net.peer.name": "localhost",
"net.transport": "ip_tcp",
"otel.status_code": "OK"
आप देख सकते हैं कि यह लगभग सब कुछ शामिल है जो आपको क्वेरी के बारे में जानने की जरूरत है
अंत में
मैंने केवल ट्रैसिंग की सतह को scratched यहाँ किया है। ,। यह' passionate advocates के साथ एक बिट क्षेत्र है।