Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Diagnostic Dumping Functionality #1443

Draft
wants to merge 39 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
7ffe56c
Add Enhanced Diagnostic Dump Feature with Configurable Output Format…
mdaneri Nov 2, 2024
8cc7d02
add pipe example
mdaneri Nov 2, 2024
6121cb5
various improvements
mdaneri Nov 3, 2024
d362833
Merge branch 'develop' into invoke-podedump
mdaneri Nov 3, 2024
dbf54d9
Fixes and improvements
mdaneri Nov 4, 2024
14afc55
Update Helpers.ps1
mdaneri Nov 4, 2024
34d7b6b
added variables from runspace
mdaneri Nov 5, 2024
f05adda
Update Dump.ps1
mdaneri Nov 5, 2024
b64da21
Added suspend and resume server
mdaneri Nov 5, 2024
7db258a
internazioanalization+ example
mdaneri Nov 5, 2024
88642e8
Update PetData.json
mdaneri Nov 5, 2024
65836b5
Documentation
mdaneri Nov 6, 2024
52574f9
upgrade powershell to '7.2.24'
mdaneri Nov 6, 2024
0bd3f8a
Update Server.Tests.ps1
mdaneri Nov 6, 2024
7dd5f96
Merge branch 'develop' into invoke-podedump
mdaneri Nov 6, 2024
6135e17
fixes
mdaneri Nov 8, 2024
82a6020
Fix CTRL B issue
mdaneri Nov 11, 2024
49f962b
fixes
mdaneri Nov 13, 2024
70a8696
Merge branch 'develop' into invoke-podedump
Badgerati Nov 22, 2024
82c2a28
add net9
mdaneri Nov 22, 2024
6ec63d9
Merge remote-tracking branch 'upstream/develop' into invoke-podedump
mdaneri Nov 23, 2024
e41c207
Merge remote-tracking branch 'upstream/develop' into invoke-podedump
mdaneri Nov 25, 2024
f0c8b45
doc fixes
mdaneri Nov 25, 2024
dc76df3
first review
mdaneri Nov 30, 2024
c8ab57c
second update
mdaneri Dec 1, 2024
79fdf46
suspend http and tcp
mdaneri Dec 1, 2024
900001a
fix tests
mdaneri Dec 2, 2024
526325c
WSS suspension
mdaneri Dec 2, 2024
ce5cc01
Fix suspend
mdaneri Dec 2, 2024
9cdaf4e
Update DebuggerHandler.cs
mdaneri Dec 2, 2024
414d785
minor changes
mdaneri Dec 4, 2024
68f14b0
tentative to use a new terminate token
mdaneri Dec 4, 2024
edc604e
looking good
mdaneri Dec 5, 2024
0081477
Fix the suspend and dump
mdaneri Dec 6, 2024
1791f76
Add progress bar
mdaneri Dec 6, 2024
525638f
debugging
mdaneri Dec 7, 2024
5493c91
suspend resume fixed
mdaneri Dec 7, 2024
3ea0267
fixes
mdaneri Dec 8, 2024
a9dfecf
Changed the runspace enumeration logic
mdaneri Dec 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -266,3 +266,6 @@ examples/PetStore/data/PetData.json
packers/choco/pode.nuspec
packers/choco/tools/ChocolateyInstall.ps1
docs/Getting-Started/Samples.md

# Dump Folder
Dump
159 changes: 155 additions & 4 deletions docs/Getting-Started/Debug.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,27 @@ Start-PodeServer -EnableBreakpoints {
The steps to attach to the Pode process are as follows:

1. In a PowerShell console, start the above Pode server. You will see the following output, and you'll need the PID that is shown:

```plain
Pode v2.10.0 (PID: 28324)
Listening on the following 1 endpoint(s) [1 thread(s)]:
- http://localhost:8080/
```

2. In a browser or a new PowerShell console, invoke the `[GET] http://localhost:8080` Route to hit the breakpoint.

```powershell
Invoke-RestMethod -Uri 'http://localhost:8080/'
```

3. Open another new PowerShell console, and run the following command to enter the first PowerShell console running Pode - you'll need the PID as well:

```powershell
Enter-PSHostProcess -Id '<PID_HERE>'
```

4. Once you have entered the PowerShell console running Pode, run the below command to attach to the breakpoint:

```powershell
Get-Runspace |
Where-Object { $_.Debugger.InBreakpoint } |
Expand All @@ -101,6 +105,7 @@ The steps to attach to the Pode process are as follows:
7. When you are done debugging the current request, hit the `d` key.

8. When you're done with debugging altogether, you can exit the entered process as follows:

```powershell
exit
```
Expand All @@ -110,6 +115,7 @@ The steps to attach to the Pode process are as follows:
If you're using [`Wait-PodeDebugger`](../../Functions/Core/Wait-PodeDebugger) then you can leave these breakpoint lines in place, and toggle them in non-developer environments by passing `-EnableBreakpoints` to [`Start-PodeServer`](../../Functions/Core/Start-PodeServer). If you don't supply `-EnableBreakpoints`, or you explicitly pass `-EnableBreakpoints:$false`, then this will disable the breakpoints from being set.

You can also toggle breakpoints via the `server.psd1` [configuration file](../../Tutorials/Configuration):

```powershell
@{
Server = @{
Expand Down Expand Up @@ -158,6 +164,7 @@ The steps to attach to the Pode process are as follows:
1. In a PowerShell console, start the above Pode server.

2. In a browser or a new PowerShell console, invoke the `[GET] http://localhost:8080` Route to hit the breakpoint.

```powershell
Invoke-RestMethod -Uri 'http://localhost:8080/'
```
Expand All @@ -175,8 +182,6 @@ The steps to attach to the Pode process are as follows:

6. When you are done debugging the current request, hit the `d` key.



## Managing Runspace Names

### Internal Runspace Naming
Expand Down Expand Up @@ -209,7 +214,7 @@ Set-PodeCurrentRunspaceName -Name 'Custom Runspace Name'

This cmdlet sets a custom name for the runspace, making it easier to track during execution.

#### Example
#### Example: Setting a Custom Runspace Name in a Task

Here’s an example that demonstrates how to set a custom runspace name in a Pode task:

Expand All @@ -235,7 +240,7 @@ Get-PodeCurrentRunspaceName

This cmdlet returns the name of the current runspace, allowing for easier tracking and management in complex scenarios with multiple concurrent runspaces.

#### Example
#### Example: Outputting the Runspace Name in a Schedule

Here’s an example that uses `Get-PodeCurrentRunspaceName` to output the runspace name during the execution of a schedule:

Expand All @@ -246,3 +251,149 @@ Add-PodeSchedule -Name 'TestSchedule' -Cron '@hourly' -ScriptBlock {
```

In this example, the schedule outputs the name of the runspace executing the script block every hour. This can be useful for logging and monitoring purposes when dealing with multiple schedules or tasks.

## Memory Dump for Diagnostics

Pode provides a powerful memory dump feature to capture detailed information during critical failures or fatal exceptions. This feature, triggered by the `Invoke-PodeDump` function, captures the state of your application, including memory usage, runspace details, variables, and stack traces. You can configure the dump format, enable or disable it, and specify the save location. By default, Pode saves the dump in JSON format, but you can also choose from other supported formats.

### Configuring Dump Defaults

To set up default options for the memory dump feature in Pode, you can configure them in the `server.psd1` configuration file. Under the `Server.Debug.Dump` section, you can specify whether to enable the dump, the default format, and the save path. Below is an example configuration for setting up defaults:

```powershell
@{
Server = @{
Debug = @{
Dump = @{
Enable = $true
Format = 'Yaml' # Options: 'json', 'clixml', 'txt', 'bin', 'yaml'
Path = './Dump' # Path to save the dump files
MaxDepth = 6
}
}
}
}
```

- **Enable**: Boolean value to enable or disable the memory dump feature.
- **Format**: Specifies the default format for the dump file. Supported formats are `json`, `clixml`, `txt`, `bin`, and `yaml`.
- **Path**: Specifies the directory where the dump file will be saved. If the directory does not exist, it will be created.
- **MaxDepth**: Specifies the maximum depth to traverse when collecting information.

### Overriding Default Settings at Runtime

The `Invoke-PodeDump` function allows you to override these defaults at runtime by passing parameters to specify the format and path. This can be useful for debugging in specific cases without altering the default configuration.

```powershell
try {
# Simulate a critical error
throw [System.OutOfMemoryException] "Simulated out of memory error"
}
catch {
# Capture the dump with custom options
Invoke-PodeDump -ErrorRecord $_ -Format 'clixml' -Path 'C:\CustomDump'
}
```

In this example:

- The memory dump is saved in CLIXML format instead of the default.
- The dump file is saved in the specified directory (`C:\CustomDump`) instead of the default path.

### Using the Dump Feature

To use the dump feature effectively in your Pode server, you may want to include it in specific places within your code to capture state information when critical errors occur.

Example :

```powershell
Start-PodeServer -EnableBreakpoints {
Add-PodeEndpoint -Address localhost -Port 8080 -Protocol Http

Add-PodeRoute -Method Get -Path '/' -ScriptBlock {
try {
# Simulate an operation that could fail
$processes = Get-Process -ErrorAction Stop
Write-PodeJsonResponse -Value @{ Process = $processes[0] }
}
catch {
# Invoke a memory dump when a critical error occurs
$_ | Invoke-PodeDump
}
}
}
```

In this setup, if an error occurs in the route, `Invoke-PodeDump` is called, capturing the current state.

### Dump File Content

When a dump file is created using the `Invoke-PodeDump` function, it captures detailed information about the state of the Pode application. The captured information provides valuable insights into the internal state at the time of the error or diagnostic event. Below is a description of the content included in the dump file:

#### **1. Timestamp**

- The exact date and time when the dump was generated.
- Format: ISO8601 (e.g., `2024-12-01T12:34:56`).

#### **2. Memory Details**

- Provides information about the memory usage of the Pode application at the time of the dump.
- Captures metrics such as total memory allocated and other relevant details to analyze memory-related issues.

#### **3. Script Context**

- Contains details about the script execution context at the time of the dump.
- Includes information such as the script path, parameters passed, and the execution environment.

#### **4. Stack Trace**

- A snapshot of the call stack, showing the sequence of function calls leading up to the dump.
- Useful for identifying the source of an error or pinpointing the exact location in the code where the issue occurred.

#### **5. Exception Details**

- Contains information about any exceptions that triggered the dump.
- Includes the exception type, message, and inner exception details (if available).

#### **6. Scoped Variables**

- Lists all variables currently in scope, including their names and values.
- This information is useful for debugging issues related to variable states.

#### **7. Runspace Pool Details**

- Describes the state and configuration of each runspace pool within the Pode application.
- Captures the following details for each runspace pool:
- **Pool Name**: The name assigned to the runspace pool.
- **State**: The current state of the pool (e.g., `Opened`, `Closing`).
- **Result**: The result of the last operation performed on the pool.
- **Instance ID**: A unique identifier for the runspace pool instance.
- **Is Disposed**: Indicates whether the pool has been disposed.
- **Runspace Pool State Info**: Detailed state information about the runspace pool.
- **Initial Session State**: The initial session state used to configure the pool.
- **Cleanup Interval**: The interval used to clean up the pool.
- **Availability**: The availability of the runspace pool for handling requests.
- **Thread Options**: The threading options configured for the pool.

#### **8. Runspace Details**

- Provides detailed information about each individual runspace within the application.
- Captures the following information for each runspace:
- **Runspace ID**: A unique identifier for the runspace.
- **Name**: The name of the runspace, often reflecting its purpose (e.g., `Pode_Web_Listener_1`).
- **Scoped Variables**: A detailed list of variables scoped to this runspace, captured using the Pode debugger.
- **Initial Session State**: The initial session state of the runspace.
- **Runspace State Info**: Detailed state information about the runspace, such as `Opened`, `Busy`, or `Disconnected`.

### Dumping Options and Best Practices
mdaneri marked this conversation as resolved.
Show resolved Hide resolved

- **Enabling Dump in Production**: Enabling the dump in production can be valuable for diagnosing unexpected failures. However, use it selectively, especially if you are using binary or CLIXML formats, as they can produce large files.
- **Specifying Formats**: Choose a format based on your needs:
- **JSON** and **YAML** are human-readable and suitable for quick inspection.
- **CLIXML** is ideal for preserving object structures, especially when analyzing PowerShell-specific data.
- **Binary** is compact and suitable for raw state captures but requires deserialization for inspection.
- **Setting the Path**: Use a dedicated folder for dump files (e.g., `./Dump`) to keep diagnostic files organized. The default path in the configuration can be overridden at runtime if needed.

With these configurations and usage practices, the memory dump feature in Pode can provide a powerful tool for diagnostics and debugging, capturing critical state information at the time of failure.


2 changes: 1 addition & 1 deletion docs/Getting-Started/FirstApp.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The following steps will run you through creating your first Pode app, and give

* Run `pode init` in the console, this will create a basic `package.json` file for you - see the [`CLI`](../CLI) reference for more information.

* The `init` action will ask for some input, leave everything as default (just press enter).
* The `init` action will ask for some input, leave everything as default (just press enter).

```powershell
PS> pode init
Expand Down
53 changes: 53 additions & 0 deletions docs/Tutorials/ServerOperation/Suspending/Overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Overview

In addition to restarting, Pode provides a way to temporarily **suspend** and **resume** the server, allowing you to pause all activities and connections without completely stopping the server. This can be especially useful for debugging, troubleshooting, or performing maintenance tasks where you don’t want to fully restart the server.

## Suspending

To suspend a running Pode server, use the `Suspend-PodeServer` function. This function will pause all active server runspaces, effectively putting the server into a suspended state. Here’s how to do it:

1. **Run the Suspension Command**:
- Simply call `Suspend-PodeServer` from within your Pode environment or script.

```powershell
Suspend-PodeServer -Timeout 60
```

The `-Timeout` parameter specifies how long the function should wait (in seconds) for each runspace to be fully suspended. This is optional, with a default timeout of 30 seconds.

2. **Suspension Process**:
- When you run `Suspend-PodeServer`, Pode will:
- Pause all runspaces associated with the server, putting them into a debug state.
- Trigger a "Suspend" event to signify that the server is paused.
- Update the server’s status to reflect that it is now suspended.

3. **Outcome**:
- After suspension, all server operations are halted, and the server will not respond to incoming requests until it is resumed.

## Resuming

Once you’ve completed any tasks or troubleshooting, you can resume the server using `Resume-PodeServer`. This will restore the Pode server to its normal operational state:

1. **Run the Resume Command**:
- Call `Resume-PodeServer` to bring the server back online.

```powershell
Resume-PodeServer
```

2. **Resumption Process**:
- When `Resume-PodeServer` is executed, Pode will:
- Restore all paused runspaces back to their active states.
- Trigger a "Resume" event, marking the server as active again.
- Clear the console, providing a refreshed view of the server status.

3. **Outcome**:
- The server resumes normal operations and can now handle incoming requests again.

## When to Use Suspend and Resume

These functions are particularly useful when:

- **Debugging**: If you encounter an issue, you can pause the server to inspect state or troubleshoot without a full restart.
- **Maintenance**: Suspend the server briefly during configuration changes, and then resume when ready.
- **Performance Management**: Temporarily pause during high load or for throttling purposes if required by your application logic.
2 changes: 1 addition & 1 deletion docs/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ Date: 24th May 2020
### Enhancements
* #533: Support on states for inclusion/exlcusions when saving, and scopes on states
* #538: Support to batch log items together before sending them off to be recorded
* #540: Adds a Ctrl+B shortcutto open the server in the default browser
* #540: Adds a Ctrl+B shortcut to open the server in the default browser
* #542: Add new switch to help toggling of Status Page exception message
* #548: Adds new `Get-PodeSchedule` and `Get-PodeTimer` functions
* #549: Support for calculating a schedule's next trigger datetime
Expand Down
2 changes: 1 addition & 1 deletion examples/PetStore/data/PetData.json
Original file line number Diff line number Diff line change
Expand Up @@ -360,4 +360,4 @@
"Users"
]
}
}
}
12 changes: 12 additions & 0 deletions examples/PetStore/server.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,22 @@
Server = @{
Timeout = 60
BodySize = 100MB
Debug = @{
Breakpoints = @{
Enable = $true
}
Dump = @{
Enabled = $true
Format = 'json'
Path = './Dump'
MaxDepth = 6
}
}
}
Web = @{
OpenApi = @{
DefaultDefinitionTag = 'v3.0.3'
}
}

}
2 changes: 2 additions & 0 deletions examples/Tasks.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ Start-PodeServer {
Add-PodeTask -Name 'Test2' -ScriptBlock {
param($value)
Start-Sleep -Seconds 10
"a $($value) is comming" | Out-Default
Start-Sleep -Seconds 100
"a $($value) is never late, it arrives exactly when it means to" | Out-Default
}

Expand Down
Loading
Loading