ClearPeople logo

Sending MongoDB Atlas WebHooks notifications to Microsoft Teams

16 January 2020
  

Do you want to integrate MongoDB Atlas notifications into Microsoft Teams? Here we show you how.

 

Let's say you have your MongoDB databases on MongoDB Atlas (Ideally hosted on Microsoft Azure, but that's not important now).

Let's also say you are using Microsoft Teams and you are trying to use it for as many scenarios as possible.

 

My initial approach would be checking if MongoDB comes with a connector for Teams to integrate it seamlessly. As per today, I can let you know this feature doesn't exist (they already have a feature request for it).

 

My second approach would be, using MongoDb's webhooks integrations to send the notifications to Teams, but no, it doesn't work either. This functionality is sending a custom payload which Teams doesn't understand.

 

As there is no OOTB solution, I'm proposing is simple one: Let's build a gateway to transform that custom payload into a Message Card that Teams can understand. The process will be:

  1. MongoDb sends the notification via webhook integration to our gateway.
  2. Our gateway will read the custom payload and transform it into a Message card object.
  3. Our gateway will post the new Message Card to our Teams' Webhook.
  4. Teams will display the notification on our channel.


Let's get started!

 

Setting up a custom incoming webhook in Microsoft Teams

This step enables your channel for receiving external messages.

  • In Microsoft Teams, choose More options (⋯) next to the channel name and then choose Connectors.
  • Scroll through the list of Connectors to Incoming Webhook, and choose Add.
  • Enter a name for the webhook, upload an image to associate with data from the webhook, and choose "Create".
  • Copy the webhook to the clipboard and save it. You'll need the webhook URL for sending information to Microsoft Teams.
  • Choose Done.

Creating the gateway between MongoDB and Microsoft Teams

We are going to use an Azure Function to do the job. There is plenty of documentation about creating Azure functions out there. I'll give you some links to the official documentation:

  • Create a function app from the Azure portal. This will give you an Internet-facing endpoint accessible for MongoDB. It will also give you the capabilities to implement our transformation and call back to Microsoft Teams. Also, creating a consumption base app service plan when following the guide, should result in an almost free service, considering the number of free resources provided by Azure and the expected limited number of alerts triggered from MongoDB.
  • Create an HTTP triggered function. With this step, you'll have an actual URL to be used by MongoDB and a method in a class to implement our logic. Copy the function URL as described in the "Test the function step", as we'll need it later.
  • Replace the code of the function, by the one provided by the following Github Gist (YOu can find it also at the bottom of the page)
  • Type the URL generated with Teams, to the variable "uri" (line 26). With these steps we are telling the function app where must it call to send us our notifications.

Configuring MongoDB Atlas to send the notifications to the gateway (our function app on Azure)

  • Login into your project and go to Integrations (Left-hand column)
  • From the list of possible integrations, choose Webhook Settings and click "Configure".
  • On the pop-up, paste the URL of the function app you saved on the previous step. The URL already contains the secret, so leave the "Webhook Secret" field empty.


Now MongoDB is able to communicate with our function app, but by default all the alerts are configured to send them by email only. So let's change it.

 

  • Under your project, go to "Alerts", and here click on the tab "Alert settings".
  • For each alert, click on the 3 dots on the right and click "Edit".
  • At the bottom, there is an "Add" dropdown. Click on it and choose "Webhook".This step will add the previously configured webhook to the list of targets to send the notification to.
  • You can remove the previously default target "email" if you don't want to receive the notifications by email.

And that's it, now MongoDB will call your Azure function whenever an alert is triggered, this function will get the data sent by MongoDB, and push it to your Microsoft teams channel to get a message like the image below:

 

Of course, this is a "quick and dirty" example to give you a PoC.

 

Mongo atlas notification in Microsoft Teams
NOTIFICATION PUBLISHED IN TEAMS BY MONGODB
  #r "Newtonsoft.Json"
   
  using System.Net;
  using Microsoft.AspNetCore.Mvc;
  using Microsoft.Extensions.Primitives;
  using Newtonsoft.Json;
  using System.Net.Http.Headers;
   
  public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
  {
  log.LogInformation("C# HTTP trigger function processed a request.");
   
  string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
  ActionResult result;
  if(!string.IsNullOrEmpty(requestBody))
  {
  dynamic data = JsonConvert.DeserializeObject(requestBody);
  log.LogInformation(requestBody);
  //Push message through Teams
  using (var client = new HttpClient())
  {
  client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
  client.DefaultRequestHeaders.Add("User-Agent", "AzureFunctions");
   
  //Copy paste uri from Teams
  var uri = "https://outlook.office.com/webhook/XXXXX/IncomingWebhook/YYYY/ZZZZ";
   
  String content = @"{
  ""@type"": ""MessageCard"",
  ""@context"": ""https://schema.org/extensions"",
  ""summary"": ""Card \""Test card\"""",
  ""themeColor"": ""0078D7"",
  ""title"": ""--title--"",
  ""sections"": [
  {
  ""activityTitle"": ""--stitle--"",
  ""activitySubtitle"": ""--date--"",
  ""activityImage"": ""--icon--"",
  ""facts"": [
  {
  ""name"": ""Custer:"",
  ""value"": ""--clustername--""
  },
  {
  ""name"": ""Replica set:"",
  ""value"": ""--repset--""
  },
  {
  ""name"": ""Server:"",
  ""value"": ""--handp--""
  },
  {
  ""name"": ""Metric:"",
  ""value"": ""--stitle--""
  },
  {
  ""name"": ""Metric value:"",
  ""value"": ""--value--""
  },
  {
  ""name"": ""Type:"",
  ""value"": ""--type--""
  },
  {
  ""name"": ""Event:"",
  ""value"": ""--event--""
  }
   
  ],
  ""text"": ""--MESSAGE--""
  }
  ],
  ""potentialAction"": [
  {
  ""@type"": ""OpenUri"",
  ""name"": ""Check the stats"",
  ""targets"": [
  {
  ""os"": ""default"",
  ""uri"": ""--url--"",
  ""url"": ""--url--""
  }
  ]
  }
  ]
  }";
   
  if(data!= null)
  {
  string value = data.metricName;
  if(!string.IsNullOrEmpty(value))
  content = content.Replace(@"--stitle--",value);
   
  value = data.updated;
  if(!string.IsNullOrEmpty(value))
  content = content.Replace(@"--date--",value);
   
  value = data.humanReadable;
  if(!string.IsNullOrEmpty(value))
  content = content.Replace(@"--MESSAGE--",value);
   
  value = data.replicaSetName;
  if(!string.IsNullOrEmpty(value))
  content = content.Replace(@"--repset--",value);
   
  value = data.hostnameAndPort;
  if(!string.IsNullOrEmpty(value))
  content = content.Replace(@"--handp--",value);
   
  value = data.clusterName;
  if(!string.IsNullOrEmpty(value))
  content = content.Replace(@"--clustername--",value);
   
  value = data.status;
  if(!string.IsNullOrEmpty(value))
  {
  content = content.Replace(@"--status--",value);
  if(value =="OPEN")
  {
  content = content.Replace(@"--icon--","https://www.clearpeople.com/-/media/Images/TeamsIntegrations/notification%20png.png");
  content = content.Replace(@"--title--","New alert triggered");
  }
  else if(value =="CLOSED")
  {
  content = content.Replace(@"--icon--","https://www.clearpeople.com/-/media/Images/TeamsIntegrations/correct%20jpg.jpg");
  content = content.Replace(@"--title--","Alert closed");
  }
  }
   
  value = data.typeName;
  if(!string.IsNullOrEmpty(value))
  content = content.Replace(@"--type--",value);
   
  value = data.eventTypeName;
  if(!string.IsNullOrEmpty(value))
  content = content.Replace(@"--event--",value);
   
   
  if(data.currentValue!=null)
  {
  value = data.currentValue.number;
  content = content.Replace(@"--value--",value);
  }
  if(data.links!= null && data.links[0]!= null)
  {
  value = data.links[0].href;
  content = content.Replace(@"--url--",value );
  }
  }
   
   
  StringContent TeamMsg = new StringContent(content);
  log.LogInformation(content);
  HttpResponseMessage response = client.PostAsync(uri,TeamMsg).Result;
  var responseString = response.Content.ReadAsStringAsync().Result;
  log.LogInformation(responseString);
  }
  result = new OkObjectResult($"Hello");
  }
  else
  {
  result = new BadRequestObjectResult("Please pass some JSON in the request body");
  }
  return result;
  }
view rawvicent@galysoft.es hosted with ❤ by GitHub

Author bio

ClearPeople

ClearPeople

Sign up to our ClearThought newsletter

Get inspired and learn something new by subscribing to our FREE newsletter. It’s full of ClearPeople's thought-leadership whitepapers, blogs, events, and much more. We promise to not use your email for spam.