Skip to content

feat: PowerShell support #66586

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

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Sentry is a developer-first error tracking and performance monitoring platform t
- [Elixir](https://github.com/getsentry/sentry-elixir)
- [Unity](https://github.com/getsentry/sentry-unity)
- [Unreal Engine](https://github.com/getsentry/sentry-unreal)
- [PowerShell](https://github.com/getsentry/sentry-powershell)

# Resources

Expand Down
1 change: 1 addition & 0 deletions bin/extension_language_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"lua",
"ocaml",
"hcl",
"powershell",
]

EXTENSION_LANGUAGE_MAP: dict[str, str] = {}
Expand Down
12 changes: 12 additions & 0 deletions fixtures/integration-docs/_platforms.json
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,18 @@
],
"id": "mock",
"name": "Mock"
},
{
"integrations": [
{
"link": "https://docs.getsentry.com/platforms/powershell/",
"type": "language",
"id": "powershell",
"name": "PowerShell"
}
],
"id": "powershell",
"name": "PowerShell"
}
]
}
6 changes: 6 additions & 0 deletions fixtures/integration-docs/powershell.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"html": "<div class=\"section\" id=\"installation\">\n<h2>Installation</h2>\n<p>A <a class=\"reference external\" href=\"https://www.powershellgallery.com/packages/Sentry/\">PowerShell module</a> is available for Sentry.</p>\n</div>\n",
"link": "https://docs.getsentry.com/platforms/powrshell/",
"id": "powershell",
"name": "PowerShell"
}
3 changes: 3 additions & 0 deletions src/sentry/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,9 @@ def from_str(cls, string: str) -> int:
"pm": "perl",
"psgi": "perl",
"t": "perl",
"ps1": "powershell",
"psd1": "powershell",
"psm1": "powershell",
"py": "python",
"gyp": "python",
"gypi": "python",
Expand Down
2 changes: 1 addition & 1 deletion src/sentry/issues/event.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@
}
},
"platform": {
"description": " Platform identifier of this event (defaults to \"other\").\n\n A string representing the platform the SDK is submitting from. This will be used by the\n Sentry interface to customize various components in the interface, but also to enter or\n skip stacktrace processing.\n\n Acceptable values are: `as3`, `c`, `cfml`, `cocoa`, `csharp`, `elixir`, `haskell`, `go`,\n `groovy`, `java`, `javascript`, `native`, `node`, `objc`, `other`, `perl`, `php`, `python`,\n `ruby`",
"description": " Platform identifier of this event (defaults to \"other\").\n\n A string representing the platform the SDK is submitting from. This will be used by the\n Sentry interface to customize various components in the interface, but also to enter or\n skip stacktrace processing.\n\n Acceptable values are: `as3`, `c`, `cfml`, `cocoa`, `csharp`, `elixir`, `haskell`, `go`,\n `groovy`, `java`, `javascript`, `native`, `node`, `objc`, `other`, `perl`, `php`, `python`,\n `powershell`, `ruby`",
"type": "string"
},
"project_id": {
Expand Down
1 change: 1 addition & 0 deletions src/sentry/models/featureadoption.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
manager.add(12, "cfml", "CFML", "language")
manager.add(13, "groovy", "Groovy", "language")
manager.add(14, "csp", "CSP Reports", "language")
manager.add(11, "powershell", "PowerShell", "language")

# Frameworks
manager.add(20, "flask", "Flask", "integration", prerequisite=["python"])
Expand Down
1 change: 1 addition & 0 deletions src/sentry/models/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
"php",
"php-laravel",
"php-symfony",
"powershell",
"python",
"python-aiohttp",
"python-asgi",
Expand Down
1 change: 1 addition & 0 deletions src/sentry/utils/platform_categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
"php-monolog",
"php-symfony",
"php",
"powershell",
"python",
"python-aiohttp",
"python-asgi",
Expand Down
1 change: 1 addition & 0 deletions src/sentry/utils/tag_normalization.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"sentry.objc",
"sentry.perl",
"sentry.php",
"sentry.powershell",
"sentry.python",
"sentry.ruby",
"sentry.rust",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const BLOCK_COMMENT_SYNTAX_BY_LANGUAGE: Record<string, BlockCommentSyntax[]> = {
julia: [{start: '#=', end: '=#'}],
lua: [{start: '--[[', end: ']]'}],
perl: [{start: {example: '=comment', search: /^\s*?=\S+/m}, end: '=cut'}],
powershell: [{start: '<#', end: '#>'}],
python: [
{start: '"""', end: '"""'},
{start: "'''", end: "'''"},
Expand Down
1 change: 1 addition & 0 deletions static/app/data/platformCategories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export const backend: PlatformKey[] = [
'php-laravel',
'php-monolog',
'php-symfony',
'powershell',
'python',
'python-aiohttp',
'python-asgi',
Expand Down
1 change: 1 addition & 0 deletions static/app/data/platformPickerCategories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ const server: Set<PlatformKey> = new Set([
'php',
'php-laravel',
'php-symfony',
'powershell',
'python',
'python-aiohttp',
'python-asgi',
Expand Down
7 changes: 7 additions & 0 deletions static/app/data/platforms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,13 @@ export const platforms: PlatformIntegration[] = [
language: 'php',
link: 'https://docs.sentry.io/platforms/php/guides/symfony/',
},
{
id: 'powershell',
name: 'PowerShell',
type: 'language',
language: 'powershell',
link: 'https://docs.sentry.io/platforms/powershell/',
},
{
id: 'python',
name: 'Python',
Expand Down
35 changes: 35 additions & 0 deletions static/app/gettingStartedDocs/powershell/powershell.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
import {screen} from 'sentry-test/reactTestingLibrary';
import {textWithMarkupMatcher} from 'sentry-test/utils';

import docs from './powershell';

describe('powershell onboarding docs', function () {
it('renders docs correctly', async function () {
renderWithOnboardingLayout(docs, {
releaseRegistry: {
'sentry.powershell': {
version: '1.99.9',
},
},
});

// Renders main headings
expect(screen.getByRole('heading', {name: 'Install'})).toBeInTheDocument();
expect(screen.getByRole('heading', {name: 'Configure SDK'})).toBeInTheDocument();
expect(screen.getByRole('heading', {name: 'Verify'})).toBeInTheDocument();
expect(
screen.getByRole('heading', {name: 'Performance Monitoring'})
).toBeInTheDocument();
expect(screen.getByRole('heading', {name: 'Samples'})).toBeInTheDocument();

// Renders SDK version from registry
expect(
await screen.findByText(
textWithMarkupMatcher(
/Install-Module -Name Sentry -Repository PSGallery -RequiredVersion 1\.99\.9/
)
)
).toBeInTheDocument();
});
});
207 changes: 207 additions & 0 deletions static/app/gettingStartedDocs/powershell/powershell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import ExternalLink from 'sentry/components/links/externalLink';
import List from 'sentry/components/list';
import ListItem from 'sentry/components/list/listItem';
import altCrashReportCallout from 'sentry/components/onboarding/gettingStartedDoc/feedback/altCrashReportCallout';
import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
import type {
Docs,
DocsParams,
OnboardingConfig,
} from 'sentry/components/onboarding/gettingStartedDoc/types';
import {
getCrashReportApiIntroduction,
getCrashReportInstallDescription,
} from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
import {t, tct} from 'sentry/locale';
import {getPackageVersion} from 'sentry/utils/gettingStartedDocs/getPackageVersion';

type Params = DocsParams;

const getConfigureSnippet = (params: Params) => `
# You may need to import the module if you've just installed it.
Import-Module Sentry

# Start the Sentry SDK with the default options.
Start-Sentry {
# A Sentry Data Source Name (DSN) is required.
# See https://docs.sentry.io/product/sentry-basics/dsn-explainer/
# You can set it in the SENTRY_DSN environment variable, or you can set it in code here.
$_.Dsn = '${params.dsn}'

# When debug is enabled, the Sentry client will emit detailed debugging information to the console.
# This might be helpful, or might interfere with the normal operation of your application.
# We enable it here for demonstration purposes when first trying Sentry.
# You shouldn't do this in your applications unless you're troubleshooting issues with Sentry.
# Alternatively, you can pass \`-Debug\` to the \`Start-Sentry\` command.
$_.Debug = $true

# This option is recommended. It enables Sentry's "Release Health" feature.
$_.AutoSessionTracking = $true

# This option will enable Sentry's tracing features. You still need to start transactions and spans.
# Example sample rate for your transactions: captures 10% of transactions
$_.TracesSampleRate = 0.1
}`;

const getPerformanceMonitoringSnippet = () => `
# Transaction can be started by providing, at minimum, the name and the operation
$transaction = Start-SentryTransaction 'test-transaction-name' 'test-transaction-operation'

# Transactions can have child spans (and those spans can have child spans as well)
$span = $transaction.StartChild("test-child-operation")
# ...
# (Perform the operation represented by the span/transaction)
# ...
$span.Finish() # Mark the span as finished

$span = $transaction.StartChild("another-span")
# ...
$span.Finish()

$transaction.Finish() # Mark the transaction as finished and send it to Sentry`;

const onboarding: OnboardingConfig = {
introduction: () =>
tct(
'Sentry for PowerShell module supports PowerShell 7.2+ on Windows, macOS, and Linux as well as Windows PowerShell 5.1+.',
{
strong: <strong />,
link: <ExternalLink href="https://docs.sentry.io/platforms/powershell/" />,
}
),
install: params => [
{
type: StepType.INSTALL,
description: tct('Install the module:', {
strong: <strong />,
}),
configurations: [
{
partialLoading: params.sourcePackageRegistries.isLoading,
code: [
{
language: 'powershell',
label: 'Install Module',
value: 'powershellget',
code: `Install-Module -Name Sentry -Repository PSGallery -RequiredVersion ${getPackageVersion(params, 'sentry.powershell', '1.0.0')} -Force`,
},
],
},
],
},
],
configure: params => [
{
type: StepType.CONFIGURE,
description: tct('Initialize the SDK as early as possible.', {
sentrySdkCode: <code />,
programCode: <code />,
}),
configurations: [
{
language: 'powershell',
code: getConfigureSnippet(params),
},
],
},
],
verify: () => [
{
type: StepType.VERIFY,
description: t('Verify Sentry is correctly configured by sending a message:'),
configurations: [
{
language: 'powershell',
code: '"Something went wrong" | Out-Sentry',
},
],
},
{
title: t('Performance Monitoring'),
description: t(
'You can measure the performance of your code by capturing transactions and spans.'
),
configurations: [
{
language: 'powershell',
code: getPerformanceMonitoringSnippet(),
},
],
additionalInfo: tct(
'Check out [link:the documentation] to learn more about the API and instrumentations.',
{
link: (
<ExternalLink href="https://docs.sentry.io/platforms/powershell/performance/instrumentation/" />
),
}
),
},
{
title: t('Samples'),
description: t('You can find sample usage of the SDK:'),
configurations: [
{
description: (
<List symbol="bullet">
<ListItem>
{tct('[link:Samples in the [code:powershell] SDK repository]', {
link: (
<ExternalLink href="https://github.com/getsentry/sentry-powershell/tree/main/samples" />
),
code: <code />,
strong: <strong />,
})}
</ListItem>
<ListItem>
{tct(
'[link:Many more samples in the [code:dotnet] SDK repository] [strong:(C#)]',
{
link: (
<ExternalLink href="https://github.com/getsentry/sentry-dotnet/tree/main/samples" />
),
code: <code />,
strong: <strong />,
}
)}
</ListItem>
</List>
),
},
],
},
],
};

export const powershellFeedbackOnboarding: OnboardingConfig = {
introduction: () => getCrashReportApiIntroduction(),
install: () => [
{
type: StepType.INSTALL,
description: getCrashReportInstallDescription(),
configurations: [
{
code: [
{
label: 'PowerShell',
value: 'powershell',
language: 'powershell',
code: `$eventId = "An event that will receive user feedback." | Out-Sentry
[Sentry.SentrySdk]::CaptureUserFeedback($eventId, "user@example.com", "It broke.", "The User")`,
},
],
},
],
additionalInfo: altCrashReportCallout(),
},
],
configure: () => [],
verify: () => [],
nextSteps: () => [],
};

const docs: Docs = {
onboarding,
feedbackOnboardingCrashApi: powershellFeedbackOnboarding,
};

export default docs;
1 change: 1 addition & 0 deletions static/app/types/project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ export type PlatformKey =
| 'php-monolog'
| 'php-symfony'
| 'php-symfony2'
| 'powershell'
| 'python'
| 'python-aiohttp'
| 'python-asgi'
Expand Down
2 changes: 2 additions & 0 deletions static/app/utils/docs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const platforms = [
'node',
'perl',
'php',
'powershell',
'python',
'react-native',
'ruby',
Expand All @@ -32,6 +33,7 @@ const performancePlatforms: DocPlatform[] = [
'javascript',
'node',
'php',
'powershell',
'python',
'react-native',
'ruby',
Expand Down
Loading