Udostępnij przez


TripPin — część 8 — dodawanie diagnostyki

Uwaga / Notatka

Ta zawartość odwołuje się obecnie do zawartości ze starszej implementacji diagnostyki w programie Visual Studio. Zawartość zostanie zaktualizowana w najbliższej przyszłości, aby uwzględnić nowy zestaw POWER Query SDK w programie Visual Studio Code.

Ten wieloczęściowy samouczek obejmuje tworzenie nowego rozszerzenia źródła danych dla dodatku Power Query. Samouczek ma być wykonywany sekwencyjnie — każda lekcja opiera się na łączniku utworzonym w poprzednich lekcjach, przyrostowo dodając nowe możliwości do łącznika.

W tej lekcji wykonasz następujące czynności:

  • Dowiedz się więcej o funkcji Diagnostics.Trace
  • Używanie funkcji pomocnika diagnostyki do dodawania informacji śledzenia w celu ułatwienia debugowania łącznika

Włączanie diagnostyki

Użytkownicy dodatku Power Query mogą włączyć rejestrowanie śledzenia, zaznaczając pole wyboru w obszarze Opcje | Diagnostyka.

Zrzut ekranu przedstawiający opcje dodatku Power Query z wybraną kartą Diagnostyka i włączonym śledzeniem.

Po włączeniu wszystkie kolejne zapytania powodują, że silnik M generuje śledzenia do plików dziennika w stałym katalogu użytkownika.

Po uruchomieniu zapytań języka M z poziomu zestawu SDK dodatku Power Query śledzenie jest włączone na poziomie projektu. Na stronie właściwości projektu istnieją trzy ustawienia związane z śledzeniem:

  • Wyczyść dziennik: po ustawieniu true, dziennik zostanie zresetowany/wyczyszczony podczas uruchamiania zapytań. Zalecamy zachowanie tego ustawienia na wartość true.

  • Pokaż ślady silnika: to ustawienie steruje wynikiem wbudowanych śladów z silnika M. Te rejestry są przydatne tylko dla członków zespołu Power Query, więc zazwyczaj chcesz zachować to ustawienie na wartość false.

  • Pokaż ślady użytkownika: to ustawienie kontroluje dane wyjściowe śledzenia łącznika. Chcesz ustawić to ustawienie na true.

    Zrzut ekranu przedstawiający strony właściwości TripPin z trzema ustawieniami związanymi z śledzeniem.

Po włączeniu wpisy dziennika są wyświetlane w oknie Wynik zapytania M na karcie Dziennik.

Diagnostics.Trace

Funkcja Diagnostics.Trace służy do zapisywania komunikatów w dzienniku śledzenia silnika M.

Diagnostics.Trace = (traceLevel as number, message as text, value as any, optional delayed as nullable logical as any) => ...

Ważne

M to język funkcjonalny z leniwym wartościowaniem. W przypadku używania Diagnostics.Tracefunkcji należy pamiętać, że funkcja jest wywoływana tylko wtedy, gdy wyrażenie jest częścią tego, co jest rzeczywiście oceniane. Przykłady tego zachowania można znaleźć w dalszej części tego samouczka.

Parametr traceLevel może być jedną z następujących wartości (w kolejności malejącej):

  • TraceLevel.Critical
  • TraceLevel.Error
  • TraceLevel.Warning
  • TraceLevel.Information
  • TraceLevel.Verbose

Po włączeniu śledzenia użytkownik może wybrać maksymalny poziom komunikatów, które mają zobaczyć. Wszystkie komunikaty śledzenia tego poziomu i niższe są zapisywane w dzienniku. Jeśli na przykład użytkownik wybierze poziom "Ostrzeżenie", w dziennikach pojawią się komunikaty śledzenia TraceLevel.Warning, TraceLevel.Error i TraceLevel.Critical.

Parametr message jest rzeczywistym tekstem wyjściowym do pliku śledzenia. Tekst nie zawiera parametru value , chyba że jawnie dołączysz go do tekstu.

Parametr value jest zwracany przez funkcję. Gdy parametr delayed jest ustawiony na true, value jest funkcją bez parametrów, która zwraca wartość, którą oceniasz. Kiedy delayed jest ustawiony na false, value jest wartością rzeczywistą. Przykład tego działania można znaleźć w sekcji Ocena opóźniona.

Korzystanie z pliku Diagnostics.Trace w łączniku TripPin

Aby uzyskać praktyczny przykład użycia Diagnostics.Trace i wpływu parametru delayed, zaktualizuj funkcję łącznika TripPin, aby przechwycić wyjątek error.

GetSchemaForEntity = (entity as text) as type =>
    try
        SchemaTable{[Entity=entity]}[Type]
    otherwise
        let
            message = Text.Format("Couldn't find entity: '#{0}'", {entity})
        in
            Diagnostics.Trace(TraceLevel.Error, message, () => error message, true);

Błąd można wymusić podczas oceny (na potrzeby testu), przekazując nieprawidłową nazwę encji do funkcji GetEntity. W tym miejscu zmieniasz withData wiersz w funkcji TripPinNavTable, zastępując [Name] za "DoesNotExist".

TripPinNavTable = (url as text) as table =>
    let
        // Use our schema table as the source of top level items in the navigation tree
        entities = Table.SelectColumns(SchemaTable, {"Entity"}),
        rename = Table.RenameColumns(entities, {{"Entity", "Name"}}),
        // Add Data as a calculated column
        withData = Table.AddColumn(rename, "Data", each GetEntity(url, "DoesNotExist"), type table),
        // Add ItemKind and ItemName as fixed text values
        withItemKind = Table.AddColumn(withData, "ItemKind", each "Table", type text),
        withItemName = Table.AddColumn(withItemKind, "ItemName", each "Table", type text),
        // Indicate that the node should not be expandable
        withIsLeaf = Table.AddColumn(withItemName, "IsLeaf", each true, type logical),
        // Generate the nav table
        navTable = Table.ToNavigationTable(withIsLeaf, {"Name"}, "Name", "Data", "ItemKind", "ItemName", "IsLeaf")
    in
        navTable;

Włącz śledzenie projektu i uruchom zapytania testowe. Errors Na karcie powinien zostać wyświetlony tekst zgłoszonego błędu:

Zrzut ekranu przedstawiający dane wyjściowe zapytania M z wyświetlonym błędem „nie istnieje”.

Ponadto na karcie Log powinna zostać wyświetlona tę samą wiadomość. Jeśli używasz różnych wartości dla message parametrów i value , te wartości będą inne.

Zrzut ekranu przedstawiający tag logu w danych wyjściowych zapytania M z podkreślonym komunikatem logu.

Należy również pamiętać, że Action pole komunikatu dziennika zawiera nazwę (rodzaj źródła danych) rozszerzenia (w tym przypadku Engine/Extension/TripPin). To pole ułatwia znajdowanie komunikatów związanych z rozszerzeniem, gdy zaangażowane są liczne zapytania i/lub włączone jest śledzenie systemu (aparatu mashupu).

Opóźniona ocena

Przykładem działania parametru delayed jest wprowadzenie pewnych modyfikacji i ponowne uruchomienie zapytań.

Najpierw ustaw wartość delayed na false, ale pozostaw parametr value tak jak jest.

Diagnostics.Trace(TraceLevel.Error, message, () => error message, false);

Po uruchomieniu zapytania zostanie wyświetlony błąd "Nie można przekonwertować wartości typu Funkcja na typ Type", zamiast rzeczywistego błędu, który zgłosiłeś. Ta różnica polega na tym, że wywołanie teraz zwraca wartość function, a nie samą wartość.

Następnie usuń funkcję z parametru value :

Diagnostics.Trace(TraceLevel.Error, message, error message, false);

Po uruchomieniu zapytania zostanie wyświetlony prawidłowy błąd, ale jeśli sprawdzisz kartę Dziennik , nie ma żadnych komunikatów. Ta rozbieżność wynika z tego, że wynik error jest zgłaszany/oceniany podczas wywołania metody Diagnostics.Trace, więc komunikat nigdy nie jest w rzeczywistości zwracany.

Teraz, gdy rozumiesz wpływ parametru delayed , pamiętaj, aby zresetować łącznik z powrotem do stanu roboczego przed kontynuowaniem.

Funkcje pomocnika diagnostycznego w pliku Diagnostics.pqm

Plik Diagnostics.pqm zawarty w tym projekcie zawiera wiele funkcji pomocnika, które ułatwiają śledzenie. Jak pokazano w poprzednim samouczku, możesz dołączyć ten plik do projektu (pamiętając o ustawieniu akcji kompilacji na kompilowanie), a następnie załadować go w pliku łącznika. Dolna część pliku łącznika powinna teraz wyglądać podobnie do poniższego fragmentu kodu. Możesz zapoznać się z różnymi funkcjami dostępnymi w tym module, ale w tym przykładzie używasz tylko funkcji Diagnostics.LogValue i Diagnostics.LogFailure.

// Diagnostics module contains multiple functions. We can take the ones we need.
Diagnostics = Extension.LoadFunction("Diagnostics.pqm");
Diagnostics.LogValue = Diagnostics[LogValue];
Diagnostics.LogFailure = Diagnostics[LogFailure];

Diagnostics.LogValue

Funkcja Diagnostics.LogValue jest bardzo podobna do funkcji Diagnostics.Trace i może być użyta do wyświetlania wartości, którą oceniasz.

Diagnostics.LogValue = (prefix as text, value as any) as any => ...

Parametr prefix jest dodawany przed komunikatem dziennika. Użyj tego parametru, aby określić, które wywołanie wygenerowało wiadomość. Parametr value jest zwracany przez funkcję, a także zapisywany w śladzie jako tekstowa reprezentacja wartości języka M. Jeśli na przykład value jest równe table, zawierającym kolumny A i B, to dziennik zawiera równoważną reprezentację #table: #table({"A", "B"}, {{"row1 A", "row1 B"}, {"row2 A", row2 B"}}).

Uwaga / Notatka

Serializowanie wartości M do tekstu może być kosztowną operacją. Należy pamiętać o potencjalnym rozmiarze wartości, które są wyprowadzane do śladu.

Uwaga / Notatka

Większość środowisk Power Query obcina komunikaty śledzenia do maksymalnej długości.

Na przykład zaktualizuj funkcję TripPin.Feed, aby śledzić argumenty url i schema przekazywane do funkcji.

TripPin.Feed = (url as text, optional schema as type) as table =>
    let
        _url = Diagnostics.LogValue("Accessing url", url),
        _schema = Diagnostics.LogValue("Schema type", schema),
        //result = GetAllPagesByNextLink(url, schema)
        result = GetAllPagesByNextLink(_url, _schema)
    in
        result;

Musisz użyć nowych wartości _url i _schema w wywołaniu GetAllPagesByNextLink. Jeśli użyto oryginalnych parametrów funkcji, Diagnostics.LogValue wywołania nigdy nie są faktycznie przetwarzane, co powoduje, że żadne komunikaty nie są zapisywane w śledzeniu. Programowanie funkcjonalne jest zabawne!

Po uruchomieniu zapytań w dzienniku powinny zostać wyświetlone nowe komunikaty.

Uzyskiwanie dostępu do adresu URL:

Zrzut ekranu przedstawiający dane wyjściowe zapytania języka M z komunikatem o dostępie do adresu URL.

Typ schematu:

Zrzut ekranu przedstawiający dane wyjściowe zapytania języka M z komunikatem o typie schematu.

Wyświetlana jest serializowana wersja parametru schematype, zamiast tego, co uzyskasz, gdy dokonasz prostego Text.FromValue na wartości typu (co skutkuje "typ").

Diagnostics.LogFailure

Funkcja Diagnostics.LogFailure może służyć do opakowywania wywołań funkcji i zapisu do śledzenia tylko wtedy, jeśli wywołanie funkcji zakończy się niepowodzeniem (co oznacza, że zwraca error).

Diagnostics.LogFailure = (text as text, function as function) as any => ...

Wewnętrznie Diagnostics.LogFailure dodaje operator try do wywołania function. Jeśli wywołanie zakończy się niepowodzeniem, wartość text zostanie zapisana w śledzeniu przed zwróceniem oryginalnego error elementu. Jeśli wywołanie function powiedzie się, wynik zostanie zwrócony bez zapisywania czegokolwiek do śladu. Ponieważ błędy języka M nie zawierają pełnego śledzenia stosu (czyli zazwyczaj widzisz tylko komunikat o błędzie), ta funkcja może być przydatna, gdy chcesz wskazać, gdzie został zgłoszony błąd.

Jako słaby przykład, zmodyfikuj linię withData funkcji TripPinNavTable , aby ponownie wymusić błąd.

withData = Table.AddColumn(rename, "Data", each Diagnostics.LogFailure("Error in GetEntity", () => GetEntity(url, "DoesNotExist")), type table),

W śladzie można znaleźć komunikat o błędzie wynikowy zawierający Twój text oraz oryginalne informacje o błędzie.

Zrzut ekranu przedstawiający dane wyjściowe zapytania M z komunikatem o błędzie dziennika.

Przed przejściem do następnego samouczka pamiętaj, aby zresetować funkcję do stanu roboczego.

Podsumowanie

W tej krótkiej lekcji (ale ważnej) pokazano, jak używać funkcji pomocnika diagnostycznego do rejestrowania się w plikach śledzenia dodatku Power Query. Gdy te funkcje są używane prawidłowo, są przydatne podczas debugowania problemów w łączniku.

Uwaga / Notatka

Jako deweloper łącznika ponosisz odpowiedzialność za to, aby w ramach rejestrowania diagnostycznego nie rejestrować poufnych ani danych osobowych. Należy również zachować ostrożność, aby nie generować zbyt dużej ilości informacji z logów, ponieważ może to mieć negatywny wpływ na wydajność.

Dalsze kroki

TripPin — część 9 — TestConnection