Send Devolutions Server logs to Azure Log Analytics

This guide provides instructions for creating and configuring all the components needed to send Devolutions Server logs to Azure Log Analytics.

Create a new app registration

  1. Open the Azure portal and navigate to App Registrations.

  2. Click on New Registration.

  3. Give your app a name and click Register (no Redirect URL is necessary).

  4. Under Supported account types, select Accounts in this organizational directory only.

Retrieve client ID and tenant ID

After registration, locate Client ID and Tenant ID under the Overview section. These will be required later.

Create a client secret

  1. Navigate to Certificates & secrets.

  2. Click on New client secret to create a secret.

  3. Save the secret value securely, as it will be used later in Devolutions Server.

  4. Once the secret expires, you must renew it and update it in Devolutions Server; otherwise, log ingestion will stop.

Set up a Data Collection Endpoint (DCE)

Create a Data Collection Endpoint (DCE) in Azure to receive requests from Devolutions Server.

In Devolutions Server, this corresponds to the Azure Endpoint field.

Create an Azure log analytics table

Follow Microsoft's tutorial to create a Log Analytics table in Azure for sample data. Here is the required sample data sent by Devolutions Server.

Retrieve immutable ID and stream name

Once the Log analytics table is created, locate the Immutable ID and Stream Name for log streaming. Log ingestionsetup does not require further configuration here.

Assign permissions to the Data Collection Rule (DCR)

Assign the required permissions to the DCR:

Microsoft.Insights/DataCollectionRules/Read Read a data collection rule
 Microsoft.Insights/DataCollectionRules/Write Create or update a data collection rule
Microsoft.Insights/DataCollectionRules/Delete Delete a data collection rule

Test and activate logging

Click Send Test Log or activate logs to verify they are sent into Sentinel.

KQL commands

Here are some KQL queries to help you quickly analyse the logs sent by Devolutions Server in your Azure Log Analytics environment.

Commands

Description

Table_Name
| where tostring(Event.Level) != "Debug"

Filter debug events

Table_Name
| where tostring(Event.Level) != "Debug"
| extend eventData = parse_json(Event)
| extend LogEvent_Properties = parse_json(tostring(eventData.Properties.LogEvent_Properties))
| project
Timestamp = eventData.Timestamp,
Level = eventData.Level,
Message = eventData.MessageTemplate,
ConnectionID = LogEvent_Properties.ConnectionID,
ConnectionName = LogEvent_Properties.ConnectionName,
Duration = LogEvent_Properties.Duration,
GroupDate = LogEvent_Properties.GroupDate,
MachineName = LogEvent_Properties.MachineName,
Username = LogEvent_Properties.Username

Destructure entries log


Devolutions Server configuration

  1. Open the Devolutions Server web service.

  2. Go to Administration - Server settings - Logging.

  3. Enter the information.

Administration - Server settings - Logging
Administration - Server settings - Logging

Devolutions Server sample data

Here is the sample data sent by Devolutions Server:

[
    {
      "TimeGenerated": "2024-10-16T13:44:47.5509387Z",
      "Event": {
        "Timestamp": "2024-10-16T09:44:25.8462542-04:00",
        "Level": "Debug",
        "MessageTemplate": "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms",
        "TraceId": "c12cb69321ff0864707e3527d05dcce7",
        "SpanId": "79f11f0b42e9c4f0",
        "Properties": {
          "RequestMethod": "GET",
          "RequestPath": "/dps/api/security/application/users/list",
          "StatusCode": 200,
          "Elapsed": 156.3594,
          "SourceContext": "Serilog.AspNetCore.RequestLoggingMiddleware",
          "RequestId": "40000016-0000-fe00-b63f-84710c7967bb"
        },
        "Renderings": {
          "Elapsed": [
            {
              "Format": "0.0000",
              "Rendering": "156.3594"
            }
          ]
        }
      },
      "Message": "HTTP \"GET\" \"/dps/api/security/application/users/list\" responded 200 in 156.3594 ms"
    },
    {
      "TimeGenerated": "2024-10-16T13:44:47.5515067Z",
      "Event": {
        "Timestamp": "2024-10-16T09:44:25.8462943-04:00",
        "Level": "Debug",
        "MessageTemplate": "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms",
        "TraceId": "05a78b4781e238171db4eeb0c02227a2",
        "SpanId": "02b5cf6af13f085c",
        "Properties": {
          "RequestMethod": "GET",
          "RequestPath": "/dps/api/connections/partial/tree/2a18029b-883d-4930-9d3f-c1eb1a57cbdb?includeSummary=false",
          "StatusCode": 200,
          "Elapsed": 106.5969,
          "SourceContext": "Serilog.AspNetCore.RequestLoggingMiddleware",
          "RequestId": "40000008-000a-fd00-b63f-84710c7967bb"
        },
        "Renderings": {
          "Elapsed": [
            {
              "Format": "0.0000",
              "Rendering": "106.5969"
            }
          ]
        }
      },
      "Message": "HTTP \"GET\" \"/dps/api/connections/partial/tree/2a18029b-883d-4930-9d3f-c1eb1a57cbdb?includeSummary=false\" responded 200 in 106.5969 ms"
    },
    {
      "TimeGenerated": "2024-10-16T13:44:47.5515531Z",
      "Event": {
        "Timestamp": "2024-10-16T09:44:25.9138522-04:00",
        "Level": "Debug",
        "MessageTemplate": "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms",
        "TraceId": "04761490f7195b1de4265d0794bb8cda",
        "SpanId": "c6a3435990708323",
        "Properties": {
          "RequestMethod": "GET",
          "RequestPath": "/dps/api/password-configuration",
          "StatusCode": 200,
          "Elapsed": 167.2742,
          "SourceContext": "Serilog.AspNetCore.RequestLoggingMiddleware",
          "RequestId": "40000002-0000-fc00-b63f-84710c7967bb"
        },
        "Renderings": {
          "Elapsed": [
            {
              "Format": "0.0000",
              "Rendering": "167.2742"
            }
          ]
        }
      },
      "Message": "HTTP \"GET\" \"/dps/api/password-configuration\" responded 200 in 167.2742 ms"
    },
    {
      "TimeGenerated": "2024-10-16T13:44:47.5515767Z",
      "Event": {
        "Timestamp": "2024-10-16T09:44:25.9138500-04:00",
        "Level": "Debug",
        "MessageTemplate": "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms",
        "TraceId": "ee5022da714a27f1644c53abc111f3c1",
        "SpanId": "53cda82c4ed064b4",
        "Properties": {
          "RequestMethod": "GET",
          "RequestPath": "/dps/api/security/roles/basic",
          "StatusCode": 200,
          "Elapsed": 211.735,
          "SourceContext": "Serilog.AspNetCore.RequestLoggingMiddleware",
          "RequestId": "40000002-0000-fd00-b63f-84710c7967bb"
        },
        "Renderings": {
          "Elapsed": [
            {
              "Format": "0.0000",
              "Rendering": "211.7350"
            }
          ]
        }
      },
      "Message": "HTTP \"GET\" \"/dps/api/security/roles/basic\" responded 200 in 211.7350 ms"
    },
    {
      "TimeGenerated": "2024-10-16T13:44:47.5515982Z",
      "Event": {
        "Timestamp": "2024-10-16T09:44:25.9139175-04:00",
        "Level": "Debug",
        "MessageTemplate": "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms",
        "TraceId": "7e2d65d01dcb95c74ef2b03c0af22140",
        "SpanId": "84d30dbb5cbbcecd",
        "Properties": {
          "RequestMethod": "GET",
          "RequestPath": "/dps/api/connections/partial/tree/00000000-0000-0000-0000-000000000000?includeSummary=false",
          "StatusCode": 200,
          "Elapsed": 186.1316,
          "SourceContext": "Serilog.AspNetCore.RequestLoggingMiddleware",
          "RequestId": "40000002-0006-fe00-b63f-84710c7967bb"
        },
        "Renderings": {
          "Elapsed": [
            {
              "Format": "0.0000",
              "Rendering": "186.1316"
            }
          ]
        }
      },
      "Message": "HTTP \"GET\" \"/dps/api/connections/partial/tree/00000000-0000-0000-0000-000000000000?includeSummary=false\" responded 200 in 186.1316 ms"
    },
    {
      "TimeGenerated": "2024-10-16T13:44:47.5516143Z",
      "Event": {
        "Timestamp": "2024-10-16T09:44:25.9502376-04:00",
        "Level": "Debug",
        "MessageTemplate": "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms",
        "TraceId": "a3b65a98ff6fe33f67f22ff451094b13",
        "SpanId": "5f3ab7c12942b19c",
        "Properties": {
          "RequestMethod": "GET",
          "RequestPath": "/dps/api/security/resolved-permissions?connectionId=ca90060e-a410-455d-967d-46ca2c3eb39d",
          "StatusCode": 200,
          "Elapsed": 103.5951,
          "SourceContext": "Serilog.AspNetCore.RequestLoggingMiddleware",
          "RequestId": "4000000f-000a-ff00-b63f-84710c7967bb"
        },
        "Renderings": {
          "Elapsed": [
            {
              "Format": "0.0000",
              "Rendering": "103.5951"
            }
          ]
        }
      },
      "Message": "HTTP \"GET\" \"/dps/api/security/resolved-permissions?connectionId=ca90060e-a410-455d-967d-46ca2c3eb39d\" responded 200 in 103.5951 ms"
    },
    {
      "TimeGenerated": "2024-10-16T13:44:47.5516328Z",
      "Event": {
        "Timestamp": "2024-10-16T09:44:25.9832335-04:00",
        "Level": "Debug",
        "MessageTemplate": "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms",
        "TraceId": "02f7d828e01ff47212b339fc4931001b",
        "SpanId": "5fc4b3b327a2dfc5",
        "Properties": {
          "RequestMethod": "GET",
          "RequestPath": "/dps/api/connection/vpn-group/00000000-0000-0000-0000-000000000000",
          "StatusCode": 200,
          "Elapsed": 71.9778,
          "SourceContext": "Serilog.AspNetCore.RequestLoggingMiddleware",
          "RequestId": "40000019-0006-ff00-b63f-84710c7967bb"
        },
        "Renderings": {
          "Elapsed": [
            {
              "Format": "0.0000",
              "Rendering": "71.9778"
            }
          ]
        }
      },
      "Message": "HTTP \"GET\" \"/dps/api/connection/vpn-group/00000000-0000-0000-0000-000000000000\" responded 200 in 71.9778 ms"
    },
    {
      "TimeGenerated": "2024-10-16T13:44:47.5516484Z",
      "Event": {
        "Timestamp": "2024-10-16T09:44:27.6131069-04:00",
        "Level": "Debug",
        "MessageTemplate": "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms",
        "TraceId": "d843142d0e1a4967851abec402433361",
        "SpanId": "40cd4ec917ea3ef0",
        "Properties": {
          "RequestMethod": "PUT",
          "RequestPath": "/dps/api/connection/releaselockedit/ca90060e-a410-455d-967d-46ca2c3eb39d",
          "StatusCode": 200,
          "Elapsed": 49.0958,
          "SourceContext": "Serilog.AspNetCore.RequestLoggingMiddleware",
          "RequestId": "40000002-0005-ff00-b63f-84710c7967bb"
        },
        "Renderings": {
          "Elapsed": [
            {
              "Format": "0.0000",
              "Rendering": "49.0958"
            }
          ]
        }
      },
      "Message": "HTTP \"PUT\" \"/dps/api/connection/releaselockedit/ca90060e-a410-455d-967d-46ca2c3eb39d\" responded 200 in 49.0958 ms"
    },
    {
      "TimeGenerated": "2024-10-16T13:44:47.5516696Z",
      "Event": {
        "Timestamp": "2024-10-16T09:44:30.2814335-04:00",
        "Level": "Debug",
        "MessageTemplate": "HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms",
        "TraceId": "f68d75f4a69a6b0de24ae5d3c637e229",
        "SpanId": "9b1d7ff780c07959",
        "Properties": {
          "RequestMethod": "GET",
          "RequestPath": "/dps/api/connections/partial/templates?forRepositoryId=00000000-0000-0000-0000-000000000000",
          "StatusCode": 200,
          "Elapsed": 57.0181,
          "SourceContext": "Serilog.AspNetCore.RequestLoggingMiddleware",
          "RequestId": "40000011-000a-ff00-b63f-84710c7967bb"
        },
        "Renderings": {
          "Elapsed": [
            {
              "Format": "0.0000",
              "Rendering": "57.0181"
            }
          ]
        }
      },
      "Message": "HTTP \"GET\" \"/dps/api/connections/partial/templates?forRepositoryId=00000000-0000-0000-0000-000000000000\" responded 200 in 57.0181 ms"
    }
  ]

 

Devolutions Forum logo Give us Feedback