<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: List/Export Opaque services using API in Dynatrace tips</title>
    <link>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229842#M1098</link>
    <description>&lt;P&gt;Excellent Mostafa! very useful.&lt;img class="lia-deferred-image lia-image-emoji" src="https://community.dynatrace.com/html/@0159DAC3E7471E7A67CC76770F97BEC3/images/emoticons/clap.gif" alt=":clap:" title=":clap:" /&gt;&lt;/P&gt;</description>
    <pubDate>Fri, 24 Nov 2023 10:38:26 GMT</pubDate>
    <dc:creator>Islam_Zedan</dc:creator>
    <dc:date>2023-11-24T10:38:26Z</dc:date>
    <item>
      <title>List/Export Opaque services using API</title>
      <link>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229835#M1097</link>
      <description>&lt;P&gt;For covering all aspects of any environment, it’s important to know your Opaque services as it represents a blind spots in your environment. So what if your environment is huge and you need to easily cover this point to take action like start support ticket for the opaque services relies on technologies that are supported by Dynatrace , upgrade technology version or doing manual instrumentation. So it’s important to not only select this also you should know many other things about each service like process group, process group tech version, in which host it relies and many important meta data about the technology.&lt;/P&gt;&lt;P&gt;We’ll cover this in the below steps:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Auto tag all opaque services&lt;/LI&gt;&lt;LI&gt;Define PowerQuery function to list services from API and this method should be recursive to run through all result pages&lt;/LI&gt;&lt;LI&gt;Define PowerQuery function to get each service details&lt;/LI&gt;&lt;/UL&gt;&lt;H2&gt;&amp;nbsp;&lt;/H2&gt;&lt;H2&gt;1.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Auto tag all Opaque Services&lt;/H2&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;We’ll define auto tag for capturing all services that is&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Not external, so we’ll add to the entity selector that our service must be running on process group that’s hosted on monitored host.&lt;/LI&gt;&lt;LI&gt;Agent technology is missing and this is the Opaque service indicator, accordingly we use &lt;STRONG&gt;agentTechnologyType(“N/A”)&lt;/STRONG&gt; in our entity selector query&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;This is the entity selector query below:&lt;/P&gt;&lt;P&gt;&lt;FONT color="#008080"&gt;type(SERVICE),agentTechnologyType("N/A"),serviceType("WEB_REQUEST_SERVICE"),fromRelationship.runsOn(type(PROCESS_GROUP),fromRelationship.runsOn(type(HOST)))&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mhussein_0-1700817326368.png" style="width: 761px;"&gt;&lt;img src="https://community.dynatrace.com/t5/image/serverpage/image-id/15818i63413B7194F2CAEA/image-dimensions/761x506?v=v2" width="761" height="506" role="button" title="mhussein_0-1700817326368.png" alt="mhussein_0-1700817326368.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H2&gt;2.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Query that get entity details (service / process group)&lt;/H2&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;When we getting list of services from the api we just get 3 things&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Entity type&lt;/LI&gt;&lt;LI&gt;Entity ID&lt;/LI&gt;&lt;LI&gt;Entity name&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;So we want to get entity details in addition for the ease of analysis in the future and defining the hotspots if we have big number of the opaque services based on process groups, technologies, hosts, etc..&lt;/P&gt;&lt;P&gt;We I made the below code for retrieving the entity details for each service after we fetch all services, open blank excel sheet then from the upper ribbon go to &lt;STRONG&gt;Data &amp;gt; Get Data &amp;gt; From Other Sources &amp;gt; Blank Query&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="markup"&gt;let GetEntityDetails = (EntityID as text) =&amp;gt;
    let
        Response = Json.Document(Web.Contents("https://{your-domain}/e/{your-environment-id}/api/v2/entities/" &amp;amp; EntityID , [Headers=[Accept="application/*", #"Accept-Charset"="utf-8", #"Content-Type"="application/json", Authorization="Api-Token {your-token}"]]))
    in
        Response
in
    GetEntityDetails&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;H2&gt;3.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Query that retrieve pages and get services&lt;/H2&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In this section we’ll divide our code to 3 parts&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Part 1: how to make it recursive for fetch all services from all pages&lt;/LI&gt;&lt;LI&gt;Part 2: get the service details&lt;/LI&gt;&lt;LI&gt;Part 3: transform fetched data&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;To do all that we need API key with &lt;STRONG&gt;entities.read&lt;/STRONG&gt; permission.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Part 1:&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;This is a recursive function for retrieving all services through all pages, as its repeat itself, when you use &lt;STRONG&gt;nextPageKey&lt;/STRONG&gt; you don’t have to add &lt;STRONG&gt;entitySelector&lt;/STRONG&gt; or other parameter to the url.&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;In case it’s the first iteration it’ll add all needed parameters to the url&lt;/LI&gt;&lt;LI&gt;In case not, it will just add nextPageKey only to the url&lt;/LI&gt;&lt;LI&gt;In case no nextPageKey exists, it will stop recursion&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;See the below code:&lt;/P&gt;&lt;LI-CODE lang="markup"&gt;let FetchServicesPages = (optional nextPageKey as text) =&amp;gt;
    let
        queryString = if nextPageKey = null then
               "?entitySelector=type(SERVICE),tag(""opaque-service-tag"")"
            else
               "?nextPageKey=" &amp;amp; nextPageKey,

        Response = Json.Document(Web.Contents("{environment-url}" &amp;amp; "api/v2/entities" &amp;amp; queryString, [Headers=[Accept="application/*", #"Accept-Charset"="utf-8", #"Content-Type"="application/json", Authorization="Api-Token {your-token}"]])),

        services = Response[entities],
        #"Services Table" = Table.FromList(services, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
        #"Expanded Column1" = Table.ExpandRecordColumn(#"Services Table", "Column1", {"entityId", "displayName"}),
       
        nextPage = if Record.HasFields(Response, "nextPageKey") then true else false,

        FinalTable =
            if nextPage = true then
                Table.Combine({ #"Expanded Column1", FetchServicesPages(Response[nextPageKey])})
            else
                #"Expanded Column1"
    in
        FinalTable
in
    FetchServicesPages&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Part 2:&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Is to get details for each services we have got, before checking the nextPage variable mentioned in part 1, we’ll add new column as below colored line and set it’s value using &lt;STRONG&gt;GetEntityDetails&lt;/STRONG&gt; method we’ve defined separately before by passing the current Service ID to it.&lt;/P&gt;&lt;P&gt;&lt;FONT color="#008080"&gt;#"Get Service Details" = Table.AddColumn(#"Expanded Column1", "ServiceDetails", each GetEntityDetails([entityId])),&lt;/FONT&gt;&lt;/P&gt;&lt;P&gt;&lt;EM&gt;see the below code snippet as our code should be&lt;/EM&gt;:&lt;/P&gt;&lt;LI-CODE lang="markup"&gt;let FetchServicesPages = (optional nextPageKey as text) =&amp;gt;
    let
        queryString = if nextPageKey = null then
                "?entitySelector=type(SERVICE),tag(""opaque-service-tag"")"
            else
                "?nextPageKey=" &amp;amp; nextPageKey,

        Response = Json.Document(Web.Contents("environment url" &amp;amp; "api/v2/entities" &amp;amp; queryString, [Headers=[Accept="application/*", #"Accept-Charset"="utf-8", #"Content-Type"="application/json", Authorization="Api-Token your token"]])),
        services = Response[entities],

        #"Services Table" = Table.FromList(services, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
        #"Expanded Column1" = Table.ExpandRecordColumn(#"Services Table", "Column1", {"entityId", "displayName"}),
        #"Get Service Details" = Table.AddColumn(#"Expanded Column1", "ServiceDetails", each GetEntityDetails([entityId])),

        nextPage = if Record.HasFields(Response, "nextPageKey") then true else false,
        FinalTable =
            if nextPage = true then
                Table.Combine({ #"Get Service Details", FetchServicesPages(Response[nextPageKey])})
            else
                #"Get Service Details"
    in
        FinalTable
in
    FetchServicesPages&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Part 3:&lt;/STRONG&gt;&lt;/P&gt;&lt;P&gt;Transform ServiceDetails columns to get readable data.&lt;/P&gt;&lt;P&gt;when you expand technologies column you'll get duplication for each service by its techs it relies on, so it's important to limit service selection only based on Primary Technology!&lt;/P&gt;&lt;P&gt;what we did for defining the primary technology depending on Icon column based on it we remove other technologies from the list to keep only the primary technology name &amp;amp; version.&lt;/P&gt;&lt;P&gt;&lt;EM&gt;see the lines starting from&amp;nbsp;&lt;/EM&gt;&lt;STRONG&gt;#"Expanded ServiceDetails"&lt;/STRONG&gt;&lt;EM&gt; in the below code snippet&lt;/EM&gt;:&lt;/P&gt;&lt;LI-CODE lang="markup"&gt;let FetchServicesPages = (optional nextPageKey as text) =&amp;gt;
    let
        queryString = if nextPageKey = null then
                "?entitySelector=type(SERVICE),tag(""opaque-service-tag"")"
            else
                "?nextPageKey=" &amp;amp; nextPageKey,

        Response = Json.Document(Web.Contents("environment url" &amp;amp; "api/v2/entities" &amp;amp; queryString, [Headers=[Accept="application/*", #"Accept-Charset"="utf-8", #"Content-Type"="application/json", Authorization="Api-Token your token"]])),

        services = Response[entities],

        #"Services Table" = Table.FromList(services, Splitter.SplitByNothing(), null, null, ExtraValues.Error),

        #"Expanded Column1" = Table.ExpandRecordColumn(#"Services Table", "Column1", {"entityId", "displayName"}),

        #"Get Service Details" = Table.AddColumn(#"Expanded Column1", "ServiceDetails", each GetEntityDetails([entityId])),       

       #"Expanded ServiceDetails" = Table.ExpandRecordColumn(#"Get Service Details", "ServiceDetails", {"properties", "icon", "fromRelationships"}),
        #"Expanded properties" = Table.ExpandRecordColumn(#"Expanded ServiceDetails", "properties", {"port", "softwareTechnologies"}, {"port", "softwareTechnologies"}),
        #"Expanded icon" = Table.ExpandRecordColumn(#"Expanded properties", "icon", {"primaryIconType"}, {"primaryTechnology"}),
        #"Expanded fromRelationships" = Table.ExpandRecordColumn(#"Expanded icon", "fromRelationships", {"runsOn", "runsOnHost"}),
        #"Expanded runsOn" = Table.ExpandListColumn(#"Expanded fromRelationships", "runsOn"),
        #"Expanded runsOn1" = Table.ExpandRecordColumn(#"Expanded runsOn", "runsOn", {"id"}),
        #"Expanded runsOnHost" = Table.AddColumn(#"Expanded runsOn1", "HostID", each Text.Combine(List.Transform([runsOnHost], each Text.From([id])), ",")),
        //#"Expanded runsOnHost" = Table.ExpandListColumn(#"Expanded runsOn1",{"runsOnHost", each Text.Combine(List.Transform([runsOnHost], each Text.From([id])), ",")}),
        // #"Expanded runsOnHost" = Table.ExpandListColumn(#"Expanded runsOn1", "runsOnHost"),
        #"Removed Columns" = Table.RemoveColumns(#"Expanded runsOnHost", {"runsOnHost"}),
        #"Expanded softwareTechnologies" = Table.ExpandListColumn(#"Removed Columns", "softwareTechnologies"),
        #"Expanded softwareTechnologies1" = Table.ExpandRecordColumn(#"Expanded softwareTechnologies", "softwareTechnologies", {"type", "version"}, {"technologyType", "technologyVersion"}),
        #"Uppercased Text" = Table.TransformColumns(#"Expanded softwareTechnologies1",{{"primaryTechnology", Text.Upper, type text}}),
        #"Replaced Value" = Table.ReplaceValue(#"Uppercased Text","-","_",Replacer.ReplaceText,{"primaryTechnology"}),
        #"Filtered Rows" = Table.SelectRows(#"Replaced Value", each [technologyType] = [primaryTechnology]),

        nextPage = if Record.HasFields(Response, "nextPageKey") then true else false,

        FinalTable =
            if nextPage = true then
                Table.Combine({ #"Filtered Rows", FetchServicesPages(Response[nextPageKey])})
            else
                #"Filtered Rows"
    in
        FinalTable
in
    FetchServicesPages&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Finally you can focus on &lt;STRONG&gt;FetchServicesPages&lt;/STRONG&gt; and press invoke without entering the &lt;STRONG&gt;nextPageKey&lt;/STRONG&gt; as it’s optional parameter as shown below.&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="mhussein_1-1700818473558.png" style="width: 825px;"&gt;&lt;img src="https://community.dynatrace.com/t5/image/serverpage/image-id/15819i43BE2D03601E1AA6/image-dimensions/825x522?v=v2" width="825" height="522" role="button" title="mhussein_1-1700818473558.png" alt="mhussein_1-1700818473558.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 24 Nov 2023 09:43:58 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229835#M1097</guid>
      <dc:creator>MostafaHussein</dc:creator>
      <dc:date>2023-11-24T09:43:58Z</dc:date>
    </item>
    <item>
      <title>Re: List/Export Opaque services using API</title>
      <link>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229842#M1098</link>
      <description>&lt;P&gt;Excellent Mostafa! very useful.&lt;img class="lia-deferred-image lia-image-emoji" src="https://community.dynatrace.com/html/@0159DAC3E7471E7A67CC76770F97BEC3/images/emoticons/clap.gif" alt=":clap:" title=":clap:" /&gt;&lt;/P&gt;</description>
      <pubDate>Fri, 24 Nov 2023 10:38:26 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229842#M1098</guid>
      <dc:creator>Islam_Zedan</dc:creator>
      <dc:date>2023-11-24T10:38:26Z</dc:date>
    </item>
    <item>
      <title>Re: List/Export Opaque services using API</title>
      <link>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229848#M1100</link>
      <description>&lt;P&gt;many thanks, appreciate your support.&lt;/P&gt;</description>
      <pubDate>Fri, 24 Nov 2023 12:05:31 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229848#M1100</guid>
      <dc:creator>MostafaHussein</dc:creator>
      <dc:date>2023-11-24T12:05:31Z</dc:date>
    </item>
    <item>
      <title>Re: List/Export Opaque services using API</title>
      <link>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229864#M1101</link>
      <description>&lt;P&gt;Thank you for sharing this great info, I'm sure that the tips that you have shared recently are very useful for the Dynatrace community, Keep up the great work!&lt;/P&gt;</description>
      <pubDate>Fri, 24 Nov 2023 15:17:02 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229864#M1101</guid>
      <dc:creator>Mohamed_Hamdy</dc:creator>
      <dc:date>2023-11-24T15:17:02Z</dc:date>
    </item>
    <item>
      <title>Re: List/Export Opaque services using API</title>
      <link>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229886#M1102</link>
      <description>&lt;P&gt;Many Thanks&amp;nbsp;&lt;a href="https://community.dynatrace.com/t5/user/viewprofilepage/user-id/4007"&gt;@Mohamed_Hamdy&lt;/a&gt;&amp;nbsp;your support is too much appreciated.&lt;/P&gt;</description>
      <pubDate>Fri, 24 Nov 2023 19:03:28 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229886#M1102</guid>
      <dc:creator>MostafaHussein</dc:creator>
      <dc:date>2023-11-24T19:03:28Z</dc:date>
    </item>
    <item>
      <title>Re: List/Export Opaque services using API</title>
      <link>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229907#M1103</link>
      <description>&lt;P&gt;Thank you!&amp;nbsp;This is very useful.&lt;/P&gt;</description>
      <pubDate>Sat, 25 Nov 2023 17:24:23 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229907#M1103</guid>
      <dc:creator>radek_jasinski</dc:creator>
      <dc:date>2023-11-25T17:24:23Z</dc:date>
    </item>
    <item>
      <title>Re: List/Export Opaque services using API</title>
      <link>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229916#M1104</link>
      <description>&lt;P&gt;Really effective tips, thanks for you addiction&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sun, 26 Nov 2023 06:29:56 GMT</pubDate>
      <guid>https://community.dynatrace.com/t5/Dynatrace-tips/List-Export-Opaque-services-using-API/m-p/229916#M1104</guid>
      <dc:creator>IslamEsmail</dc:creator>
      <dc:date>2023-11-26T06:29:56Z</dc:date>
    </item>
  </channel>
</rss>

