Using Telegram Bot for logging in .NET with NLog without any existing code change

Image for post
Image for post

There was a tutorial, published yesterday on the Russian tech website on how to create a logging provider for Telegram in .NET 5. And while it’s good on checking how to create custom log provider — you probably already use some provider. So I thought: why should you write your own one and add it to the existing code and not just customize the existing one using it’s built in capabilities. We will look here at NLog as an example. You can use it in any type of .NET projects (.NET Framewok/.NET Core) and add various logging targets using NLog’s configuration (file/database/send to elasticsearch…..). I will use XML based NLog.config file in this article, so you will not have to change any of your existing code in case you already use NLog with the configuration file.

Why to Telegram? Telegram is one of the most popular messengers right now and it has nice bot API, so you can use it with your programs. Log forwarding is a good example of using messenger, because you can forward there some critical messages right to the group team chat. Use hashtags and other abilities for fast searching the messages (Telegram is far better then email in this case: instant message delivery, very high messages limit, advanced super fast search: by dates/hashtags/fulltext).

About NLog:

NLog is a flexible and free logging platform for various .NET platforms, including .NET standard. NLog makes it easy to write to several targets. (database, file, console) and change the logging configuration on-the-fly.

About Telegram:

Telegram is a freeware, cross-platform, cloud-based instant messaging software and application service. The service also provides end-to-end encrypted video calling, VoIP, file sharing and several other features.

Give Me Just The Configuration Part

First things first, here is the final config, you can just copy it’s target/rule into your existing config (+add your generated bot details there) and it should work right away, but we will discuss it’s parts later with explanations:

Tutorial/Explanations Part

As I already wrote here — to use Telegram API you just need to send an HTTP request to your bot, to use it as a ‘notificator’.

First you need to create a Telegram bot using special BotFather bot:, after that you will be granted with bot token like this one: 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw (pssst: this one is a secret parameter! Don’t tell it to anyone or your bot will be used for some bad things!) which will be used any bot API related request as part of the request URL.

Telegram supports GET and POST HTTP methods. Use either URL query string or application/json or application/x-www-form-urlencoded or multipart/form-data for passing parameters in Bot API requests.
On successful call, a JSON-object containing the result will be returned.

And using the WebService target for NLog we can send the log layout to the remote webservice. Here:

<target xsi:type=”WebService”
encoding=”utf-8" protocol=”JsonPost”>

We tell NLog to register the target of type “WebService”, that sends the data to… with your generated bot token using JsonPost (HTTP Post with ContentType “application/json”)protocol.

${telegramBotToken} — was declared as a parameter in the configuration:

<variable name="telegramBotToken" value="YOUR_TELEGRAM_BOT_TOKEN"/>

There is also another parameter:

<variable name="telegramChatId" value="YOUR_BOT_CHAT_ID"/>

this one is the chat_id to which your message will be sent. Let’s discuss this part a bit: to use the bot you must open some chat with him. Let’s say we create a private group in Telegram and add our bot there. After that you expect the bot to post messages into that group. Just send a “test” message to the group and recheck it:

That will return you the response like:

"ok": true,
"result": [
"update_id": 85245699,
"message": {
"message_id": 1,
"from": {
"id": 3307102,
"is_bot": false,
"first_name": "XXX",
"username": "XXX"
"chat": {
"id": -4317009,
"title": "test",
"type": "group",
"all_members_are_administrators": true
"date": 1611813493,
"group_chat_created": true

Where the “id”: -43170019 — is our chat_id.

To send the data as JSON (you can use other types: just GET/POST parameters), I’ve used the JsonLayout for NLog:

<parameter name="">  
<layout xsi:type="JsonLayout" includeAllProperties="true">
<attribute name="chat_id" layout="${telegramChatId}"/>
<attribute name="parse_mode" layout="HTML"/>
<attribute name="text"
layout="${longdate}|#${level}|&lt;i&gt;${logger}&lt;/i&gt;|&lt;pre&gt;&lt;code&gt;${message} ${exception:format=@}&lt;/code&gt;&lt;/pre&gt;"/>

Here I use `HTML` as `parse_mode` to format the message using <pre><code> tags (html encoded) just for sense of beauty.

That’s all about the config..

Test example code for this config:

using System;
using NLog;

namespace ConsoleApp1
class Program
private static Logger _logger = LogManager.GetCurrentClassLogger();

static void Main(string[] args)
_logger.Debug("test debug");
Console.WriteLine("Hello World!");
int a = 1;
int b = 0;
var c = a / b;
catch (Exception ex)

So it first sends the “test debug” text, prints “Hello World!” in the console and sends the exception log. These log send operations are asynchronous, so timeout of Telegram’s webservice should not slowdown your code.

You get the results in the following format:

Image for post
Image for post

Sure you probably should not use this type of log target (the messenger) to send every trace there, so just change the log level to some reasonable one for your situation in the NLog.config.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store