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á en un futuro próximo 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 seguirse secuencialmente: cada lección se basa en el conector creado en las lecciones anteriores, agregando incrementalmente nuevas funcionalidades al conector.

En esta lección, aprenderá lo siguiente:

  • 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 seleccionando la casilla en Opciones | Diagnósticos.

Habilite el seguimiento en Power Query.

Una vez habilitado, las consultas posteriores harán 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 se habilita en el nivel de proyecto. En la página de propiedades del proyecto, hay tres valores relacionados con el seguimiento:

  • Clear Log (Borrar registro): cuando esta opción se establezca en true, el registro se restablecerá o borrará cuando se ejecuten las consultas. Le recomendamos que la mantenga establecida en true.
  • Show Engine Traces (Mostrar seguimientos del motor): esta opción controla la salida de seguimientos integrados del motor de M. Estos seguimientos solo son útiles para los miembros del equipo de Power Query, por lo que normalmente es recomendable mantener esta opción establecida en false.
  • Show User Traces (Mostrar seguimientos de usuario): esta opción controla la información de seguimiento generada por el conector. Es recomendable establecer esta opción en true.

Propiedades del proyecto.

Una vez habilitada, empezará a ver las entradas de registro en la ventana M Query Output (Salida de consulta M), en la pestaña Log (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 llamará a la función si la expresión de la que forma parte realmente se evalúa. Encontrará ejemplos de esto más adelante en este tutorial.

El parámetro traceLevel puede ser en uno de los valores siguientes (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 y de niveles inferiores en se mostrarán en el registro. Por ejemplo, si el usuario selecciona el nivel "Advertencia", los mensajes de seguimiento de TraceLevel.Warning, TraceLevel.Error y TraceLevel.Critical aparecerán en los registros.

El parámetro message es el texto real que se generará en el archivo de seguimiento. El texto no contendrá el parámetro value a menos que usted lo incluya explícitamente en el texto.

El parámetro value es lo que devolverá la función. Cuando el parámetro delayed se establezca en true, value será una función de parámetro cero que devuelve el valor real que se está evaluando. Cuando delayed se establezca en false, value será el valor real. A continuación se muestra un ejemplo de cómo funciona esto.

Uso de diagnósticos. Seguimiento en el conector de TripPin

Para obtener un ejemplo práctico del uso de Diagnostics.Trace y el impacto del parámetro delayed, actualice la función GetSchemaForEntity del conector TripPin para ajustar la excepción 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);

Puede forzar un error durante la evaluación (con fines de prueba). Para ello, pase un nombre de entidad no válido a la función GetEntity. Aquí se cambia la línea withData de la función TripPinNavTable, reemplazando [Name] por "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 para el proyecto y ejecute las consultas de prueba. En la pestaña Errors debería ver el texto del error que ha generado:

Mensaje de error.

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

Registro de errores.

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

Evaluación retrasada

Como ejemplo de cómo funciona el parámetro delayed, deberá llevar a cabo algunas modificaciones y ejecutar las consultas de nuevo.

En primer lugar, establezca el valor delayed en false, 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 "We cannot convert a value of type Function to type Type" (No se puede convertir un valor de tipo Función a tipo Tipo) y no el error real que usted ha generado. Esto se debe a que la llamada ahora devuelve un valor function, 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 Log (Registro), no habrá ningún mensaje. Esto se debe a que error termina generándose o evaluándose durante la llamada a Diagnostics.Trace, por lo que el mensaje nunca se emite realmente.

Ahora que ya sabe cuál es el impacto del parámetro delayed, asegúrese de restablecer el conector a un estado de funcionamiento 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 ahora debería ser similar al fragmento de código siguiente. No dude en explorar las distintas funciones que proporciona este módulo, pero en este ejemplo, solo usará las funciones Diagnostics.LogValue 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 se está evaluando.

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

El parámetro prefix se antepone al mensaje de registro. Se usaría para averiguar qué llamada genera el mensaje. El parámetro value es lo que devolverá la función y también se escribirá en el seguimiento como una representación de texto del valor M. Por ejemplo, si value es igual a table con las columnas A y B, el registro contendrá la representación #table equivalente: #table({"A", "B"}, {{"row1 A", "row1 B"}, {"row2 A", row2 B"}})

Nota:

La serialización de valores 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 truncarán los mensajes de seguimiento a una longitud máxima.

Por ejemplo, usted actualizará la función TripPin.Feed para realizar un seguimiento de los argumentos url 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;

Tiene que usar los nuevos valores _url y _schema en la llamada a GetAllPagesByNextLink. Si usó los parámetros de función originales, las llamadas Diagnostics.LogValue nunca se evaluarían realmente, lo que provocaría que no se escribiese ningún mensaje 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:

Acceso al mensaje de dirección URL.

Tipo de esquema:

Mensaje de tipo esquema.

Verá la versión serializada del parámetro schema type, en lugar de lo que obtendría al llevar a cabo un simple Text.FromValue en un valor de tipo (lo que da como resultado "type").

Diagnostics.LogFailure

La función Diagnostics.LogFailure se puede usar para encapsular llamadas de función y solo escribirá 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 operador try a la llamada function. Si se produce un error en la llamada, el valor text 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 seguimiento. Dado que los errores de M no contienen un seguimiento de pila completo (es decir, normalmente solo se ve el mensaje del error), esto puede resultar útil cuando se desea identificar dónde se generó el error.

Como ejemplo (poco adecuado), modifique la línea withData de la función TripPinNavTable 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 el seguimiento, puede encontrar el mensaje de error resultante que contiene el text y la información del error original.

Mensaje LogFailure.

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

Conclusión

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

Nota:

Como desarrollador de conectores, debe asegurarse de que registrar 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