Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Observação
Este conteúdo atualmente faz referência a conteúdos de uma implementação legada para diagnósticos no Visual Studio. O conteúdo será atualizado em breve para cobrir o novo Power Query SDK no Visual Studio Code.
Este tutorial em várias partes aborda a criação de uma nova extensão de fonte de dados para o Power Query. O tutorial destina-se a ser feito sequencialmente — cada lição baseia-se no conector criado nas aulas anteriores, adicionando gradualmente novas capacidades ao seu conector.
Nesta lição, vocês:
- Aprenda mais sobre a função Diagnostics.Trace
- Use as funções auxiliares de Diagnóstico para adicionar informação de rastreio e ajudar a depurar o seu conector
Habilitação de diagnósticos
Os utilizadores do Power Query podem ativar o registo de traços selecionando a caixa de seleção em Opções | Diagnósticos.
Uma vez ativadas, quaisquer consultas subsequentes fazem com que o motor M emita informação de rastreio para ficheiros de registo localizados num diretório fixo de utilizador.
Quando executa consultas M no Power Query SDK, o rastreamento é ativado ao nível do projeto. Na página de propriedades do projeto, existem três definições relacionadas com o rastreio:
Limpar Registo: Quando definido para
true, o registo é reiniciado/limpo quando executa as suas consultas. Recomendamos que mantenha isto definido paratrue.Mostrar Registos do Motor: Esta definição controla a saída dos registos incorporados do motor M. Estes registos são úteis apenas para membros da equipa do Power Query, por isso normalmente deves deixar isto configurado como
false.Mostrar Traços do Utilizador: Esta definição controla a informação de rastreio emitida pelo seu conector. Quer definir esta definição para
true.
Uma vez ativadas, as entradas de registo são mostradas na janela de Saída de Consulta M, na aba Log.
Diagnostics.Trace
A função Diagnostics.Trace é usada para escrever mensagens no registo de traços do motor M.
Diagnostics.Trace = (traceLevel as number, message as text, value as any, optional delayed as nullable logical as any) => ...
Importante
M é uma linguagem funcional com avaliação preguiçosa. Ao usar Diagnostics.Trace, tenha em mente que a função só é chamada se a expressão fizer parte do que está realmente a ser avaliado. Exemplos deste comportamento podem ser encontrados mais adiante neste tutorial.
O traceLevel parâmetro pode ser um dos seguintes valores (por ordem decrescente):
TraceLevel.CriticalTraceLevel.ErrorTraceLevel.WarningTraceLevel.InformationTraceLevel.Verbose
Quando o rastreio está ativado, o utilizador pode selecionar o nível máximo de mensagens que deseja ver. Todas as mensagens de rastreio deste nível e abaixo são enviadas para o log. Por exemplo, se o utilizador selecionar o nível "Aviso", as mensagens de TraceLevel.Warning, TraceLevel.Error e TraceLevel.Critical aparecem nos registos.
O message parâmetro é o texto realmente enviado para o ficheiro de traço. O texto não contém o value parâmetro a menos que o inclua explicitamente no texto.
O value parâmetro é o que a função devolve. Quando o delayed parâmetro está definido para true, value é uma função de parâmetro zero que devolve o valor real que está a avaliar. Quando delayed está definido como false, value é o valor real. Um exemplo de como isto funciona pode ser encontrado em Avaliação Retardada.
Utilização do Diagnostics.Trace no conector TripPin
Para um exemplo prático de utilização de Diagnostics.Trace e do parâmetro delayed, atualize a função do conector GetSchemaForEntity TripPin para encapsular a exceção 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);
Pode forçar um erro durante a avaliação (para fins de teste) passando um nome de entidade inválido para a função GetEntity. Aqui muda a withData linha na TripPinNavTable função, substituindo [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;
Ativa o rastreio para o teu projeto e executa as tuas consultas de teste. Na aba Errors deverá ver o texto do erro que levantou:
Além disso, no Log separador, deverás ver a mesma mensagem. Se usares valores diferentes para os message parâmetros e, value esses valores seriam diferentes.
Note também que o Action campo da mensagem de registo contém o nome (Data Source Type) da sua extensão (neste caso, Engine/Extension/TripPin). Este campo facilita a localização das mensagens relacionadas com a sua extensão quando há múltiplas consultas envolvidas e/ou o rastreio do sistema (motor mashup) está ativado.
Avaliação tardia
Como exemplo de como o delayed parâmetro funciona, precisa de fazer algumas modificações e executar as consultas novamente.
Primeiro, defina o delayed valor para false, mas deixe o value parâmetro as-is:
Diagnostics.Trace(TraceLevel.Error, message, () => error message, false);
Quando executa a consulta, recebe um erro indicando que "Não podemos converter um valor do tipo Função para o tipo Tipo", e não o erro real que reportou. Esta diferença deve-se ao facto de a chamada estar agora a devolver um function valor, em vez do valor em si.
De seguida, remova a função do value parâmetro:
Diagnostics.Trace(TraceLevel.Error, message, error message, false);
Quando executas a consulta, recebes o erro correto, mas se consultares o separador Log , não aparecem mensagens. Esta discrepância deve-se ao facto de o error acabar por ser levantado/avaliado durante a chamada para Diagnostics.Trace, pelo que a mensagem nunca é de facto enviada.
Agora que compreendes o impacto do delayed parâmetro, certifica-te de que o conector volta a funcionar antes de avançar.
Funções auxiliares de diagnóstico no Diagnostics.pqm
O ficheiro Diagnostics.pqm incluído neste projeto contém muitas funções auxiliares que facilitam o rastreamento. Como mostrado no tutorial anterior, podes incluir este ficheiro no teu projeto (lembrando-te de definir a Build Action para Compilar) e depois carregá-lo no ficheiro do conector. A parte final do ficheiro do seu conector deverá agora ficar semelhante ao seguinte excerto de código. Sente-te à vontade para explorar as várias funções que este módulo oferece, mas neste exemplo, só usas as funções Diagnostics.LogValue e 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
A função Diagnostics.LogValue é muito semelhante a Diagnostics.Trace, e pode ser usada para exibir o valor do que está a ser avaliado.
Diagnostics.LogValue = (prefix as text, value as any) as any => ...
O prefix parâmetro é anteposto à mensagem de log. Usas este parâmetro para perceber que chamada gera a mensagem. O value parâmetro é o que a função devolve, e também é escrito no traço como uma representação em texto do valor M. Por exemplo, se value for igual a a table com as colunas A e B, o logaritmo contém a representação equivalente #table : #table({"A", "B"}, {{"row1 A", "row1 B"}, {"row2 A", row2 B"}})
Observação
Serializar valores M em texto pode ser uma operação dispendiosa. Esteja atento ao tamanho potencial dos valores que está a enviar para o rastreio.
Observação
A maioria dos ambientes Power Query trunca as mensagens de rastreamento até um comprimento máximo.
Por exemplo, atualize a função TripPin.Feed para rastrear os argumentos url e schema passados para a função.
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;
Tens de usar os valores novos _url e _schema na chamada para GetAllPagesByNextLink. Se usasse os parâmetros originais da função, as Diagnostics.LogValue chamadas nunca seriam realmente avaliadas, resultando em nenhuma mensagem escrita no rastreio.
Programação funcional é divertida!
Quando executas as tuas consultas, agora deves ver novas mensagens no registo.
Aceder ao URL:
Tipo de esquema:
A versão serializada do parâmetro schematype é apresentada, em vez do que se obtém quando se faz um simples Text.FromValue a um valor do tipo (que resulta em "tipo").
Diagnostics.LogFailure
A função Diagnostics.LogFailure pode ser usada para encapsular chamadas de função, e só escreve no registo se a chamada falhar (ou seja, retorna um error que indica falha).
Diagnostics.LogFailure = (text as text, function as function) as any => ...
Internamente, Diagnostics.LogFailure adiciona um operador try à chamada function. Se a chamada falhar, o valor text é escrito no tracing antes de devolver o original error. Se a function chamada for bem-sucedida, o resultado é devolvido sem escrever nada no rastreio. Como os erros M não contêm um traço de stack completo (ou seja, normalmente só vê a mensagem do erro), esta função pode ser útil quando se quer identificar exatamente onde o erro foi gerado.
Como um exemplo pobre, modifique a linha withData da função TripPinNavTable para forçar um erro novamente:
withData = Table.AddColumn(rename, "Data", each Diagnostics.LogFailure("Error in GetEntity", () => GetEntity(url, "DoesNotExist")), type table),
No rastreio, pode encontrar a mensagem de erro resultante que contém o seu text, e a informação de erro original.
Certifique-se de reiniciar a sua função para um estado funcional antes de prosseguir com o próximo tutorial.
Conclusion
Esta breve (mas importante) lição mostrou-lhe como utilizar as funções auxiliares de diagnóstico para aceder aos ficheiros de rastreamento do Power Query. Quando usadas corretamente, estas funções são úteis para depurar problemas dentro do seu conector.
Observação
Como desenvolvedor de conectores, é sua responsabilidade garantir que não regista informações sensíveis ou pessoais identificáveis (PII) como parte do seu registo de diagnóstico. Também deve ter cuidado para não fornecer demasiada informação de rastreamento, pois pode ter um impacto negativo no desempenho.