- 12 minutes to read

FAQ — Generate a batch of Nodinite JSON Log Events (PowerShell 7)

This FAQ shows PowerShell 7 scripts to generate Nodinite JSON Log Event files for demos, load testing, and exception logging scenarios.

What you'll find on this page:

  • Batch generation script - Create hundreds of realistic order events for testing
  • Exception logging script - Generate .NET exception chains (Azure Functions, database errors)
  • Ready-to-use examples - Copy, customize, and run immediately with PowerShell 7
  • Pickup Service integration - Files written in the correct format for asynchronous delivery

Use cases: Demo environments, load testing, training sessions, exception handling validation, and testing Nodinite v7's exception viewer.

PowerShell 7 required: These scripts use PowerShell 7 features like improved JSON handling, better UTF-8 support, and cross-platform compatibility. Install PowerShell 7 if you haven't already.

Jump to section: Understanding Log Event Generation | Batch Generation | Exception Logging | How v7 Displays Exceptions

Understanding Log Event Generation

Nodinite Log Events are JSON files that contain structured logging data. When you need to test your logging infrastructure or create demo environments, manually creating hundreds of events is impractical. These PowerShell 7 scripts automate the process by:

  • Generating valid JSON - Each file matches the Log Event schema
  • Simulating realistic data - Random cities, order IDs, timestamps, and processing times
  • Creating exception chains - Nested .NET exceptions with stack traces and error codes
  • Base64-encoding payloads - The Body field contains base64-encoded JSON (as required)

The generated files can be consumed by the Pickup Service for asynchronous delivery to the Logging Service, or sent directly via Log API.

Why PowerShell 7? PowerShell 7 provides better JSON handling with ConvertTo-Json -Depth, improved UTF-8 encoding without BOM, and cross-platform compatibility. These features ensure the generated Log Events are correctly formatted for Nodinite.

Learn more: Log Event structure | JSON Log Event schema | Pickup Service overview | Install PowerShell 7

Batch Generation: Order Events

Generate multiple order events with randomized data for demo or load testing purposes.

Configuration options: Customize LogAgentValueId, EndPointName, MessageType, and order count parameters. Files are written to the specified output folder in UTF-8 format (no BOM) for compatibility with the Pickup Service.

Usage (quick)

Open PowerShell 7 terminal and run:

pwsh .\Generate-Nodinite-LogEvents.ps1 -OrderCount 150 -OutputFolder 'C:\temp\logevents'

This will create 150 JSON files in the target folder with LogDateTime values scattered earlier today.

Verify PowerShell 7: Run $PSVersionTable.PSVersion to confirm you're using PowerShell 7.0 or later. Download PowerShell 7 if needed.

Script: Generate-Nodinite-LogEvents.ps1

Save this file next to your documentation or in a demo folder. It uses PowerShell 7 features for improved JSON handling and UTF-8 encoding.

#!/usr/bin/env pwsh
#Requires -Version 7.0
<#
.SYNOPSIS
Generates Nodinite-style LogEvent JSON files for demo/load-testing.

.DESCRIPTION
This PowerShell 7 script creates realistic Log Event JSON files for testing Nodinite.
- Requires PowerShell 7.0 or later
- Each file contains a single LogEvent object
- UTF-8 encoding without BOM
- Randomized data for realistic testing

.PARAMETER OrderCount
Number of order events to generate (default: 150)

.PARAMETER OutputFolder
Destination folder for generated JSON files (default: C:\temp\logevents)

.EXAMPLE
pwsh .\Generate-Nodinite-LogEvents.ps1 -OrderCount 150 -OutputFolder 'C:\temp\logevents'
#>
param(
    [int]$OrderCount = 150,
    [string]$OutputFolder = 'C:\temp\logevents',
    [int]$RowsMin = 1,
    [int]$RowsMax = 9,
    [int]$LogAgentValueId = 42,
    [string]$EndPointName = 'INT101: Demo Log Events',
    [string]$MessageType = 'Demo.Order/1.0'
)

# Ensure folder exists
if (-not (Test-Path -Path $OutputFolder)) {
    New-Item -Path $OutputFolder -ItemType Directory -Force | Out-Null
}

# City list for variety
$cities = @(
    'New York','London','Tokyo','Sydney','Mumbai','São Paulo','Cairo','Nairobi','Moscow','Berlin',
    'Paris','Madrid','Rome','Lisbon','Oslo','Stockholm','Helsinki','Reykjavik','Dubai','Singapore',
    'Hong Kong','Seoul','Beijing','Jakarta','Bangkok','Manila','Mexico City','Vancouver','Toronto','Los Angeles'
)

# Helper: base64 encode text
function To-Base64([string]$text) {
    return [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($text))
}

# Determine a start time "some time ago today" (random earlier time today)
$now = Get-Date
$maxHours = [Math]::Max(1, $now.Hour)
$startHour = Get-Random -Minimum 1 -Maximum ($maxHours + 1)
$startMinute = Get-Random -Minimum 0 -Maximum 59
$startSecond = Get-Random -Minimum 0 -Maximum 59
$startDate = $now.Date.AddHours($startHour).AddMinutes($startMinute).AddSeconds($startSecond)

# If startDate is in the future, fallback to now
if ($startDate -gt $now) {
    $startDate = $now.AddMinutes(-(Get-Random -Minimum 1 -Maximum 60))
}

Write-Host "Generating $OrderCount events starting around: $($startDate.ToString('o'))" -ForegroundColor Cyan

$current = $startDate.ToUniversalTime()

for ($i = 1; $i -le $OrderCount; $i++) {
    # Generate unique order ID: ORD-MMDDHHMM-###
    $orderTimestamp = $current.ToString('MMddHHmm')
    $orderSequence = $i.ToString('D3')
    $orderNumber = "ORD-$orderTimestamp-$orderSequence"
    
    $city = $cities[Get-Random -Minimum 0 -Maximum $cities.Count]
    $rowCount = Get-Random -Minimum $RowsMin -Maximum ($RowsMax + 1)

    $rows = for ($r = 1; $r -le $rowCount; $r++) {
        @{ Id = $r; Amount = (Get-Random -Minimum 1 -Maximum 100) }
    }

    $payload = @{ OrderNumber = $orderNumber; City = $city; Date = $current.ToString('o'); Rows = $rows } | ConvertTo-Json -Depth 5

    # Build the LogEvent object (fields chosen to be compatible with Nodinite JSON Log Event)
    $logEvent = [ordered]@{
        LogAgentValueId = $LogAgentValueId
        EndPointName = $EndPointName
        EndPointUri = "C:\\temp\\pickup"
        EndPointDirection = 0
        EndPointTypeId = 60
        OriginalMessageTypeName = $MessageType
        LogDateTime = $current.ToString('o')
        EventDirection = 0
        ProcessingUser = "DEMO\\Generator"
        SequenceNo = $i
        EventNumber = $i
        LogText = "Demo order generated"
        ApplicationInterchangeId = $orderNumber
        LogStatus = 0
        ProcessName = "DemoOrderProcess"
        ProcessingMachineName = $env:COMPUTERNAME
        ProcessingModuleName = "Generate-Nodinite-LogEvents.ps1"
        ProcessingModuleType = "DemoGenerator"
        ProcessingTime = (Get-Random -Minimum 10 -Maximum 300)
        Body = To-Base64 $payload
        Context = @{ OrderNumber = $orderNumber; City = $city }
    }

    $json = $logEvent | ConvertTo-Json -Depth 10

    $fileName = "LogEvent_{0}_{1}.json" -f $orderNumber, ([guid]::NewGuid())
    $filePath = Join-Path -Path $OutputFolder -ChildPath $fileName

    # Write UTF8 no BOM
    [System.IO.File]::WriteAllText($filePath, $json, [System.Text.Encoding]::UTF8)

    # Advance current by a few to tens of seconds (randomized)
    $current = $current.AddSeconds((Get-Random -Minimum 5 -Maximum 300))

    if ($i % 50 -eq 0) { Write-Host "  Created $i/$OrderCount events..." -ForegroundColor Green }
}

Write-Host "Done. Files written to: $OutputFolder" -ForegroundColor Cyan

What this script does:

  • PowerShell 7 features - Uses improved ConvertTo-Json -Depth and UTF-8 encoding without BOM
  • Randomizes data - Each order gets a random city from 30+ options and 1-9 order rows
  • Realistic timestamps - Events scattered throughout earlier today (simulates organic traffic)
  • Base64 encoding - Payload JSON is automatically base64-encoded in the Body field
  • Context properties - Includes OrderNumber and City for searchability in Log Views
  • Processing metadata - Sets ProcessingTime, ProcessingMachineName, and other Log Event properties

Next steps: Place generated files in the Pickup Service input folder, or use Log API to send them directly via HTTP POST.

Compatibility note: This script requires PowerShell 7 or later. The #Requires -Version 7.0 directive ensures the script won't run on older PowerShell versions.


Exception Logging: .NET Exception Chains

Nodinite v7 includes a specialized exception viewer that beautifully displays exception chains directly in the Log View. When logging exceptions from .NET applications, Azure Functions, or with Serilog, serialize the exception to JSON and include it in the Body as a base64-encoded payload.

Why this matters: Exception chains show the complete failure path from root cause to final error. The Log Views exception viewer in Nodinite v7 parses .NET exception structures automatically, making troubleshooting faster and more accurate.

Serilog integration: When using Serilog with Nodinite sinks, exceptions are automatically stored in Context["ExtendedProperties/1.0#Exception"] when you call .Error(exception, message). This script mimics that behavior for testing. Learn more: Serilog .NET Exceptions

How Nodinite v7 Displays Exceptions

When you open this Log Event in Nodinite v7 Log View, the exception viewer will display:

  • Exception chain visualization - Each exception level is clearly separated
  • Stack trace formatting - Line breaks and indentation preserved for readability
  • Inner exception navigation - Drill down from outer to inner exceptions
  • Exception properties - HResult, error codes, source, and other .NET exception details
  • Contextual information - Order ID, retry attempts, and environment details in Context properties
  • Formula-based extraction - Use JsonPath('..Message', Context('ExtendedProperties/1.0#Exception')) to extract specific exception data for Search Fields

Exception Details in Log View
Screenshot of the exception details view in a Nodinite v7 Log View.

Serilog users: See Serilog .NET Exceptions for how exceptions are automatically captured and formatted when using .Error(exception, message) with Nodinite sinks.

Try it yourself: Generate an exception Log Event using the script above, place it in the Pickup Service folder, then open it in Log Views to see the v7 exception viewer in action.

Typical Exception Scenario

This example simulates a common .NET application scenario: An Azure Function attempts to process an order, encounters a database connection timeout, which is caused by a DNS resolution failure.

Script: Generate-Exception-LogEvent.ps1

This PowerShell 7 script generates a realistic .NET exception chain for testing the Nodinite v7 exception viewer.

#!/usr/bin/env pwsh
#Requires -Version 7.0
<#
.SYNOPSIS
Generate a Nodinite LogEvent with a .NET exception chain in the payload.

.DESCRIPTION
This PowerShell 7 script creates a realistic exception Log Event for testing.
The exception simulates: Azure Function → Database Timeout → DNS Resolution Failure
- Requires PowerShell 7.0 or later
- Creates nested exception chain with stack traces
- UTF-8 encoding without BOM

.PARAMETER OutputFolder
Destination folder for the generated JSON file (default: C:\temp\logevents)

.EXAMPLE
pwsh .\Generate-Exception-LogEvent.ps1 -OutputFolder 'C:\temp\logevents'
#>
param(
    [string]$OutputFolder = 'C:\temp\logevents',
    [int]$LogAgentValueId = 42,
    [string]$EndPointName = 'INT201: Process Order Azure Function',
    [string]$MessageType = 'Error.Exception/1.0'
)

# Ensure folder exists
if (-not (Test-Path -Path $OutputFolder)) {
    New-Item -Path $OutputFolder -ItemType Directory -Force | Out-Null
}

# Helper: base64 encode text
function To-Base64([string]$text) {
    return [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($text))
}

# Generate unique order number: ORD-MMDDHHMM-001
$timestamp = (Get-Date).ToString('MMddHHmm')
$orderNumber = "ORD-$timestamp-001"

# Build exception chain (innermost first)
$dnsException = @{
    ClassName = "System.Net.Sockets.SocketException"
    Message = "No such host is known (sql-prod-east.database.windows.net)"
    Source = "System.Net.Sockets"
    StackTraceString = "   at System.Net.Dns.GetHostEntry(String hostNameOrAddress)`n   at System.Data.SqlClient.SNI.SNITCPHandle.GetFQDN(String hostname)`n   at System.Data.SqlClient.SNI.SNITCPHandle..ctor(String serverName, Int32 port, TimeSpan timeout)"
    HResult = -2147467259
    NativeErrorCode = 11001
    InnerException = $null
}

$sqlException = @{
    ClassName = "System.Data.SqlClient.SqlException"
    Message = "A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 0 - No such host is known.)"
    Source = "Core .Net SqlClient Data Provider"
    StackTraceString = "   at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, DbConnectionPool pool, String accessToken)`n   at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)`n   at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)`n   at OrderProcessingFunction.ProcessOrder(String orderId) in C:\\src\\OrderProcessingFunction.cs:line 127"
    HResult = -2146232060
    Number = -1
    State = 0
    Class = 20
    Server = "sql-prod-east.database.windows.net"
    ErrorCode = -2146232060
    InnerException = $dnsException
}

$applicationException = @{
    ClassName = "System.InvalidOperationException"
    Message = "Failed to process order $orderNumber. Database connection could not be established after 3 retry attempts."
    Source = "OrderProcessingFunction"
    StackTraceString = "   at OrderProcessingFunction.ProcessOrder(String orderId) in C:\\src\\OrderProcessingFunction.cs:line 142`n   at OrderProcessingFunction.Run(TimerInfo myTimer, ILogger log) in C:\\src\\OrderProcessingFunction.cs:line 38`n   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithWatchersAsync(IFunctionInstanceEx instance, ParameterHelper parameterHelper, ILogger logger, CancellationToken cancellationToken)"
    HResult = -2146233079
    InnerException = $sqlException
}

# Create the payload with exception details
$payload = @{
    Timestamp = (Get-Date).ToUniversalTime().ToString('o')
    OrderNumber = $orderNumber
    City = "Los Angeles"
    FunctionName = "ProcessOrderFunction"
    Exception = $applicationException
    RetryAttempts = 3
    Environment = "Production"
    Region = "East US"
    OrderRows = @(
        @{ Id = 1; Amount = 42 }
        @{ Id = 2; Amount = 87 }
        @{ Id = 3; Amount = 15 }
    )
} | ConvertTo-Json -Depth 10

# Build the LogEvent object
$logEvent = [ordered]@{
    LogAgentValueId = $LogAgentValueId
    EndPointName = $EndPointName
    EndPointUri = "https://prod-order-func.azurewebsites.net/api/ProcessOrder"
    EndPointDirection = 0
    EndPointTypeId = 3  # HTTP/HTTPS
    OriginalMessageTypeName = $MessageType
    LogDateTime = (Get-Date).ToUniversalTime().ToString('o')
    EventDirection = 0
    ProcessingUser = "AZURE\\OrderProcessingFunction"
    SequenceNo = 1
    EventNumber = 1
    LogText = "Exception: Failed to process order $orderNumber"
    ApplicationInterchangeId = $orderNumber
    LogStatus = 2  # Error status
    ProcessName = "OrderProcessingFunction"
    ProcessingMachineName = "prod-order-func-001"
    ProcessingModuleName = "ProcessOrderFunction"
    ProcessingModuleType = "AzureFunction"
    ProcessingTime = 15487  # 15.5 seconds before timeout
    Body = To-Base64 $payload
    Context = @{
        OrderNumber = $orderNumber
        ExceptionType = "System.InvalidOperationException"
        FailureReason = "Database Connection Timeout"
        RetryAttempts = "3"
        "ExtendedProperties/1.0#Exception" = ($applicationException | ConvertTo-Json -Depth 10)
    }
}

$json = $logEvent | ConvertTo-Json -Depth 15

$fileName = "LogEvent_Exception_{0}_{1}.json" -f $orderNumber, ([guid]::NewGuid())
$filePath = Join-Path -Path $OutputFolder -ChildPath $fileName

# Write UTF8 no BOM
[System.IO.File]::WriteAllText($filePath, $json, [System.Text.Encoding]::UTF8)

Write-Host "Exception LogEvent created: $filePath" -ForegroundColor Cyan
Write-Host "Exception chain: InvalidOperationException -> SqlException -> SocketException" -ForegroundColor Yellow
Write-Host "Order Number: $orderNumber" -ForegroundColor Green

Common Exception Scenarios for Logging

  • Azure Function failures - Timeout, binding errors, connection issues
  • Database operations - Connection timeouts, deadlocks, constraint violations
  • API integrations - HTTP timeouts, authentication failures, rate limiting
  • Message processing - Deserialization errors, validation failures, poison messages
  • File operations - Access denied, file not found, disk space issues

Tip: Always include the full exception chain with InnerException properties. Nodinite v7's exception viewer makes it easy to diagnose root causes by navigating through the exception hierarchy. Use Context Options to add business identifiers (order IDs, customer IDs) for faster incident correlation in Log Views.

Learn more: Log Status Codes for error classification | Log Views for querying and filtering | Context Options for custom metadata


Notes & tips:

  • PowerShell 7 required: Both scripts use PowerShell 7 features. Run pwsh command (not powershell) to use PowerShell 7. Verify version with $PSVersionTable.PSVersion.
  • For correlated multi-step flows (receive/send pairs) review Generate-O2C-Demo-Data-REFACTORED.ps1 in the Troubleshooting\Demo folder and adapt the deterministic correlation IDs and step templates.
  • If you want to send these events directly to Log API rather than to Pickup Service, wrap the JSON with an HTTP POST using your API key and the Log API endpoint.
  • The exception payload structure shown above mirrors .NET's Exception.ToString() serialization, which Nodinite v7 recognizes and formats automatically.
  • Cross-platform: PowerShell 7 works on Windows, Linux, and macOS. These scripts run on any platform where PowerShell 7 is installed.

Next Step