Join us for an expert-led overview of the tools and concepts you'll need to pass exam PL-300. The first session starts on June 11th. See you there!
Get registeredPower BI is turning 10! Let’s celebrate together with dataviz contests, interactive sessions, and giveaways. Register now.
Hola a todos,
Dado que me llevó mucho tiempo resolver mi problema y finalmente lo logré con esta comunidad, no quería ocultarles la solución y mostrarles cómo logré obtener datos en Power BI a través de la API de Jira Rest. Espero que ayude a muchos otros que tienen el mismo problema y sienten que están buscando en toda la web y no pueden encontrar una solución adecuada, como yo. Sobre la situación inicial. Quería obtener datos de Jira de mi empresa en Power BI a través de la API de Rest. Esto me planteó varios desafíos:
El mayor problema resultó ser el mensaje de error constante de un origen de datos dinámico en Power BI Services. Para solucionar esto utilizo los comandos Web.Contents, RelativePath y Query. Estos artículos me han ayudado mucho como base para entender:
https://blog.crossjoin.co.uk/2016/08/16/using-the-relativepath-and-query-options-with-web-contents-i...
https://blog.crossjoin.co.uk/2016/08/23/web-contents-m-functions-and-dataset-refresh-errors-in-power...
Para obtener el token de API de Jira, sigue este artículo:
https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/
A pesar de los blogs que encontré en Internet, una autorización básica no funcionó para mí. Utilicé el tipo de autorización del portador con mi token de API sin modificar.
Para obtener solo los datos de mi filtro personalizado de Jira, el ID del filtro era importante. Puedes averiguarlo en la url de Jira cuando llames al filtro.
En pocas palabras, aquí está la consulta final que funcionó bien para mí y resolvió todos mis desafíos. He tratado de explicar los pasos individuales en los comentarios:
let
BaseUrl =
Web.Contents(
"https://XXX.XXX.net/jira/rest/api",
[
RelativePath="2/search",
Query=
[
jql="filter=525545",
fields="issuetype,key,summary,customfield_10401,labels,customfield_10000,status,resolution,customfield_11200"
],
Headers=[Authorization="Bearer **Your Token here**"]]
) ,
// JiraIDPerPage: Number of Jira tickets per page.
JiraIDPerPage = 1000,
// GetJson: Function to retrieve data from the Jira API and return it as JSON.
GetJson = (Url) =>
let
RawData = Web.Contents(
"https://XXX.XXX.net/jira/rest/api",
[
RelativePath="2/search",
Query=
[
jql="filter=525545",
fields="issuetype,key,summary,customfield_10401,labels,customfield_10000,status,resolution,customfield_11200"
],
Headers=[Authorization="Bearer **Your Token here**"]]
) ,
Json = Json.Document(RawData)
in Json,
// GetJiraIDCount: Function to determine the total number of available Jira tickets for a filter ID.
GetJiraIDCount = () =>
let Url = Web.Contents(
"https://XXX.XXX.net/jira/rest/api",
[
RelativePath="2/search",
Query=
[
jql="filter=525545",
fields="issuetype,key,summary,customfield_10401,labels,customfield_10000,status,resolution,customfield_11200"
],
Headers=[Authorization="Bearer **Your Token here**"]]
) ,
Json = GetJson(Url),
Count = Json[#"total"]
in Count,
//GetPage function: Retrieves a page of Jira tickets based on the specified index.
// - Index: The page number, starting at 0.
// - Skip: Skips a certain number of Jira tickets based on the page number.
// - Top: Specifies the maximum number of tickets to return per page.
// - Url: The full URL for the API request based on BaseUrl, Skip and Top.
// - Json: Retrieves data from the Jira API and returns it as JSON.
// - Value: Extracts the relevant information (under 'issues') from the JSON.
GetPage = (Index) =>
let
Skip = Text.From(Index * JiraIDPerPage),
Top = Text.From(JiraIDPerPage),
PageData = Web.Contents(
"https://XXX.XXX.net/jira/rest/api",
[
RelativePath="2/search",
Query=
[
jql="filter=525545",
startAt=Skip,
maxResults=Top,
fields="issuetype,key,summary,customfield_10401,labels,customfield_10000,status,resolution,customfield_11200"
],
Headers=[Authorization="Bearer **Your Token here**"]
]
),
Json = Json.Document(PageData),
Value = Json[#"issues"]
in Value,
// JiraIDCount: Calculates the total number of Jira tickets and selects the maximum number per page.
JiraIDCount = List.Max({ JiraIDPerPage, GetJiraIDCount() }),
// PageCount: Calculates the total number of pages based on the number of tickets per page.
PageCount = Number.RoundUp(JiraIDCount / JiraIDPerPage),
// PageIndices: List of page indices.
PageIndices = { 0 .. PageCount - 1 },
// Pages: Retrieves the corresponding page of Jira tickets for each page index.
Pages = List.Transform(PageIndices, each GetPage(_)),
// JiraID: Combines the pages into a complete list of Jira tickets.
JiraID = List.Union(Pages),
// Table: Creates a Power Query table from the list of Jira tickets.
Table = Table.FromList(JiraID, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
//From here data transformation
....
¡Espero que este post te ayude!
Alina
Hola Alina, intenté usar tu código y recibo el error Token Identifier esperado. ¿Es porque no agregué ninguna transformación de datos debajo del código que proporcionó?
¡Hola!
La integración de Jira y Power BI puede ser un desafío, pero afortunadamente, puede usar dos métodos principales para lograrlo. Una opción es la API REST de Jira, que requiere habilidades técnicas y puede ser compleja. La segunda opción es Conector de Power BI para Jira.
Es una aplicación fácil de usar que permite exportar datos de Jira a Power BI sin necesidad de conocimientos de codificación. Obtenga más información sobre el segundo método aquí:
https://marketplace.atlassian.com/apps/1221150/power-bi-connector-for-jira?hosting=cloud&tab=overvie... está disponible para Jira Cloud / Server / Data Center.
Dar
Hola Alina,
Gracias por el código que proporcionaste.
Desafortunadamente, la consulta devuelve solo 100 filas.
¿Sabrías la razón?
Gracias
Tuve el mismo problema, pero pude resolverlo configurando JiraIDPerPage en 100 (no en 1000).
Hola @Alina12,
Gracias por compartir, creo que este código de muestra ayudará a otros que tengan el requisito similar.
Saludos
Xiaoxin Sheng