diff --git a/DnsApplicationCommon/IDnsLogger.cs b/DnsApplicationCommon/IDnsLogger.cs
new file mode 100644
index 00000000..9a14d0c3
--- /dev/null
+++ b/DnsApplicationCommon/IDnsLogger.cs
@@ -0,0 +1,244 @@
+/*
+Technitium DNS Server
+Copyright (C) 2021 Shreyas Zare (shreyas@technitium.com)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Threading.Tasks;
+using TechnitiumLibrary.Net.Dns;
+
+namespace DnsApplicationCommon
+{
+ public enum DnsServerResponseType : byte
+ {
+ Authoritative = 1,
+ Recursive = 2,
+ Cached = 3,
+ Blocked = 4
+ }
+
+ ///
+ /// Allows a DNS App to log incoming DNS requests and their corresponding responses.
+ ///
+ public interface IDnsLogger : IDisposable
+ {
+ ///
+ /// Allows initializing the DNS application with a config. This function is also called when the config is updated to allow reloading.
+ ///
+ /// The DNS server interface object that allows access to DNS server properties.
+ /// The DNS application config stored in the dnsApp.config file.
+ Task InitializeAsync(IDnsServer dnsServer, string config);
+
+ ///
+ /// Allows a DNS App to log incoming DNS requests and responses. This method is called by the DNS Server after an incoming request is processed and a response is sent.
+ ///
+ /// The incoming DNS request that was received.
+ /// The end point (IP address and port) of the client making the request.
+ /// The protocol using which the request was received.
+ /// The DNS response that was sent.
+ Task InsertLogAsync(DnsDatagram request, IPEndPoint remoteEP, DnsTransportProtocol protocol, DnsDatagram response);
+
+ ///
+ /// Allows DNS Server HTTP API to query the logs recorded by the DNS App.
+ ///
+ /// The page number to be displayed to the user.
+ /// Total entries per page.
+ /// Optional parameter to filter records by start date time.
+ /// Optional parameter to filter records by end date time.
+ /// Optional parameter to filter records by the client IP address.
+ /// Optional parameter to filter records by the DNS transport protocol.
+ /// Optional parameter to filter records by the type of response.
+ /// Optional parameter to filter records by the response code.
+ /// Optional parameter to filter records by the request QNAME.
+ /// Optional parameter to filter records by the request QTYPE.
+ /// Optional parameter to filter records by the request QCLASS.
+ /// The DnsLogPage object that contains all the entries in the requested page number.
+ Task QueryLogsAsync(long pageNumber, int entriesPerPage, DateTime? start, DateTime? end, IPAddress clientIpAddress, DnsTransportProtocol? protocol, DnsServerResponseType? responseType, DnsResponseCode? rcode, string qname, DnsResourceRecordType? qtype, DnsClass? qclass);
+
+ ///
+ /// The description about this app to be shown in the Apps section of the DNS web console.
+ ///
+ string Description { get; }
+ }
+
+ public class DnsLogPage
+ {
+ #region variables
+
+ readonly long _pageNumber;
+ readonly long _totalPages;
+ readonly long _totalEntries;
+ readonly IReadOnlyList _entries;
+
+ #endregion
+
+ #region constructor
+
+ ///
+ /// Creates a new object initialized with all the log page parameters.
+ ///
+ /// The actual page number of the selected data set.
+ /// The total pages for the selected data set.
+ /// The total number of entries in the selected data set.
+ /// The DNS log entries in this page.
+ public DnsLogPage(long pageNumber, long totalPages, long totalEntries, IReadOnlyList entries)
+ {
+ _pageNumber = pageNumber;
+ _totalPages = totalPages;
+ _totalEntries = totalEntries;
+ _entries = entries;
+ }
+
+ #endregion
+
+ #region properties
+
+ ///
+ /// The actual page number of the selected data set.
+ ///
+ public long PageNumber
+ { get { return _pageNumber; } }
+
+ ///
+ /// The total pages for the selected data set.
+ ///
+ public long TotalPages
+ { get { return _totalPages; } }
+
+ ///
+ /// The total number of entries in the selected data set.
+ ///
+ public long TotalEntries
+ { get { return _totalEntries; } }
+
+ ///
+ /// The DNS log entries in this page.
+ ///
+ public IReadOnlyList Entries
+ { get { return _entries; } }
+
+ #endregion
+ }
+
+ public class DnsLogEntry
+ {
+ #region variables
+
+ readonly long _rowNumber;
+ readonly DateTime _timestamp;
+ readonly IPAddress _clientIpAddress;
+ readonly DnsTransportProtocol _protocol;
+ readonly DnsServerResponseType _responseType;
+ readonly DnsResponseCode _rcode;
+ readonly DnsQuestionRecord _question;
+ readonly string _answer;
+
+ #endregion
+
+ #region constructor
+
+ ///
+ /// Creates a new object initialized with all the log entry parameters.
+ ///
+ /// The row number of the entry in the selected data set.
+ /// The time stamp of the log entry.
+ /// The client IP address of the request.
+ /// The DNS transport protocol of the request.
+ /// The type of response sent by the DNS server.
+ /// The response code sent by the DNS server.
+ /// The question section in the request.
+ /// The answer in text format sent by the DNS server.
+ public DnsLogEntry(long rowNumber, DateTime timestamp, IPAddress clientIpAddress, DnsTransportProtocol protocol, DnsServerResponseType responseType, DnsResponseCode rcode, DnsQuestionRecord question, string answer)
+ {
+ _rowNumber = rowNumber;
+ _timestamp = timestamp;
+ _clientIpAddress = clientIpAddress;
+ _protocol = protocol;
+ _responseType = responseType;
+ _rcode = rcode;
+ _question = question;
+ _answer = answer;
+
+ switch (_timestamp.Kind)
+ {
+ case DateTimeKind.Local:
+ _timestamp = _timestamp.ToUniversalTime();
+ break;
+
+ case DateTimeKind.Unspecified:
+ _timestamp = DateTime.SpecifyKind(_timestamp, DateTimeKind.Utc);
+ break;
+ }
+ }
+
+ #endregion
+
+ #region properties
+
+ ///
+ /// The row number of the entry in the selected data set.
+ ///
+ public long RowNumber
+ { get { return _rowNumber; } }
+
+ ///
+ /// The time stamp of the log entry.
+ ///
+ public DateTime Timestamp
+ { get { return _timestamp; } }
+
+ ///
+ /// The client IP address of the request.
+ ///
+ public IPAddress ClientIpAddress
+ { get { return _clientIpAddress; } }
+
+ ///
+ /// The DNS transport protocol of the request.
+ ///
+ public DnsTransportProtocol Protocol
+ { get { return _protocol; } }
+
+ ///
+ /// The type of response sent by the DNS server.
+ ///
+ public DnsServerResponseType ResponseType
+ { get { return _responseType; } }
+
+ ///
+ /// The response code sent by the DNS server.
+ ///
+ public DnsResponseCode RCODE
+ { get { return _rcode; } }
+
+ ///
+ /// The question section in the request.
+ ///
+ public DnsQuestionRecord Question
+ { get { return _question; } }
+
+ ///
+ /// The answer in text format sent by the DNS server.
+ ///
+ public string Answer
+ { get { return _answer; } }
+
+ #endregion
+ }
+}