Udostępnij za pośrednictwem


Odpytywanie odpowiedzi HTTP w wersji 2

Wiersz stanu odpowiedzi HTTP

Jeśli żądanie powiedzie się, kod stanu odpowiedzi HTTP to 200 OK. Treść odpowiedzi HTTP jest tablicą JSON, jak wyjaśniono poniżej.

Jeśli żądanie zakończy się niepowodzeniem 4xx , kod stanu odpowiedzi HTTP to błąd lub 5xx . Fraza przyczyny będzie zawierać dodatkowe informacje o niepowodzeniu. Treść odpowiedzi HTTP jest obiektem JSON, jak wyjaśniono poniżej.

Uwaga

Żądanie może zwrócić kod stanu elementu 200 OK, ale treść odpowiedzi HTTP będzie wskazywać błąd. Może się to zdarzyć, gdy błąd zostanie zgłoszony po powrocie wiersza stanu HTTP. Oczekuje się, że czytelnik jawnie sprawdzi taki warunek.

Nagłówki odpowiedzi HTTP

Niezależnie od powodzenia/niepowodzenia żądania dwa niestandardowe nagłówki HTTP są dołączone do odpowiedzi:

  1. x-ms-client-request-id: Usługa zwraca nieprzezroczysty ciąg identyfikujący parę żądań/odpowiedzi na potrzeby korelacji. Jeśli żądanie zawiera identyfikator żądania klienta, jego wartość będzie wyświetlana tutaj; w przeciwnym razie zwracany jest losowy ciąg.

  2. x-ms-activity-id: usługa zwraca nieprzezroczysty ciąg, który jednoznacznie identyfikuje parę żądań/odpowiedzi na potrzeby korelacji. W przeciwieństwie do x-ms-client-request-idelementu ten identyfikator nie ma wpływu na żadne informacje w żądaniu i jest unikatowy na odpowiedź.

Treść odpowiedzi HTTP (po niepowodzeniu żądania)

Po niepowodzeniu żądania treść odpowiedzi HTTP będzie dokumentem JSON sformatowanym zgodnie z regułami OneApiErrors . Aby uzyskać opis OneApiErrors formatu, zobacz sekcję 7.10.2 tutaj. Poniżej przedstawiono przykład takiego błędu.

{
    "error": {
        "code": "General_BadRequest",
        "message": "Request is invalid and cannot be executed.",
        "@type": "Kusto.Data.Exceptions.KustoBadRequestException",
        "@message": "Request is invalid and cannot be processed: Semantic error: SEM0100: 'table' operator: Failed to resolve table expression named 'aaa'",
        "@context": {
            "timestamp": "2023-04-18T12:59:27.4855445Z",
            "serviceAlias": "HELP",
            "machineName": "KEngine000000",
            "processName": "Kusto.WinSvc.Svc",
            "processId": 12580,
            "threadId": 10260,
            "clientRequestId": "Kusto.Cli;b90f4260-4eac-4574-a27a-3f302db21404",
            "activityId": "9dcc4522-7b51-41db-a7ae-7c1bfe0696b2",
            "subActivityId": "d0f30c8c-e6c6-45b6-9275-73dd6b379ecf",
            "activityType": "DN.FE.ExecuteQuery",
            "parentActivityId": "6e3c8dab-0aaf-4df5-85b5-fc20b0b29a84",
            "activityStack": "(Activity stack: CRID=Kusto.Cli;b90f4260-4eac-4574-a27a-3f302db21404 ARID=9dcc4522-7b51-41db-a7ae-7c1bfe0696b2 > KD.Query.Client.ExecuteQueryAsKustoDataStream/8191428e-7139-4c5d-9da7-839a0f21c5b9 > P.WCF.Service.ExecuteQueryAsKustoDataStream..IInterNodeCommunicationQueryContract/6e3c8dab-0aaf-4df5-85b5-fc20b0b29a84 > DN.FE.ExecuteQuery/d0f30c8c-e6c6-45b6-9275-73dd6b379ecf)"
        },
        "@permanent": true,
        "@text": "aaa",
        "@database": "Samples",
        "@ClientRequestLogger": "",
        "innererror": {
            "code": "SEM0100",
            "message": "'table' operator: Failed to resolve table expression named 'aaa'",
            "@type": "Kusto.Data.Exceptions.SemanticException",
            "@message": "Semantic error: SEM0100: 'table' operator: Failed to resolve table expression named 'aaa'",
            "@context": {
                "timestamp": "2023-04-18T12:59:27.4855445Z",
                "serviceAlias": "HELP",
                "machineName": "KEngine000000",
                "processName": "Kusto.WinSvc.Svc",
                "processId": 12580,
                "threadId": 10260,
                "clientRequestId": "Kusto.Cli;b90f4260-4eac-4574-a27a-3f302db21404",
                "activityId": "9dcc4522-7b51-41db-a7ae-7c1bfe0696b2",
                "subActivityId": "d0f30c8c-e6c6-45b6-9275-73dd6b379ecf",
                "activityType": "DN.FE.ExecuteQuery",
                "parentActivityId": "6e3c8dab-0aaf-4df5-85b5-fc20b0b29a84",
                "activityStack": "(Activity stack: CRID=Kusto.Cli;b90f4260-4eac-4574-a27a-3f302db21404 ARID=9dcc4522-7b51-41db-a7ae-7c1bfe0696b2 > KD.Query.Client.ExecuteQueryAsKustoDataStream/8191428e-7139-4c5d-9da7-839a0f21c5b9 > P.WCF.Service.ExecuteQueryAsKustoDataStream..IInterNodeCommunicationQueryContract/6e3c8dab-0aaf-4df5-85b5-fc20b0b29a84 > DN.FE.ExecuteQuery/d0f30c8c-e6c6-45b6-9275-73dd6b379ecf)"
            },
            "@permanent": true,
            "@errorCode": "SEM0100",
            "@errorMessage": "'table' operator: Failed to resolve table expression named 'aaa'"
        }
    }
}

Treść odpowiedzi HTTP (po pomyślnych żądaniach)

Po pomyślnym żądaniu treść odpowiedzi HTTP będzie tablicą JSON, która koduje wyniki żądania.

Logicznie odpowiedź w wersji 2 opisuje obiekt DataSet , który zawiera dowolną liczbę tabel. Te tabele mogą reprezentować rzeczywiste dane wymagane przez żądanie lub dodatkowe informacje o wykonaniu żądania (takie jak ewidencjonowanie zasobów używanych przez żądanie). Ponadto rzeczywiste żądanie może rzeczywiście zakończyć się niepowodzeniem (z powodu różnych warunków), nawet jeśli 200 OK zostanie zwrócony stan, a w takim przypadku odpowiedź będzie zawierać częściowe dane odpowiedzi oraz wskazanie błędów.

Fizycznie tablica JSON treści odpowiedzi jest listą obiektów JSON, z których każda jest nazywana ramką. Obiekt DataSet jest zakodowany w dwóch ramkach: DataSetHeader i DataSetCompletion. Pierwsza jest zawsze pierwszą ramką, a druga jest zawsze ostatnią ramką. W obszarze "między" można znaleźć ramki opisujące obiekty tabeli.

Obiekty tabeli można kodować na dwa sposoby:

  1. Jako pojedyncza ramka: DataTable. Jest to opcja domyślna.

  2. Alternatywnie jako "mieszanka" czterech rodzajów ramek: TableHeader (który jest pierwszy i opisuje tabelę), TableFragment (który opisuje dane tabeli), TableProgress (opcjonalnie i przedstawia oszacowanie, jak daleko w danych tabeli jesteśmy) i TableCompletion (która jest ostatnią ramką tabeli).

Drugi przypadek jest nazywany "trybem progresywnym" i będzie wyświetlany tylko wtedy, gdy właściwość results_progressive_enabled żądania klienta ma wartość true. W takim przypadku każda ramka TableFragment opisuje aktualizację danych zebranych przez wszystkie poprzednie takie ramki dla tabeli jako operację dołączania lub jako operację zastępowania. (Ten ostatni jest używany, na przykład, gdy niektóre długotrwałe obliczenia agregacji są wykonywane na "najwyższym poziomie" zapytania, więc początkowy wynik agregacji jest zastępowany przez dokładniejsze wyniki później.

DataSetHeader

Ramka DataSetHeader jest zawsze pierwszą w zestawie danych i jest wyświetlana dokładnie raz.

{
    "Version": string,
    "IsProgressive": Boolean
}

Gdzie:

  • Version jest wersją protokołu. Bieżąca wersja to v2.0.

  • IsProgressive jest flagą logiczną wskazującą, czy ten zestaw danych zawiera ramki progresywne. Ramka progresywna jest jedną z:

    Klatka Opis
    TableHeader Zawiera ogólne informacje o tabeli
    TableFragment Zawiera prostokątny fragment danych tabeli
    TableProgress Zawiera postęp w procentach (0–100)
    TableCompletion Wskazuje, że ta ramka jest ostatnią ramką

    Powyższe ramki opisują tabelę. Jeśli flaga IsProgressive nie jest ustawiona na true, każda tabela w zestawie będzie serializowana przy użyciu jednej ramki:

  • DataTable: zawiera wszystkie informacje wymagane przez klienta dotyczące pojedynczej tabeli w zestawie danych.

TableHeader

Zapytania, które są tworzone z ustawioną opcją results_progressive_enabled true, mogą zawierać tę ramkę. W tej tabeli klienci mogą oczekiwać przeplatania sekwencji TableFragment ramek i TableProgress . Ostatnia ramka tabeli to TableCompletion.

{
    "TableId": Number,
    "TableKind": string,
    "TableName": string,
    "Columns": Array,
}

Gdzie:

  • TableId jest unikatowym identyfikatorem tabeli.

  • TableKind to jedna z następujących wartości:

    • PrimaryResult
    • QueryCompletionInformation
    • QueryTraceLog
    • QueryPerfLog
    • TableOfContents
    • QueryProperties
    • QueryPlan
    • Nieznane
  • TableName to nazwa tabeli.

  • Columns to tablica opisująca schemat tabeli.

{
    "ColumnName": string,
    "ColumnType": string,
}

Obsługiwane typy kolumn zostały opisane tutaj.

TabelaFragment

Ramka TableFragment zawiera prostokątny fragment danych tabeli. Oprócz rzeczywistych danych ramka TableFragmentType zawiera również właściwość, która informuje klienta, co należy zrobić z fragmentem. Fragment dołączony do istniejących fragmentów lub je zastąpić.

{
    "TableId": Number,
    "FieldCount": Number,
    "TableFragmentType": string,
    "Rows": Array
}

Gdzie:

  • TableId jest unikatowym identyfikatorem tabeli.

  • FieldCount to liczba kolumn w tabeli.

  • TableFragmentType Opisuje, co klient powinien zrobić z tym fragmentem. TableFragmentType to jedna z następujących wartości:

    • DataAppend
    • DataReplace
  • Rows to dwuwymiarowa tablica zawierająca dane fragmentu.

TableProgress

Ramka TableProgress może przeplatać się z ramką opisaną TableFragment powyżej. Jedynym celem jest powiadomienie klienta o postępie zapytania.

{
    "TableId": Number,
    "TableProgress": Number,
}

Gdzie:

  • TableId jest unikatowym identyfikatorem tabeli.
  • TableProgress to postęp w procentach (0--100).

TableCompletion

Ramka TableCompletion oznacza koniec transmisji tabeli. Nie będą wysyłane żadne ramki powiązane z tabelą.

{
    "TableId": Number,
    "RowCount": Number,
}

Gdzie:

  • TableId jest unikatowym identyfikatorem tabeli.
  • RowCount to całkowita liczba wierszy w tabeli.

DataTable

Zapytania wystawione przy użyciu flagi ustawionej na EnableProgressiveQuery wartość false nie będą zawierać żadnej z ramek (TableHeader, TableFragment, TableProgressi TableCompletion). Zamiast tego każda tabela w zestawie danych zostanie przesłana przy użyciu ramki zawierającej DataTable wszystkie informacje wymagane przez klienta, aby odczytać tabelę.

{
    "TableId": Number,
    "TableKind": string,
    "TableName": string,
    "Columns": Array,
    "Rows": Array,
}

Gdzie:

  • TableId jest unikatowym identyfikatorem tabeli.

  • TableKind to jedna z następujących wartości:

    • PrimaryResult
    • QueryCompletionInformation
    • QueryTraceLog
    • QueryPerfLog
    • QueryProperties
    • QueryPlan
    • Nieznane
  • TableName to nazwa tabeli.

  • Columns to tablica opisująca schemat tabeli i zawiera następujące elementy:

{
    "ColumnName": string,
    "ColumnType": string,
}
  • Rows to dwuwymiarowa tablica zawierająca dane tabeli.

Znaczenie tabel w odpowiedzi

  • PrimaryResult — główny wynik tabelaryczny zapytania. Dla każdej instrukcji wyrażenia tabelarycznego co najmniej jedna tabela jest generowana w kolejności, reprezentując wyniki wygenerowane przez instrukcję . Może istnieć wiele takich tabel ze względu na partie i operatory rozwidlenia.
  • QueryCompletionInformation — Zawiera dodatkowe informacje o wykonywaniu samego zapytania, takie jak pomyślne, czy nie, i jakie zasoby zostały zużyte przez zapytanie (podobnie jak tabela QueryStatus w odpowiedzi v1).
  • QueryProperties — Udostępnia dodatkowe wartości, takie jak instrukcje wizualizacji klienta (emitowane na przykład w celu odzwierciedlenia informacji w operatorze renderowania) i informacje o kursorze bazy danych .
  • QueryTraceLog — Informacje dziennika śledzenia wydajności (zwracane, gdy perftracewe właściwościach żądania klienta jest ustawiona wartość true).

DataSetCompletion

Ramka DataSetCompletion jest ostatnią ramką w zestawie danych.

{
    "HasErrors": Boolean,
    "Cancelled": Boolean,
    "OneApiErrors": Array,
}

Gdzie:

  • HasErrors wartość ma wartość true, jeśli podczas generowania zestawu danych wystąpiły błędy.
  • Cancelled ma wartość true, jeśli żądanie, które doprowadziło do wygenerowania zestawu danych, zostało anulowane przed ukończeniem.
  • OneApiErrors jest zwracany tylko wtedy, gdy HasErrors ma wartość true. OneApiErrors Opis formatu można znaleźć w sekcji 7.10.2 tutaj.