Compartir a través de


TripPin, parte 8: Adición de diagnósticos

Nota:

Actualmente, este contenido hace referencia al contenido de una implementación heredada para diagnósticos en Visual Studio. El contenido se actualizará casi en el futuro para cubrir el nuevo SDK de Power Query en Visual Studio Code.

En este tutorial de varias partes se describe la creación de una nueva extensión de origen de datos para Power Query. El tutorial está diseñado para realizarse secuencialmente: cada lección se basa en el conector creado en las lecciones anteriores, agregando incrementalmente nuevas funcionalidades al conector.

En esta lección:

  • Más información sobre la función Diagnostics.Trace
  • Uso de las funciones auxiliares de diagnóstico para agregar información de seguimiento para ayudar a depurar el conector

Habilitación de diagnósticos

Los usuarios de Power Query pueden habilitar el registro de seguimiento activando la casilla en Opciones | Diagnósticos.

Captura de pantalla de las opciones de Power Query con la pestaña Diagnósticos seleccionada y el seguimiento habilitados.

Una vez habilitada, las consultas posteriores hacen que el motor de M emita información de seguimiento a los archivos de registro ubicados en un directorio de usuario fijo.

Al ejecutar consultas M desde el SDK de Power Query, el seguimiento está habilitado en el nivel de proyecto. En la página de propiedades del proyecto, hay tres valores relacionados con el seguimiento:

  • Borrar registro: cuando se establece en true, el registro se restablece o borra al ejecutar las consultas. Se recomienda mantener este valor establecido en true.

  • Mostrar rastros del motor: esta opción controla la salida de rastros integrados desde el motor M. Estos seguimientos solo son útiles para los miembros del equipo de Power Query, por lo que normalmente se recomienda mantener esta configuración en false.

  • Mostrar seguimientos de usuario: esta configuración controla la salida de la información de seguimiento por el conector. Quiere establecer true en esta configuración.

    Captura de pantalla de las páginas de propiedades de TripPin que muestran los tres valores relacionados con el seguimiento.

Una vez habilitada, las entradas de registro se muestran en la ventana Salida de consulta M, en la pestaña Registro.

Diagnostics.Trace

La función Diagnostics.Trace se usa para escribir mensajes en el registro de seguimiento del motor de M.

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

Importante

M es un lenguaje funcional con evaluación diferida. Al usar Diagnostics.Trace, tenga en cuenta que solo se llama a la función si la expresión forma parte de lo que realmente se evalúa. Los ejemplos de este comportamiento se pueden encontrar más adelante en este tutorial.

El traceLevel parámetro puede ser uno de los siguientes valores (en orden descendente):

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

Cuando el seguimiento está habilitado, el usuario puede seleccionar el nivel máximo de mensajes que desea ver. Todos los mensajes de seguimiento de este nivel e inferiores se registran en el log. Por ejemplo, si el usuario selecciona el nivel "Advertencia", los mensajes de seguimiento de TraceLevel.Warning, TraceLevel.Errory TraceLevel.Critical aparecen en los registros.

El message parámetro es la salida de texto real en el archivo de seguimiento. El texto no contiene el value parámetro a menos que lo incluya explícitamente en el texto.

El value parámetro es lo que devuelve la función. Cuando el parámetro delayed se establece en true, value es una función sin parámetros que devuelve el valor real que está evaluando. Cuando delayed se establece en false, value es el valor real. Un ejemplo de cómo funciona esto se puede encontrar en Evaluación retrasada.

Uso de Diagnostics.Trace en el conector TripPin

Para obtener un ejemplo práctico del uso de Diagnostics.Trace y el impacto del delayed parámetro, actualice la función del conector GetSchemaForEntity TripPin para envolver la error excepción:

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);

Puede forzar un error durante la evaluación (con fines de prueba) pasando un nombre de entidad no válido a la GetEntity función. Aquí cambias la línea withData en la función TripPinNavTable, reemplazando [Name] con "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;

Habilite el seguimiento del proyecto y ejecute las consultas de prueba. En la Errors pestaña debería ver el texto del error que ha generado:

Captura de pantalla de la salida de la consulta M con el error 'no existe' mostrado.

Además, en la Log pestaña, deberías ver el mismo mensaje. Si usa valores diferentes para los message parámetros y value , estos valores serían diferentes.

Captura de pantalla de la etiqueta de registro en la salida de la consulta M con el mensaje de registro resaltado.

Tenga en cuenta también que el Action campo del mensaje de registro contiene el nombre (Tipo de origen de datos) de la extensión (en este caso, Engine/Extension/TripPin). Este campo facilita la búsqueda de los mensajes relacionados con la extensión cuando hay múltiples consultas implicadas y/o cuando el seguimiento del sistema (motor de mashup) está habilitado.

Evaluación retrasada

Como ejemplo de cómo funciona el delayed parámetro, necesita realizar algunas modificaciones y volver a ejecutar las consultas.

En primer lugar, establezca en el valor delayedfalse, pero deje el parámetro value tal como está:

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

Al ejecutar la consulta, recibirá un error que indica que "No se puede convertir un valor de tipo Function a tipo Type" y no el error real que ha generado. Esta diferencia se debe a que la llamada ahora devuelve un function valor, en lugar del propio valor.

A continuación, quite la función del parámetro value:

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

Al ejecutar la consulta, recibirá el error correcto, pero si comprueba la pestaña Registro , no hay ningún mensaje. Esta discrepancia se debe error a que termina siendo generado o evaluado durante la llamada a Diagnostics.Trace, por lo que el mensaje nunca se genera realmente.

Ahora que comprende el impacto del parámetro, asegúrese de restablecer el delayed conector a un estado de trabajo antes de continuar.

Funciones auxiliares de diagnóstico en Diagnostics.pqm

El archivo Diagnostics.pqm incluido en este proyecto contiene muchas funciones auxiliares que facilitan el seguimiento. Como se muestra en el tutorial anterior, puede incluir este archivo en el proyecto (recuerde establecer la acción de compilación en Compilar) y, a continuación, cargarlo en el archivo del conector. La parte inferior del archivo del conector debería tener ahora un aspecto similar al siguiente fragmento de código. No dude en explorar las distintas funciones que proporciona este módulo, pero en este ejemplo solo se usan las Diagnostics.LogValue funciones y 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

La función Diagnostics.LogValue es muy similar a Diagnostics.Trace, y se puede usar para generar el valor de lo que usted está evaluando.

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

El prefix parámetro se antepone al mensaje de registro. Este parámetro se usa para averiguar qué llamada genera el mensaje. El value parámetro es el valor que la función devuelve y se escribe también en la traza como una representación en texto del valor M. Por ejemplo, si value es igual a un table con las columnas A y B, el registro contiene la representación equivalente #table: #table({"A", "B"}, {{"row1 A", "row1 B"}, {"row2 A", row2 B"}})

Nota:

La serialización de valores de M en texto puede ser una operación costosa. Tenga en cuenta el tamaño potencial de los valores que va a generar en el seguimiento.

Nota:

La mayoría de los entornos de Power Query truncan los mensajes de seguimiento a una longitud máxima.

Por ejemplo, actualice la TripPin.Feed función para realizar un seguimiento de los url argumentos y schema pasados a la función .

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;

Debe usar los nuevos _url y _schema valores en la llamada a GetAllPagesByNextLink. Si ha usado los parámetros de función originales, las Diagnostics.LogValue llamadas nunca se evalúan realmente, lo que no da lugar a ningún mensaje escrito en el seguimiento. ¡La programación funcional es divertida!

Al ejecutar las consultas, ahora debería ver nuevos mensajes en el registro.

Acceso a la dirección URL:

Captura de pantalla de la salida de la consulta M que muestra el mensaje de dirección URL de acceso.

Tipo de esquema:

Captura de pantalla de la salida de la consulta M que muestra el mensaje de tipo de esquema.

Se muestra la versión serializada del schema parámetro type, en lugar de lo que se obtiene al hacer un sencillo Text.FromValue en un tipo de valor (lo que da como resultado "tipo").

Diagnostics.LogFailure

La Diagnostics.LogFailure función se puede usar para encapsular las llamadas de función y solo escribe en el seguimiento si se produce un error en la llamada de función (es decir, devuelve un error).

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

Internamente, Diagnostics.LogFailure agrega un try operador a la function llamada. Si se produce un error en la llamada, el text valor se escribe en el seguimiento antes de devolver el original error. Si la llamada function se realiza correctamente, el resultado se devuelve sin escribir nada en el registro. Dado que los errores de M no contienen un seguimiento de pila completo (es decir, normalmente solo se ve el mensaje del error), esta función puede ser útil cuando desea identificar dónde se generó el error.

Como ejemplo (deficiente), modifique la withData línea de la TripPinNavTable función para forzar un error una vez más:

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

En la traza, puede encontrar el mensaje de error resultante que contiene tu text y la información de error original.

Captura de pantalla de la salida de la consulta M que muestra el mensaje de error del registro.

Asegúrese de restablecer la función a un estado de trabajo antes de continuar con el siguiente tutorial.

Conclusión

Esta breve lección (pero importante) le mostró cómo usar las funciones auxiliares de diagnóstico para iniciar sesión en los archivos de seguimiento de Power Query. Cuando se usa correctamente, estas funciones son útiles para depurar problemas dentro del conector.

Nota:

Como desarrollador de conectores, es su responsabilidad asegurarse de que no registra información confidencial o de identificación personal (PII) como parte del registro de diagnóstico. También debe tener cuidado de no generar demasiada información de seguimiento, ya que puede tener un impacto negativo en el rendimiento.

Pasos siguientes

TripPin, parte 9: TestConnection