Edellisessä jutussa käytiin läpi miten lähtetetään viesti Teamsiin, jos flow’ssa tapahtuu virhe. Tällä kertaa ihmetellään, saisiko viestiin mukaan tarkemman tiedon tapahtuneesta virheestä/virheistä.

Tähän voimme hyödyntää kahta cloud flow’n funktiota, joihin tutustutaan nyt hieman tarkemmin.

Result() -funktio

Result()-funktio palauttaa kaikkien yhden kokonaisuuden (scope, for each, do until) sisällä suoritettujen toimintojen tiedot. Onnistumiset ja epäonnistumiset.

Alla kaikki toimenpiteet suoritetaan scopen (Scope – Main) sisällä. Tämän jälkeen mahdollisista virheistä raportoidaan eteenpäin toisen scopen (Scope – On Error) sisällä.

Komennolla result(’Scope_-_Main’) saamme yhteenvedon siitä, miten scopen sisällä oleville toiminnoille kävi. Tähän tyyliin:

    {
      "name": "Delete_item_t",
      "inputs": {
        "host": {
          "apiId": "subscriptions/754abb9d-e636-47dd-b406-0a8f58702e36/providers/Microsoft.Web/locations/westeurope/runtimes/europe-002/apis/sharepointonline",
          "connectionReferenceName": "shared_sharepointonline",
          "operationId": "DeleteItem"
        },
        "parameters": {
          "dataset": "https://pertilamvp.sharepoint.com/sites/PowerAppsandPowerAutomateDemos",
          "table": "0e929ef9-7088-4a14-9900-79f98bd78917",
          "id": 50000
        }
      },
      "outputs": {
        "statusCode": 404,
        "headers": {
          "Vary": "Origin",
          "X-SharePointHealthScore": "2",
          "X-MS-SPConnector": "1",
          "X-SP-SERVERSTATE": "ReadOnly=0",
          "DATASERVICEVERSION": "3.0",
          "SPClientServiceRequestDuration": "41",
          "SPRequestGuid": "70388b5b-2774-420f-a0d9-bd9970ebad63",
          "request-id": "70388b5b-2774-420f-a0d9-bd9970ebad63",
          "MS-CV": "W4s4cHQnD0Kg2b2ZcOutYw.0",
          "Strict-Transport-Security": "max-age=31536000",
          "X-FRAME-OPTIONS": "SAMEORIGIN",
          "Content-Security-Policy": "frame-ancestors 'self' teams.microsoft.com *.teams.microsoft.com *.skype.com *.teams.microsoft.us local.teams.office.com *.powerapps.com *.yammer.com *.officeapps.live.com *.office.com *.stream.azure-test.net *.microsoftstream.com *.dynamics.com;",
          "MicrosoftSharePointTeamServices": "16.0.0.21903",
          "X-Content-Type-Options": "nosniff",
          "X-MS-InvokeApp": "1; RequireReadOnly",
          "Timing-Allow-Origin": "*",
          "x-ms-apihub-cached-response": "false",
          "Cache-Control": "max-age=0, private",
          "Date": "Sat, 27 Nov 2021 07:53:36 GMT",
          "P3P": "CP=\"ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI\"",
          "X-AspNet-Version": "4.0.30319",
          "X-Powered-By": "ASP.NET",
          "Content-Length": "168",
          "Content-Type": "application/json",
          "Expires": "Fri, 12 Nov 2021 07:53:37 GMT",
          "Last-Modified": "Sat, 27 Nov 2021 07:53:37 GMT"
        },
        "body": {
          "status": 404,
          "message": "Item Not Found\r\nclientRequestId: 70388b5b-2774-420f-a0d9-bd9970ebad63\r\nserviceRequestId: 70388b5b-2774-420f-a0d9-bd9970ebad63"
        }
      },
      "startTime": "2021-11-27T07:53:37.078503Z",
      "endTime": "2021-11-27T07:53:37.2972624Z",
      "trackingId": "a777d933-a84d-48d1-b33c-28ad78425891",
      "clientTrackingId": "08585640239763575357733837958CU45",
      "clientKeywords": [
        "testFlow"
      ],
      "code": "NotFound",
      "status": "Failed"
    }

Voimme suodattaa (Filter Array) lopputuloksen status-kentän perusteella, jolloin jäljelle jää ainoastaan epäonnistuneet toimintojen suoritukset.

Lopuksi voimme käydä läpi nämä virheeseen päättyneet toiminnot ja kerätä niistä kiinnostavat tiedot muuttujaan.

Näin kerätty virhelista voidaan laittaa lisätiedoksi Teamsiin lähetttävään ilmoitukseeen.

Error found on action: Update_item_x
Error:  Could not find list item.
clientRequestId: 9c19e8a1-f6e2-47b5-9d47-e0b318e898d4
serviceRequestId: 9c19e8a1-f6e2-47b5-9d47-e0b318e898d4

Error found on action: Delete_item_t
Error:  Item Not Found
clientRequestId: 447383b8-0d37-4cf0-a4b4-60091c2cf332
serviceRequestId: 447383b8-0d37-4cf0-a4b4-60091c2cf332

Kätevää.

Vai onko sittenkään?

Seuraavassa flow’ssa käydään läpi SharePoint-listan rivejä. Jokaisen rivin kohdalla yritetään poistaa rivi toiselta listalta.

Tässä suorituksessa molemmat delete-toiminnot epäonnistuvat, jolloin koko Apply to each -toiminto päätyy virheeseen.

Saamme result()-funktion avulla tiedon ainoastaan siitä, että Apply to each-toiminto on epäonnistunut.

"code": "ActionFailed",
      "status": "Failed",
      "error": {
        "code": "ActionFailed",
        "message": "An action failed. No dependent actions succeeded."
      }

Oikeasti meitä kiinnostaisi se, mikä siellä silmukan sisällä on mennyt pieleen.

Luodaan seuraavaksi silmukka (Do until), joka käydään läpi kaksi kertaa. Jälkimmäisellä kierroksella yritetää poistaa SharePoint-listalta rivi.

Nyt silmukan toinen kierros päättyy virheeseen.

Result(’Scope_-_Main’) on kuitenki edelleen kovin lyhytsanainen.

”Kaksi kierrosta. Olen päättynyt virheeseen.”

[
    {
      "name": "Do_until",
      "startTime": "2021-11-27T08:30:17.0534786Z",
      "endTime": "2021-11-27T08:30:18.0534861Z",
      "trackingId": "f2d06f96-6369-4304-b713-f39acb56d05c",
      "clientTrackingId": "08585640239763575357733837958CU45",
      "clientKeywords": [
        "testFlow"
      ],
      "code": "ActionFailed",
      "status": "Failed",
      "error": {
        "code": "ActionFailed",
        "message": "An action failed. No dependent actions succeeded."
      },
      "iterationCount": 2
    }
  ]

Tämän kertoo myös dokumentaatio.

The result() function returns the results from only the first-level actions and not from deeper nested actions such as switch or condition actions.

Emme siis tiedä miten moni silmukan suorituksista päättyi virheeseen ja miten moni onnistui. Ei tällä käytännössä kauheasti tee mitään.

Mutta entäs se outputs()-funktio?

Outputs()-funktio

Outputs(’toiminnon_nimi’) palauttaa toiminnon paluuarvon kokonaisuudessaan.

Yritetään poistaa olematonta riviä ja otetaan talteen toiminnon outputs().

Outputs()-komennon paluuarvossa meitä kiinnostaa lähinnä seuraavat kentät.

{
    "statusCode": 404,
    "body": {
      "status": 404,
      "message": "Item Not Found\r\nclientRequestId: bbdf9b2b-4f60-486c-bd85-f4d1eb42b3da\r\nserviceRequestId: bbdf9b2b-4f60-486c-bd85-f4d1eb42b3da"
    }
  }

Mainiota! Outputs()-funkiota hyödyntämällä voimme halutessamme kerätä kaikkialla flow’n sisällä talteen virheilmoituksia.

Kunhan muistamme että näin toimittaessa scope ei enää päädy virhetilaan.

Virhetilanteeseen tulee reagoida flow’n lopussa muulla tavoin. Esimerkiksi tarkastamalla onko muuttujaan kertynyt virheilmoituksia.

Virhe funktiossa?

Virhe saattaa tapahtua myös toiminnon sisällä suoritettavassa funktiossa. Simuloidaan tätä laskemalla poistettavan rivin id. Laskutoimitus sisältää nollalla jakamisen, joka menee virheeseen.

Mitä nyt tapahtuu?

Käytännössä Delete item -toimintoa ei suoriteta laisinkaan, sillä sen sisällä oleva funktio menee virheeseen ennen kuin toimintoa päästään suorittamaan. Tästä johtuen toiminnon jälkeinen outputs()-funktio menee myöskin virheeseen, sillä sen viittaamaa toimintoa ei ole suoritettu.

Jep.

Tälle tielle lähtiessä käy nopeasti niin, että virhekäsittely generoi enemmän virheitä kuin itse toiminnallisuus. Aiemmin kuvaamani tapa on mielestäni useimmiten riittävä. Lähetetään virheen sattuessa tieto ”jonnekin”. Viesti sisältää linkin virheeseen menneeseen suoritukseen.

Kyllä se virhe sieltä sitten katsomalla selviää.

Power Platform pyyntöjen optimointi outputs()-funktion avulla

Outputs()-funktiota voi hyödyntää myös Power Platform palvelupyyntöjen optimoinnissa.

Alla on esitetty tyypillinen tilanne. Haetaan rivejä (Get items) ja jokaisen rivin kohdalla päivitetään vastaavaa riviä toisaalla (Update item). Jos vastaavaa riviä ei löydy (Get items palauttaa tyhjän joukon), sellainen luodaan (Create item).

Tiedämme tämän flow’n osalta 95% suorituksista olevan tietojen päivittämistä. Vastaavan rivin puuttuuminen toisesta taulusta on harvinaista.

Mikäli päivitettäviä rivejä on 200 kpl, syntyy tästä flow’sta 801 pyyntöä.

Muutetaan flow’ta hieman. Suoritetaan päivitys aina toiseen tauluun. Riippumatta siitä onko päivitettävää riviä olemassa vai ei.

Päivitettävän rivin Id:nä käytetään kaavaa

coalesce(first(outputs('Get_items_-_for_update')?['body/value'])?['Id'],100000000)

Eli käytetään joko löytyneen ensimmäisen löytyneen rivin Id:tä (vastaavia rivejä on aina max 1) tai id:tä 100000000 (jota ei koskaan ole olemassa).

Mikäli flow yrittää päivittää riviä 100000000 (eli kun päivitettävää rivieä ei Get items – for update -toiminnolla löytynyt), menee päivitys virheeseen. Tällöin tarkistetaan onko virhe 404 (not found), jolloin luodaan tarvittava rivi oikeilla tiedoilla.

Nyt saman 200 rivin läpikäynti vie 621 pyyntöä.