data.mdx.frontmatter.hero_image

.NET Core – Logowanie zapytań do MongoDB na konsolę

2018-06-25 | .NET, MongoDB | bd90

Zapewne każdy pracujący na dowolnym ORM-mie, nie zależnie czy komunikuje się z bazą danych za pomocą bibliotek, klas czy kawałka kodu zewnętrznego, ceni sobie możliwość podejrzenia w konsoli generowanych zapytań SQL. Chcąc ułatwić wam życie zademonstruje sposób logowania zapytań w kliencie csharp bazy MongoDB.

Dodanie opcji logowania na konsole

Najprostszym sposobem stworzenia klienta bazy MongoDB jest zastosowanie connection string-a. Wtedy kod wygląda następująco:

services.AddSigleton<IMongoClient>(new MongoClient("mongodb://localhost:27017/database"));

Trzeba pamiętać, że wraz ze wzrostem złożoności connection string-a, zapis zaczyna tracić na czytelności. Wystarczy dodać użytkownika bazy i hasło, aby sporo wydłużyć naszą linijkę kodu.

services.AddSigleton<IMongoClient>(new MongoClient("mongodb://user:password@localhost:27017/database"));

Łatwo zauważyć jeszcze jedna wadę. Nie możemy wykorzystać event-ów, danych nam przez mongo driver, aby np. wypisać wygenerowane zapytanie do mongo na konsole. Ok, więc olewamy i dziękuje za dzisiaj. A w następnym poście... Nie no ok, podaje sposób rozwiązania problemu: chcąc korzystać z jej dobrodziejstw, musimy stworzyć obiekt klasy MongoClientSettings i przekazać w argumencie MongoClient.

Odwzorowanie kodu opisanego wyżej wygląda następująco:

var settings = new MongoClientSettings
{
    Server = new MongoServerAddress("localhost"),
    Credential = MongoCredential.CreateCredential("database", "user", "password"),
};

var client = new MongoClient(settings);
services.AddSingleton<IMongoClient>(client);

Czytelność kodu została zachowana, a o to nam chodzi zawsze. Zawsze! Miłym zaskoczeniem był dla mnie fakt, iż w klasie MongoServerAddress nie musimy podawać protokołu (mongodb) ani portu (27017). Tak samo stworzenie danych autoryzacyjnych, potrzebnych do zalogowania się na serwerze mongo, wygląda dość prosto.

W dalszym ciągu nie otrzymaliśmy logowania na konsole zapytań mogno. Więc jak się za to zabrać? Klasa MongoClientSettings udostępnia propertis "ClusterConfigurator". Możemy w nim przekazać wyrażenie lambda, aby np. zapisać się na zdarzenia rzucone bezpośrednio przez sterownik bazy danych.

To co chcemy zrobić wymaga zapisania się na event "CommandStartedEvent". Przykładowa implementacja wygląda następująco:

var settings = new MongoClientSettings
{
    Server = new MongoServerAddress("localhost"),
    Credential = MongoCredential.CreateCredential("database", "user", "password"),
    ClusterConfigurator = cb => { 
        cb.Subscribe<CommandStartedEvent>(e =>
        {
            Console.WriteLine($"{e.CommandName} - {e.Command.ToJson()}");
        }); 
    }
};

var client = new MongoClient(settings);

services.AddSingleton<IMongoClient>(client)

Dwa wyrażenia lambda później mamy gotową implementację. Powyższy kod obsłuży wypisywanie zapytań MongoDB na konsolę.

Wykorzystanie Serilog

Jako, że podczas pisania tego artykułu zostało mi jeszcze trochę kakałka w kubku, mam siłę i czas podzielić się dodatkową wiedzą. Wiedz, drogi czytelniku, że raczej staram się nie logować żadnych ciekawych informacji za pomocą konsoli, tylko używam do tego bardziej zaawansowanych narzędzi. Jednym z nich jest Serilog z integracją do ELK stack-a. Pokaże, jak do naszego kodu dołączyć jego biblioteką.

Jak pewnie wszyscy wiedzą, tworzenie klienta do komunikacji z bazą danych MongoDB zazwyczaj znajduje się w sekcji "ConfigureServices" klasy Startup. Trochę to utrudnia sprawę, ponieważ musimy wpierw, sami, zbudować provider-a, który rozwiąże nam typ ILogger. Po dodaniu dwóch linijek (i edytowaniu trzeciej) nasza implementacja powinna wyglądać następująco:

var provider = services.BuildServiceProvider();
var logger = provider.GetService<ILogger>();

var settings = new MongoClientSettings
{
    Server = new MongoServerAddress("localhost"),
    Credential = MongoCredential.CreateCredential("database", "user", "password"),
    ClusterConfigurator = cb => { 
        cb.Subscribe<CommandStartedEvent>(e =>
        {
            logger.LogInformation($"{e.CommandName} - {e.Command.ToJson()}");
        }); 
    }
};

var client = new MongoClient(settings);

services.AddSingleton<IMongoClient>(client);

Podsumowanie

Kakałko się skończyło więc pora kończyć artykuł. Na szczęście wszystko wygląda ładnie, a co najważniejsze, działa zgodnie z naszymi oczekiwaniami. Mamy, od razu w konsoli, wypisywane zapytania do MongoDB. W razie kłopotów, czy to z pobieraniem danych, czy z długim czasem wykonania zapytania na konsoli, mamy punkt zaczepienia. Jak zawsze mam nadzieje, że artykuł okazał się być pomocny.

Do Następnego!

By Bd90 | 25-06-2018 | .NET, MongoDB