Background

For the past year I have spent time working on a hybrid/ bimodal EDI solution to support ordering- and logistics processes for a customer in China. The technical building blocks are based on integration components in the Microsoft Cloud and we're using API Management (APIM) for three main purposes:

  • Provide access for customers and suppliers, i.e. make sure that they can receive the information they are entitled to
  • Provide information about how, where, when and by whom the EDI-services are being used
  • Provide tools and documentation for customers and suppliers to make it easier to set up a working B2B-relationship 

For the first two bulletpoints one of the key features in APIM are policies where you, as an administrator, can set rules based on different criterias. Common policies include the ability to define how users interact with the service, for instance how many calls you can make per day or where the calls can be made from. Policies can be defined on different levels and there is an order of execution, i.e. an hierarchy, that defines which policies are subject to your services.
However, instead of blogging about how policies are executed I will, in a series of articles, provide you with some of the policies that I use for tasks that aren't necessarily related to security.

Log message details with <log-to-eventhub>

For most scenarios you eventually find yourself in a situation where the built-in analytics features in APIM just isn't enough. For instance, you might need to help a customer troubleshoot why her sales orders aren't accepted or you want to build a dashboard for your sales representatives so that they can see the status of all ongoing orders.

The <log-to-eventhub> will solve most, if not all, logging scenarios I can come up with. The policy lets you log activities on all or certain services/ operations that you expose. It will then send data from APIM to an Azure Event Hub for further processing somewhere else. Azure Event Hubs is a separate component/ service in Azure that can handle millions of events per second. You can think of it as a message channel where APIM dumps its logmessages for consumers to pick up.

The case for this article is about being able to follow an orderflow from the moment where a purchase order has been created in the ERP-system to the actual delivery of the goods. The process itself includes numerous activities where some of them are dependant on information to/ from suppliers and customers. Where it's suitable I use a database to collect information and status of external activities. For instance, when a supplier receives a purchase order this will generate a new row in a table with date, time, vendorname, PO-number, status and so on. This information can later be used to pair with other activities in the business process to give you an idea of the overall status for that particular order.

From an APIM standpoint we can use the <log-to-eventhub> to create rows in the table when there's an interaction between our company and it's partners.
The following example demonstrates the policy of a service that accepts Delivery Messages from different suppliers.  


<set-variable name="message-id" value="@(Guid.NewGuid())" />
  
  <log-to-eventhub logger-id="monitor-dn-test">
            @{
              var body = context.Request.Body?.As(true);
              var xElem = XElement.Load(new StringReader(body));
                
                
              string DNNumber = (string)xElem.Descendants("DeliveryMessageNumber").First().Value;
                
              List pONumbers = new List();
                
              IEnumerable DeliveryMessageLineItems = xElem.Descendants("DeliveryMessageLineItem"); 
              foreach (XElement DeliveryMessageLineItem in DeliveryMessageLineItems)
              {
                   pONumbers.Add((string)DeliveryMessageLineItem.Descendants("DeliveryMessageReference").FirstOrDefault(el => el.Attribute("DeliveryMessageReferenceType") != null && el.Attribute("DeliveryMessageReferenceType").Value == "PurchaseOrderNumber"));
              }
                
              pONumbers.ToArray();
                
              return new JObject(
                      new JProperty("id",context.Variables["message-id"]),
                      new JProperty("dateTime",DateTime.UtcNow),
                      new JProperty("operation",context.Request.Method),
                      new JProperty("Path",context.Request.Url.Path + context.Request.Url.QueryString),
                      new JProperty("stage","Delivery Message Received"),
                      new JProperty("username",context.User.Email),
                      new JProperty("DNNumber",DNNumber),
                      new JProperty("pONumbers", new JArray(pONumbers))
                  ).ToString();
            }
                
</log-to-eventhub>

The policy has a logger-id, which is a name/ alias for the EventHub used within APIM, where your logs will be sent. For more information about creating EventHub-names in Azure check out this guide by Steve Danielson.

As a first step in the policy we assign the body of the message, i.e. the Delivery Message sent from a supplier, to a variable called body. As this document is standardized and happen to be a XML document we load and serialize it into a variable called xElem.
After extracting the Delivery Note number (which can only exist once in each Delivery Message) we assign it to the string DNNumber. We also want to keep track of the PO-number but since there can be many references to different Purchase Orders in each Delivery Message we create a list which we iterate through.
Once we have received all PO-numbers we convert the list into an array. The reason for using a list in first place is that I find it easier to work with when you haven't got a clue about how many PO-numbers you will have to iterate through.

After collecting data from the Delivery Message we are ready to ship it off to Azure EventHub. But before doing do so we need to decide on the format to send it in. The <log-to-eventhub> can only return strings so we're quite limited in our options there. However in our case we want to send the data into a database and for doing that we will use another Azure component called Stream Analytics. The thing about Stream Analytics is that it only accepts serialization in JSON-objects, CSV and Avro. For a number of reasons I don't even wanna try serializing my data into CSV. When it comes to Avro I had to Google just to find out what it was. And even though it's probably a fantastic choice for some people I'm just not there..  
So the way forward for me is to create a JSON-object with the data collected along with some other information that we want to pass on to the database. Before sending it off we then convert the JSON-object into a string. Please also note that we're creating a JArray of the PO-numbers which makes a typical message look something like this:

With this policy in place you will now start receiving messages in your EventHub each time someone uses your service. As mentioned above, this also requires you to have an EventHub-name in place. 

Processing logmessage details

So how about doing something useful with those logs? Another of my favourite tools in Azure is the Stream Analytics. Basically it is a high-performing engine for processing realtime data from various sources - such as EventHub. You typically create a query to the input data and let you send it to one or many destinations. For this sample I have created a simple job in Stream Analytics with one input (the EventHub that APIM sends logmessages to) and one output (the SQL database).

The query I use is quite straighforward with one exception; the CROSS APPLY statement. As described above we put all the different PO-numbers in an JSON array. So we need to find a way to straighten/ flatten this data and let each item in the array (each PO-number) create a separate output from Stream Analytics. This is where CROSS APPLY comes into play and helps us out. For more information about working with complex data types check this article out. 

SELECT
dnEvent.Stage AS Stage, po.ArrayValue AS 'PO-Number',
dnEvent.datetime AS 'EA-DateTime', dnEvent.DNNumber AS 'DN-number'

INTO
[SQLTest-SafeToRemove]

FROM
[EventHub-mp-edi-monitor-dn-test] as dnEvent

CROSS APPLY GetElements(dnEvent.pONumbers) as po

Now all we have to do is to sit back and watch our database get populated with new rows each time someone drops you a Delivery Message. What you probably end up with eventually is a database where you collect similar, but not identical information, from all of the services involved in your business process. So you might want to give it some thought in regards to how you will pair these various messages with it's different status'.
In my experience it will save you time (and money) to focus on the business process, the user experience and the database design before you start with the policies. I would also recommend you to create different Stream Analytics jobs for each logmessage type even though they may seem almost identical at first because if there's anything we can be certain of is that it will most likely change in the future.

Läs hela inlägget »

Syfte

Integrationer handlar månt och mycket om att förstå och svara upp mot informationsbehov i olika processer. Att visuellt åskådliggöra detta gentemot olika målgrupper under ett förvaltningsobjekts livscykel är dock en utmaning och kräver att man ser helheten samtidigt som man kan diskutera detaljer.
Idén till modellen kan kopplas till behovet av att visualisera de process <-> information och system <-> informationsmatriser.
Styrkan med modellen är främst dess enkelhet

Användningsområde

Främsta användningsområdet är att få olika intressenter inom verksamhet och IT att kommunicera kring en gemensam bild och med den som utgångspunkt:

  • Ha en övergripande bild över integrationsarbetet och hur de olika delarna ”hänger ihop”. Framförallt viktigt i ett startskede när man behöver skapa sig en gemensam bild och kommunicera med sin omgivning. Allt eftersom bilden växer fram och blir mer detaljerad så får den betydelse i utvecklings-, test- och förvaltningsarbetet.
  • Göra gemensamma prioriteringar och förstå/ resonera kring konsekvenser ur ett process, system och informationsperspektiv.
  • Relatera till annan, mer detaljerad, dokumentation så som lösningsdesign och mappningar.

Stegbeskrivning

Steg 1 - Processer och information

I de fall man har tillgång till system-information och process-informationsmatriser så är dessa en bra utgångspunkt. Meddelandeflödesbeskrivningen, liksom matrisen, bygger på att ta visa vilka processer och funktioner som skapar/ läser vilken information. Utifrån Process-informationsmatrisen använder man Visio och bifogade mallar för att rita processen och dess informationsbehov.
Eftersom det än så länge är sällsynt att arbeta med IRMs matriser så går det också bra att kartlägga processerna och dess informationsbehov på egen hand och genom dialog, kunskapen finns ju ofta lättillgänglig 

TIPS

  • Lägg inte tid på processernas storlek eller informationsbehovens exakta placering – dessa kommer du att behöva justera senare.
  • Visualisera även de processer/ funktioner som inte har direkt påverkan på meddelandeflödet.
  • Använd beskrivande namn på informationsbehovet. Ibland kan det vara nödvändigt/lämpligt att utifrån ett informationsobjekt skapa flera informationslinjer (ex vis ”skapad order” och ”stängd order” för det gemensamma objektet Order.

Steg 2 - System och integration

Använd system-informationsmatrisen för att placera in system och integrationspilar i Visiomallen för att visa på vilket meddelandeflöde som behövs för att svara upp mot respektive informationsbehov.
Meddelandeflödesbeskrivningen, liksom matrisen, bygger på att ta visa var data skapas/ändras och vilka system som är i behov av att läsa detta data.
I de fall matriser saknas så beskriv databehovet efter bästa förmåga, det är ju tämligen enkelt att förbättra bilden successivt. 

TIPS

  • Pilar kan göras på en mängd olika sätt (se nästa steg). I detta läge är det dock viktigt att utgå från det faktiska informationsbehovet och rita pilen från det system där data uppstår till det system som är i behov av data.
  • I de fall flera system är i behov av samma data så visualisera detta genom att lägga pilen bakom systemet. På så vis ser man vilket system datat kommer ifrån (se exempel till höger där system C får data från system A. Detta kommer tydliggöras än mer om/ när gränssnitt ritas in.

Steg 3 - Data och gränssnitt

Utifrån vad som är känt kring eventuella gränssnitt så lägg till information om gränssnittsnamn (ofta säger ett frågetecken mer än att lämna det blankt), meddelandeformat och integrationstyp.
I detta läge kan det också vara bra att fundera på om man vill visualisera/ tydliggöra olika ansvarsdragningar i utvecklingen, ex vis om flera olika leverantörer är inblandade (ej med i bilden till nedan).

TIPS

  • Benämning av meddelandetyp har visat sig viktigt i detta läge då en bra namnstandard, ex vis IM för kanoniskt format, underlättar förståelsen. Utifrån ditt företags standardnamnsättning kan det också vara lämpligt att inkludera integrationsnamnet, ex vis INTxxxx, för att peka till rätt mappningsspecifikation och lösningsdokument.

Steg 4 - Status och prioritet

Särskilt i ett utvecklingsskede så är det viktigt att ha en uppdaterad status för gränssnitt och integrationer. För att göra detta rekommenderas enklast möjliga färgläggning i grönt, gult och rött.
Prioritering anges lämpligen genom att vikta strecken/ pilarna

TIPS
Likt bilden till höger så bör du lägga till en förklarande ruta för status och prioritet.

Steg 5 - Färdigställande

Rensa upp, tydliggör delar som återstår (hamnar i förvaltning)  eller inte fungerar tillfredsställande. Tänk också på att hålla bilden levande under informationsbehovets livscykel.

Avslutningsvis

Den modell jag har tagit fram används i dagsläget på två företag inom olika branscher och har presenterats och diskuterats i olika nätverk, bl.a. Enterprise Architect-forum.

Lycka till och hör gärna av dig om du har tips/ förslag på hur modellen kan vidareutvecklas.
- Daniel Krantz, Wi-Five AB

Läs hela inlägget »