Nesse post vou ensinar para vocês como conectar o power bi com o zabbix utilizando o power query.
Se autenticando na API do Zabbix
O primeiro passo será criarmos a autenticação do Power BI com a api do Zabbix. Conforme podemos ver na documentação do Zabbix (https://www.zabbix.com/documentation/current/pt/manual/api), primeiro precisamos se autenticar e receber um token. Para isso precisamos enviar uma requisição POST para o end-point /api_jsonrpc.php, com um JSON como corpo da requisição com os parâmetros para a autenticação
POST http://company.com/zabbix/api_jsonrpc.php HTTP/1.1
Content-Type: application/json-rpc
{
"jsonrpc": "2.0",
"method": "user.login",
"params": {
"user": "Admin",
"password": "zabbix"
},
"id": 1,
"auth": null
}
Note que a API do Zabbix mantém a mesma estrutura de end-point mas via o JSON que está no corpo da requisição, nós conseguimos ir mudando os métodos que queremos acesso aos dados, como o acima user.login utilizado para se autenticar. Após realizarmos essa chamada a API do Zabbix nos retornará o seguinte resultado em um JSON
{
"jsonrpc": "2.0",
"result": "0424bd59b807674191e7d77572075f33",
"id": 1
}
Onde no parâmetro result do JSON ela nos retorna um token aleatório que será utilizado para se autenticar com os outros métodos. (para qualquer método que você queira retornar do Zabbix você vai precisar desse token)
Como conectar o Power Bi com o Zabbix na api de autenticação
Agora que sabemos a lógica por trás da autenticação da api do Zabbix, vamos colocar isso em prática no Power BI.
Crie parâmetros no Power BI para facilitar o login.
Primeiro crie alguns parâmetros que iremos utilizar para ficar mais simples a mudança de ambientes e usuários (caso não queira você pode “chumbar” esses parâmetros diretamente no código da linguagem M no Power Query).
Crie os seguintes parâmetros no Power BI:
- User
- Password
- ZabbixURL
Criando a função de autenticação
Primeiramente iremos criar uma função no Power Query chamada GetZabbixToken que irá enviar uma solicitação HTTP se autenticando com o ambiente do zabbix, no corpo da requisição iremos colocar o usuário e senha da conta que iremos utilizar para ver os dados do Zabbix, e ao se autenticar o zabbix irá retornar um token, esse será utilizado nas outras requisições para confirmar que o usuário fez a autenticação.
(O código M abaixo deve ser colado na parte do editor avançado do Power Query no Power BI )
(Usuario as text ,Senha as text, URL as text) =>
let
user=Usuario,
password=Senha,
url=URL,
Body = "{
""jsonrpc"": ""2.0"",
""method"": ""user.login"",
""params"": {
""user"":""" & user & """,
""password"":""" & password & """
},
""auth"": null,
""id"": 1
}",
Source = Json.Document (
Web.Contents(
url,
[
Headers=[
#"Content-Type"="application/json"
],
Content = Text.ToBinary(Body)
]
)
),
#"Converted to Table" = Record.ToTable(Source),
#"Filtered Rows" = Table.SelectRows(#"Converted to Table", each ([Name] = "result")),
Value = #"Filtered Rows"{0}[Value]
in
Value
Nesse código do M, basicamente é uma função com 3 parâmetros:
- Usuario
- Senha
- URL
Esses parâmetros entram no json da variável body e são enviados através do step de Source, depois os steps abaixo pegam o retorno e colocam como retorno da função do Power Query.
Criando chamadas para a api
Com a função de autenticação pronta, você pode fazer chamadas para todos end-points da api do zabbix, a maioria deles mantem o mesmo padrão somente trocando o parâmetro method do corpo JSON da requisição que é enviada ao zabbix.
Vou dar um exemplo de como listar todos usuários do ambiente do zabbix.
(O código M abaixo deve ser colado na parte do editor avançado do Power Query no Power BI )
let
token = GetZabbixToken(User,Password,ZabbixURL),
Body =
"{
""jsonrpc"": ""2.0"",
""method"": ""user.get"",
""params"": {
""output"": ""extend""
},
""auth"": """ & token & """,
""id"": 1
}",
Source = Json.Document(
Web.Contents(
ZabbixURL,
[
Headers=[
#"Content-Type"="application/json"
],
Content = Text.ToBinary(Body)
]
)
),
result = Source[result],
#"Converted to Table" = Table.FromList(result, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", {"userid", "alias", "name", "surname", "url", "autologin", "autologout", "lang", "refresh", "type", "theme", "attempt_failed", "attempt_ip", "attempt_clock", "rows_per_page"}, {"userid", "alias", "name", "surname", "url", "autologin", "autologout", "lang", "refresh", "type", "theme", "attempt_failed", "attempt_ip", "attempt_clock", "rows_per_page"})
in
#"Expanded Column1"
Na variável token é chamada a função que se autentica com zabbix e retorna o token, depois utilizamos ele na chamada http para se autenticar, essa chamada como eu disse anteriormente acaba sendo padrão para quase toda api, somente mudando o method do JSON e alguns parâmetros nesse JSON, mas a estrutura é igual.
(O código M abaixo deve ser colado na parte do editor avançado do Power Query no Power BI )
token = GetZabbixToken(User,Password,ZabbixURL),
Body =
"{
""jsonrpc"": ""2.0"",
""method"": ""user.get"",
""params"": {
""output"": ""extend""
},
""auth"": """ & token & """,
""id"": 1
}",
Source = Json.Document(
Web.Contents(
ZabbixURL,
[
Headers=[
#"Content-Type"="application/json"
],
Content = Text.ToBinary(Body)
]
)
),
result = Source[result],
Note que esse trecho do código acima será sempre um padrão para suas chamadas, e você pode ir reaproveitando isso e mudando somente o end-point e o consequentemente o corpo JSON da requisição.
Criando uma função que pega os registros de um step e scenario
Essa função automatiza muita coisa, e com ela você consegue ver alguns parâmetros que podem ser configurados no Zabbix, como uma rotina que fica verificando se uma API está online, qual tempo de resposta, velocidade de download e qual o código de resposta.
(O código M abaixo deve ser colado na parte do editor avançado do Power Query no Power BI )
(Step as text, Scenario as text) =>
let
token = GetZabbixToken(User,Password,ZabbixURL),
Lista = {"Response time","Download speed","Response code"},
GetItemID = (Valores) =>
let
Body =
"{
""jsonrpc"": ""2.0"",
""method"": ""item.get"",
""params"": {
""output"": ""extend"",
""sortfield"": ""name"",
""webitems"": ""true"",
""search"": {
""name"": """&Valores&" for step \"""&Step&"\"" of scenario \"""&Scenario&"\"".""
}
},
""auth"": """ & token & """,
""id"": 1
}",
Source = Json.Document(
Web.Contents(
ZabbixURL,
[
Headers=[
#"Content-Type"="application/json"
],
Content = Text.ToBinary(Body)
]
)
),
result = Source[result],
#"Converted to Table" = Table.FromList(result, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
Value = #"Converted to Table" {0}[Column1],
itemid = Value[itemid],
var = if Valores = "Response code" then "3" else if Valores = "Download speed" then "0" else if Valores = "Response time" then "0" else "3",
Body_History =
"{
""jsonrpc"": ""2.0"",
""method"": ""history.get"",
""params"": {
""output"": ""extend"",
""history"": "&var&",
""itemids"": """&itemid&""",
""sortfield"": ""clock"",
""sortorder"": ""DESC""
},
""auth"": """ & token & """,
""id"": 1
}",
Source_History = Json.Document(
Web.Contents(
ZabbixURL,
[
Headers=[
#"Content-Type"="application/json"
],
Content = Text.ToBinary(Body_History)
]
)
),
result_History = Source_History[result],
Tabela_Lista = Table.FromList(result_History, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandRecordColumn(Tabela_Lista, "Column1", {"itemid", "clock", "value", "ns"}, {"itemid", "clock", "value", "ns"}),
#"Replaced Value" = Table.ReplaceValue( #"Expanded Column1",""&itemid&"",""&Valores&"",Replacer.ReplaceText,{"itemid"})
in
#"Replaced Value",
Tables = List.Transform(Lista, each GetItemID(_)),
paratabela = Table.FromList(Tables, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column2" = Table.ExpandTableColumn(paratabela, "Column1", {"itemid", "clock", "value", "ns"}, {"itemid", "clock", "value", "ns"}),
#"Pivoted Column" = Table.Pivot(#"Expanded Column2", List.Distinct(#"Expanded Column2"[itemid]), "itemid", "value"),
#"Changed Type" = Table.TransformColumnTypes( #"Pivoted Column",{{"clock", Int64.Type}}),
#"Added Custom" = Table.AddColumn(#"Changed Type", "Tempo", each #datetime(1970,1,1,0,0,0) + #duration(0,0,0,[clock]) - #duration(0,3,0,0)),
#"Changed Type1" = Table.TransformColumnTypes(#"Added Custom",{{"Tempo", type datetime}}),
#"Removed Columns" = Table.RemoveColumns(#"Changed Type1",{"clock", "ns"}),
#"Sorted Rows" = Table.Sort(#"Removed Columns",{{"Tempo", Order.Descending}}),
Colunas = Table.TransformColumnTypes(#"Sorted Rows",{{"Response time", type number}, {"Download speed", type number}, {"Response code", Int64.Type}})
in
Colunas
Note que ela é bem mais complicada que as chamadas anteriores pois automatiza muita coisa, e faz chamadas aos end-points de histórico de registros.
O retorno dessa função será nesse padrão.
Download do Pbix do projeto
Abaixo vou deixar o link com o PBIX desse projeto, com os parâmetros e funções criadas no Power Query caso queiram utilizar.
https://tadeumansi.com.br/Arquivos/ZabbixPowerBI.pbix
Referências
https://community.powerbi.com/t5/Community-Blog/Connecting-Power-BI-Desktop-to-Zabbix/ba-p/1582972
https://www.spikefishsolutions.com/post/connecting-power-bi-desktop-to-zabbix