The Experts Conference (TEC) takes place virtually on September 1-2, 2021. It’s a free event dedicated to sharing practical information about running Microsoft cloud and on-premises services. We’ve asked each of the TEC speakers to write about a topic close to what they’ll be speaking about during this conference. This is the first article in the series. Join us at TEC to hear even more valuable information!
Public Preview of New Graph API Available
As noted in June, Microsoft is moving the focus for Azure AD to the Microsoft Graph API away from the Azure AD Graph API. This is an example of consolidating older first-generation REST APIs built for Microsoft Cloud Services into the Microsoft Graph. Another example is the transition of the Office 365 Service Communications API to the Graph (MC257688, updated June 24). A beta version of the Graph-based API for Service Communications is now available in public preview (Microsoft 365 Roadmap item 67820). Eventually, the Graph-based API will take over from the earlier version and tenants will have to upgrade scripts and other tools constructed using the older API.
Update August 4: In MC275573. Microsoft moved the Graph-based Service Communications API to Generally Available status and announced their intention to retire the older API from December 17, 2021.
What the Service Communications API Does
The Office 365 Service Communications API gives access to data such as:
- Service health information – the kind of data you see in the tenant Service Health Dashboard (SHD).
- Service incidents – details of an incident (outage) for a service like Exchange Online, SharePoint Online, or Teams. When an incident finishes, the API can also fetch the post-incident report (PIR).
- Service update messages – the message center posts which appear in the Microsoft 365 admin center to advise tenants about new, updated, or deprecated features.
An example of using PowerShell and the older Service Communications API to retrieve details of service incidents is described in this post. I set out to create a Graph-based version of the script and here are my notes.
Upgrading to the Graph
First, I created a new registered application in Azure AD and an app secret for the app.
Graph apps need permissions to access data. In this case, the necessary permissions are:
- ServiceMessage.Read.All: Access information about service updates.
- ServiceHealth.Read.All: Access information about service incidents.
After assigning the permission(s) to the app and granting administrative consent, we can move to the code.
The code to acquire an access token is different because the endpoint changes from https://manage.office.com to the endpoint used for all Graph APIs (https://graph.microsoft.com/.default). If you have other scripts which interact with Graph APIs like those for users and groups, you can use the same code to get an access token.
Querying the Graph
The older API has a generic message object. Things are more specific with the Graph and you can retrieve three different collections of service information: messages, issues, and service health overviews. In this instance, I want to discover information about current service issues.
Incidents tend to be short lived. You can fetch all available incidents if you want or restrict the information returned by the Graph by using filters. Just for interest, I went back 180 days in my tenant and found that 270 incidents were available. I sorted the data to see what features caused most incidents and found the following were the top 10:
$Issues | Group FeatureGroup | Sort Count -Descending | Format-Table name, count Name Count ---- ----- Teams Components 61 Portal 39 Microsoft Intune 31 Administration 25 E-Mail and calendar access 18 SharePoint Features 16 Management and Provisioning 15 Yammer Components 8 OneDrive for Business 7 E-Mail timely delivery 7
Of course, this data needs to be probed to fully understand its meaning. Because Microsoft tailors the incident data available to a tenant, your mileage may vary and Teams might not show up as responsible for 22.6% of all incidents logged in the last 180 days.
Processing Information Retrieved from the Graph
Returning to a more focused view, the code below creates a URI to fetch service issues over the last seven days. Including a Z at the end of the date (in PowerShell sortable format) is important because the Graph insists on terminating a sortable date with Z. At least, any attempt to use a simple date fails.
# Get Service incidents - the filter clause sets the number of days to look back $DaysRange = (Get-Date).AddDays(-7) $DaysRangeZ = Get-Date($DaysRange) -format s $Uri = "https://graph.microsoft.com/beta/admin/serviceAnnouncement/issues?`$filter=startDateTime ge $DaysRangeZ" + "Z"
To retrieve the data, call the Invoke-RestMethod cmdlet to return the results in an array:
[array]$Issues = Invoke-RestMethod -Headers $Headers -Uri $Uri -UseBasicParsing -Method "GET" -ContentType "application/json"
By default, the Graph uses pagination to return data. In the case of the Service Information API, it returns 100 objects at a time, so if you want to fetch all possible data, you must check if an Odata.Nextlink is available to tell the Graph where the next page of data is waiting (here’s an example of using the Nextlink to fetch large quantities of Teams objects).
After everything is fetched, the useful data is in the Values property for each object, so you can extract the information to make it easier to work with by doing:
$Issues = $Issues.Value
To make things easier, I use a function to execute Graph queries, handle pagination, and return cleaned up results. You can see an example of the function in the Teams and Groups activity report script available in GitHub.
Interpreting Results
Queries for service issues return information incidents in different states:
- serviceRestored: The incident is over, and service is now at normal levels.
- serviceDegradation: The incident is current and is affecting the quality of service delivered to end users.
- postIncidentReviewPublished: A post incident report is published and available for administrators to download. This is the root cause analysis of the problem which caused an incident.
- investigationSuspended: Microsoft is waiting for further information to proceed).
- falsePositive: A reported incident turned out to be a false positive.
You can filter the objects in the returned array to extract the incidents you’re interested in or ask the Graph to return just objects of a certain type. For example, to have the Graph return information about currently unresolved problems (isResolved is False and status is serviceDegradation), we use:
$Uri = "https://graph.microsoft.com/beta/admin/serviceAnnouncement/issues?`$filter=startDateTime ge $DaysRangeZ" + "Z and IsResolved eq false and status eq 'serviceDegradation'"
An object for an incident in the array returned by the Graph looks like this:
startDateTime : 2021-06-30T00:00:00Z endDateTime : lastModifiedDateTime : 2021-07-05T06:01:51.013Z title : Admins may see Microsoft 365 app usage and productivity score reports data delayed after June 30, 2021 id : MO266326 impactDescription : Admins may see Microsoft 365 app usage and productivity score reports data delayed after June 30, 2021. classification : advisory origin : microsoft status : serviceDegradation service : Microsoft 365 suite feature : Company or User Administration featureGroup : Administration isResolved : False highImpact : details : {} posts : {@{createdDateTime=2021-07-02T05:54:00.587Z; postType=regular; description=},@{createdDateTime=2021-07-03T06:03:25.05Z; postType=regular; description=}, @{createdDateTime=2021-07-04T05:52:23.413Z; postType=regular; description=}, @{createdDateTime=2021-07-05T05:47:56.107Z; postType=regular; description=}}
Displaying Results
The information about an issue retrieved from the Graph is exactly what is shown in the Microsoft 365 SHD (Figure 2). Everything is available to format and report details as you would like.
For instance, the Posts property holds the set of updates issued by Microsoft about the incident shown under All updates in the SHD. Four updates are available for this incident. To see the latest details, we can use code like this:
$LastPostIndex = $Issue.Posts.Count -1 $PostInfo = $Issue.Posts[$LastPostIndex].Description.Content $PostDate = Get-Date ($Issue.Posts[$LastPostIndex].CreatedDateTime) -format g Write-Host (“Incident date: {0}: {1}” -f $PostDate, $PostInfo) Incident date: 05/07/2021 06:47: Title: Admins may see Microsoft 365 app usage and productivity score reports data delayed after June 30, 2021 User Impact: Admins may see Microsoft 365 app usage and productivity score reports data delayed after June 30, 2021. Current status: We've determined that the reports are still delayed. We're continuing our efforts to replay the delayed reporting data which we anticipate will mitigate impact. Scope of impact: This issue may affect any admin attempting to view Microsoft 365 app usage and productivity score reports after June 30, 2021. Start time: Wednesday, June 30, 2021, at 12:00 AM UTC Root cause: A recent service update introduced a code regression in a service component responsible for tracking user activity throughout multiple Microsoft 365 apps, resulting in impact. Next update by: Wednesday, July 7, 2021, at 7:00 AM UTC
Obviously, you can choose to present incident information in whatever way you choose. It’s only a matter of coding.
Summarizing the Conversion
Conversion from the older Office 365 Service Communications API to the Graph-based version isn’t difficult. If you’re used to working with the Graph APIs, you’ll find it second nature to get an access code, fetch information, apply filters, and interpret the data. The advantage of the Graph is that the same approach is used for different kinds of data, and that’s exactly what’s seen here. Happy coding!
Hello Everyone,
Can someone help me with GraphAPI ps1 script?
Thanks in advance!
Hello Tony,
I am using Graph API to extract the incidents (advisory and incidents) using a power flow.
But I have an issue with https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/issues because is extracting only some old incidents and the new ones are not present in my output.
Do you have an idea why is not getting all the incidents?
I obviously don’t have access to your code and can’t say what might be going on. What do you see in the Graph Explorer? I pasted the link into it and see recent advisories (example shown below).
{
“createdDateTime”: “2022-02-23T18:59:36.417Z”,
“postType”: “regular”,
“description”: {
“contentType”: “html”,
“content”: “Title: Admins may be unable to use the \”Get-EXOMailbox\” PowerShell cmdlet in tenants hosted across multiple geo-locationsUser Impact: Admins may be unable to use \”Get-EXOMailbox\” in tenants that are hosted across multiple geo-locations.Current status: Our deployment to the affected infrastructure is ongoing and is expected to take some time to complete. We anticipate completion of the fix deployment by our next update on Wednesday, March 2, 2022.Scope of impact: This issue may impact any admin attempting to use the Get-EXOMailbox cmdlet in tenants hosted across multiple geo-locations.Estimated time to resolve: We anticipate completion of the fix deployment by our next update on Wednesday, March 2, 2022.Root cause: ACLs on database copy objects are mismatched, leading to validation failing and ADLookup not completing.Next update by: Wednesday, March 2, 2022, at 8:30 PM UTC”
}
}
]
Hi Tony,
I am expeirencing the same issue. I am using graph explorer. I only see the old message and not the new ones.
Below is my query
https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/messages
I thought I would be a paging issue hence I used the below query and still no new message
https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/messages?`$top=100
To my surprise when I search with the message ID it shows the new message
https://graph.microsoft.com/v1.0/admin/serviceAnnouncement/messages/MC408531
Could you please guide me what am I doing wrong here and why can’t I see the new messages?
Regards,
Ashish Jaiswal
I suspect you have a permissions issue. I tried the queries and the first two worked like a charm. The last didn’t because MC408531 doesn’t exist in my tenant.
I have the exact same permission as you mentioned in this article, Please advise if more permissions are required? I am unable to share screen capture to you via this message.
Also, this spam protection on your page/article is horrendous this is 105th time I am trying to add my reply
SPAM Message
SPAM ID
Duplicate Message
Try after sometime
Not happy being a genuine guy to ask a question
When in doubt, always consult the documentation: https://docs.microsoft.com/en-us/office/office-365-management-api/get-started-with-office-365-management-apis
This says that ServiceHealth.Read and User.Read is necessary. I use ServiceHealth.Read.All and ServiceMessage.Read.All (I just checked the Azure AD app). I forget why I selected these permissions, but it might have been through trial and error. It’s over a year since I wrote this article.
Make sure that they are application permissions, not delegated permissions.
As to spam, the site is plagued by a large amount of incoming spam that insists that people want to read about various pills and other body enhancements. No one wants to see that kind of crap.
Hi Tony
I tried out your code in my tenant and always get an error:
It is not possible to apply an index to a NULL array.
In line: 35 characters: 1
+ $ PostInfo = $ Issues.Posts [$ LastPostIndex] .Description.Content
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~
+ CategoryInfo: InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId: NullArray
Next problem I have is to post the data to a teams channel like Einar Asting did http://thingsinthe.cloud/Teams-message-cards-Office-365-Health-status/
I am relativ new to O365 and powershell and it makes me a great headache.
I subscribed Office 365 for IT Pros and it is very helpful. But it is a long learning path for me.
Thanks for your great blog.
Greetings from Germany.
Kindly regards
Frank
Hi Frank,
The error means that you don’t have any data in the array ($Issues) you’re trying to use. Maybe the parameters you used for the Graph API call aren’t correct?