1

Goal:

My goal is to take data from a Sumologic dashboard using the Sumologic API and display it within a dashboard in Power BI. I am checking the calls first within Git Bash, before entering the URLs into Power BI Desktop to visualize the data.

  • I have an Access ID - Looks like: h2348f9

  • and Access Key - Looks like: 23h9qwdjqqq9qqi39d3ef9f94kks9k94k

  • This is the url I am trying to use to access the Dashboard: https://api.sumologic.com/api/v2/dashboards/{dashboard id goes here} According to Sumologic Get Dashboard Documentation

  • I have what I believe is the Dash ID

I acquired the dash ID from the end of the URL in my Sumologic UI.

I have successfully accessed data through the API for https://api.sumologic.com/api/v1/collectors?limit=10 using the PBI Desktop UI "Basic" Authentication setting, by substituting the access ID for username and the Access key for password.

(As instructed by the Power BI Documentation on APIs see first few steps. It works, even though this states it is for Azure not SumoLogic)

Problem:

But when I curl the command in my Git Bash for GET dashboard,

curl -u "(AccessID):(AccessKey)" -X GET "https://api.sumologic.com/api/v2/dashboards/(dashboardID)"

I get this json response:

{
    "id":"10NLC-3CNIS-5QN8J",
    "errors":[
        {"code":"user:not_found",
         "message":"Object Not Found."}
    ]
 }

I also am unable to add this call into Power BI, likely because of the same error. I was able to add the first URL https://api.sumologic.com/api/v1/collectors?limit=10 without any extra user info given.

This Error seems to confirm that the ID is correct, (as I used to get an "Incorrect ID" error instead of a json response before), but I'm not sure. How can I resolve this user-not-found error?

Micah
  • 479
  • 1
  • 7
  • 17

2 Answers2

1

TLDR

The /api/v2/dashboards/:dashboardId endpoint expects the same (kind of) dashboard ID as you can see in the user interface when looking at the dashboard

Long answer

If I have this:

opening the dashboard in Sumo Logic UI

then subsequently I can:

curl -u "$USER:$PASSWORD" -X GET "https://api.sumologic.com/api/v2/dashboards/PzClm5SSgWJqFSAusVkhPE5yMRU7NIrGZj6X0M28wMSgsnvmAc98cdvLiDwD"

and receive a meaningful answer:

{"title":"Dashboard Sep 27, 2021 06:53:55","description":"","folderId":"0000000000D87ECD","topologyLabelMap":{"data":{}},"domain":"",
...

Disclaimer

I am currently employed by Sumo Logic

Grzegorz Oledzki
  • 23,614
  • 16
  • 68
  • 106
  • Thank you! Really appreciate your response. This helped me know my Dash ID. But this didn't solve my user not found error. – Micah Sep 27 '21 at 15:11
  • I'm exploring a bunch of different ways to connect Dynatrace into Power BI. This method of using the API hasn't proved to be the most useful. Have you had any experience with that integration, any tips? – Micah Sep 27 '21 at 15:24
  • Hello @Grzegorz, my account has been put on restriction of asking question because they haven't been useful or positive to the community. I think I have too many errors my questions or not enough of them have solutions. Anyways I have tried curl -u "$USER:$PASS" -X GET "https://api.sumologic.com/api/v2/dashboards/on5gsvCBXci1ehmY8BybBEqSTIxJEAMglSPxbiHh2xvK9IycyhB4mmN1R3Aq" and still get back HTTP ERROR 401 User could not be found. Any Ideas on how I can fix this? I'd like to be able to ask questions again. – Micah Nov 04 '21 at 18:09
0

The best way to integrate Sumologic into Power BI is to use python scripts that do this curl to get the info needed from Sumologic's SearchJob API.

Step 1: Make Python Script Replace

  • the URL with your sourceName
  • From and to times
  • query with your query
#   IMPORTS
import requests
import json
import base64
import time
import pandas as pd
import pytz
# from async import asyncio
from datetime import datetime, timedelta, date

now = datetime.now()
current_time = now.strftime("%Y-%m-%dT%H:%M:%S")

#   VARIABLES
dt = []   # DATA TARGET - List of Data values (Index, Timestamp, Message/Query, Count)
queryList = []   # LIST of Queries
index = 0   # DATA TARGET COUNT - INDEX NumberqueryList = []
n = 1   # SET minutes - n = number of Minutes/Hours 5 min AGO TIME - the "from" value  for Query:
messageCount = 0

#   Subtract Desired time n  from datetime object containing current time
five_min_ago = now - timedelta(minutes=n)   # Change time unit here if desired
past_time = five_min_ago.strftime("%Y-%m-%dT%H:%M:%S")

print("CURRENT TIME: ", current_time, " PAST TIME: ", past_time)

def makeCall(queryString):   #   F U N C T I O N   
    #   CREDENTIALS: 
    global messageCount
    usrPass = "******"
    encoded_u = base64.b64encode(usrPass.encode()).decode()
    url = "https://api.sumologic.com/api/v1/search/jobs"
    
    fullQuery = '_sourceCategory=prod/../* _sourceName=/apps/apps/logs/../trace.log ' + queryString + " | count" # Form Query with Common Query Parts
    print(fullQuery)
    headers = {
        'Content-Type': 'application/json',
        'Authorization': 'Basic '+encoded_u,
        'Cookie': '****'
        }
    payload = json.dumps({
        "query": fullQuery, 
        "from": past_time, #   Format: 2021-10-06T11:40:05 -Minute ago
        "to": current_time, 
        "timeZone": "EST",
        "byReceiptTime": True
    })  

    #   MAKE REQUEST AND GET RESPONSE - (CALL #1):  -------------------------------------------------------------------------------------------------------
    response = requests.request("POST", url, headers=headers, data=payload)
    print("RESPONSE: ", response.text)

    #   CONTENT EXTRACTION:
    jobId = json.loads(response.text).get("id") # Convert Response (text) to json
    queryUrl = url + "/" + jobId # Make URL Query

    #   SPECIFIC SEARCH JOB CALL - (CALL #2): ---------------------------------------------------------------------------------------------------------------
    response = requests.request("GET", queryUrl, headers=headers, data=payload)
    state = json.loads(response.text).get("state")
    print(state)

    quitVal = False
    while quitVal == False :
        time.sleep(5) 
        resp = requests.request("GET", queryUrl, headers=headers, data=payload)
        state = json.loads(resp.text).get("state")
        print("...")
        if state == "DONE GATHERING RESULTS" :
            quitVal = True
            print(state)
            messageCount = json.loads(resp.text).get("messageCount")
            print(messageCount)
            

    #   GET DATA CALL - (CALL #3): ---------------------------------------------------------------------------------------------------------------------------

    #   Form Result URL:
    resultUrl = queryUrl + "/messages?offset=0&limit=10000"  #records?offset=0&limit=1
    results = requests.request("GET", resultUrl, headers=headers, data=payload)

    messages = json.loads(results.text).get("messages") # Access Data

    return messages

#                     End of   F U N C T I O N   

# QUERIES By CATEGORY ----------------------------------------

#    Query string you are searching for within the log:
Query1 = "... :Exception"


queryList.append(Query1)


print(queryList)   #   Print to Check  

# ------------------------------------------------------------

#   EXECUTE Calls on Each Query - SYNC. = SLOW
for query in queryList:   
    messages = makeCall(query)
    #print(messages)
    dt.append((index, past_time,current_time, query, messageCount))
    
    index = index + 1 #  Increment the Index of DT for next Query

#   CHECK dt:
for each in dt:
    print()
    print(each)

#   ADD data to DataFrame Format for Power BI:
df = pd.DataFrame(dt, columns=('Index', 'FromTime','ToTime', 'Message', 'Messagecount'))    
print(df)
 

Step 2: Add the Python into Power BI . This just requires you to go to add data. Then select python script. Then copy and past your script into the text entry box. Should automatically calculate when you refresh your pbi dash.

Micah
  • 479
  • 1
  • 7
  • 17