add stacktrace support for php (#149122)

Closes https://github.com/elastic/kibana/issues/80949

## Summary

This PR adds support for displaying Language specific Stacktrace for
PHP.

## PHP

**Before changes -**

<img width="1681" alt="image"
src="https://user-images.githubusercontent.com/7416358/213389631-f8dd808d-3a38-4663-b2dc-c777d87795a6.png">

**After changes the Stackttrace will look like this**

<img width="1681" alt="image"
src="https://user-images.githubusercontent.com/7416358/213192049-e4bc56b0-49ba-40a3-85c1-218be917ba71.png">
This commit is contained in:
Achyut Jhunjhunwala 2023-01-25 12:13:36 +01:00 committed by GitHub
parent 5ec4bde603
commit 7f2bf935ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 94 additions and 13 deletions

View file

@ -12,13 +12,15 @@ import { FrameHeading } from './frame_heading';
function getRenderedStackframeText(
stackframe: Stackframe,
codeLanguage: string
codeLanguage: string,
idx: string
) {
const result = renderWithTheme(
<FrameHeading
codeLanguage={codeLanguage}
isLibraryFrame={false}
stackframe={stackframe}
idx={idx}
/>
);
@ -38,7 +40,8 @@ describe('FrameHeading', () => {
function: 'Main.func2',
module: 'main',
},
'go'
'go',
'0'
)
).toEqual('main.go in Main.func2 at line 196');
});
@ -57,7 +60,8 @@ describe('FrameHeading', () => {
module: 'org.apache.catalina.connector',
function: 'flushByteBuffer',
},
'Java'
'Java',
'0'
)
).toEqual(
'at org.apache.catalina.connector.OutputBuffer.flushByteBuffer(OutputBuffer.java:825)'
@ -82,7 +86,8 @@ describe('FrameHeading', () => {
'opbeans-dotnet, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null',
function: 'Get',
},
'C#'
'C#',
'0'
)
).toEqual(
'OpbeansDotnet.Controllers.CustomersController in Get in /src/opbeans-dotnet/Controllers/CustomersController.cs at line 23'
@ -103,7 +108,8 @@ describe('FrameHeading', () => {
module:
'Microsoft.EntityFrameworkCore, Version=2.2.6.0, Culture=neutral, PublicKeyToken=adb9793829ddae60',
},
'C#'
'C#',
'0'
)
).toEqual(
'Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider+ResultEnumerable`1 in GetEnumerator'
@ -124,7 +130,8 @@ describe('FrameHeading', () => {
line: { number: 120 },
function: 'callbackTrampoline',
},
'javascript'
'javascript',
'0'
)
).toEqual('at callbackTrampoline (internal/async_hooks.js:120)');
});
@ -142,7 +149,8 @@ describe('FrameHeading', () => {
line: { number: 205 },
function: 'onStreamRead',
},
'javascript'
'javascript',
'0'
)
).toEqual(
'at TCPConnectWrap.onStreamRead (internal/stream_base_commons.js:205)'
@ -161,7 +169,8 @@ describe('FrameHeading', () => {
abs_path: 'internal/stream_base_commons.js',
line: { number: 205 },
},
'javascript'
'javascript',
'0'
)
).toEqual('at (internal/stream_base_commons.js:205)');
});
@ -195,7 +204,8 @@ describe('FrameHeading', () => {
},
vars: { request: "<WSGIRequest: POST '/api/orders'>" },
},
'python'
'python',
'0'
)
).toEqual('opbeans/views.py in orders at line 190');
});
@ -220,7 +230,8 @@ describe('FrameHeading', () => {
post: [' end\n', ' end\n'],
},
},
'ruby'
'ruby',
'0'
)
).toEqual("api/customers_controller.rb:15 in `show'");
});
@ -243,11 +254,33 @@ describe('FrameHeading', () => {
line: { number: 319, column: 3842 },
function: 'unstable_runWithPriority',
},
'javascript'
'javascript',
'0'
)
).toEqual(
'at unstable_runWithPriority (static/js/main.616809fb.js:319:3842)'
);
});
});
describe('with a PHP stackframe', () => {
it('renders', () => {
expect(
getRenderedStackframeText(
{
library_frame: false,
exclude_from_grouping: false,
filename:
'/app/vendor/laravel/framework/src/Illuminate/Database/Connectors/PostgresConnector.php',
line: { number: 87 },
function: 'PDOStatement->execute()',
},
'php',
'1'
)
).toEqual(
'#1 PDOStatement->execute() called at [/app/vendor/laravel/framework/src/Illuminate/Database/Connectors/PostgresConnector.php:87]'
);
});
});
});

View file

@ -15,6 +15,7 @@ import {
JavaFrameHeadingRenderer,
JavaScriptFrameHeadingRenderer,
RubyFrameHeadingRenderer,
PhpFrameHeadingRenderer,
} from './frame_heading_renderers';
const FileDetails = euiStyled.div`
@ -39,9 +40,15 @@ interface Props {
codeLanguage?: string;
stackframe: Stackframe;
isLibraryFrame: boolean;
idx: string;
}
function FrameHeading({ codeLanguage, stackframe, isLibraryFrame }: Props) {
function FrameHeading({
codeLanguage,
stackframe,
isLibraryFrame,
idx,
}: Props) {
const FileDetail: ComponentType = isLibraryFrame
? LibraryFrameFileDetail
: AppFrameFileDetail;
@ -59,6 +66,9 @@ function FrameHeading({ codeLanguage, stackframe, isLibraryFrame }: Props) {
case 'ruby':
Renderer = RubyFrameHeadingRenderer;
break;
case 'php':
Renderer = PhpFrameHeadingRenderer;
break;
default:
Renderer = DefaultFrameHeadingRenderer;
break;
@ -66,7 +76,11 @@ function FrameHeading({ codeLanguage, stackframe, isLibraryFrame }: Props) {
return (
<FileDetails data-test-subj="FrameHeading">
<Renderer fileDetailComponent={FileDetail} stackframe={stackframe} />
<Renderer
fileDetailComponent={FileDetail}
stackframe={stackframe}
idx={idx}
/>
</FileDetails>
);
}

View file

@ -11,6 +11,7 @@ import { Stackframe } from '../../../../../typings/es_schemas/raw/fields/stackfr
export interface FrameHeadingRendererProps {
fileDetailComponent: ComponentType;
stackframe: Stackframe;
idx?: string;
}
export { CSharpFrameHeadingRenderer } from './c_sharp_frame_heading_renderer';
@ -18,3 +19,4 @@ export { DefaultFrameHeadingRenderer } from './default_frame_heading_renderer';
export { JavaFrameHeadingRenderer } from './java_frame_heading_renderer';
export { JavaScriptFrameHeadingRenderer } from './java_script_frame_heading_renderer';
export { RubyFrameHeadingRenderer } from './ruby_frame_heading_renderer';
export { PhpFrameHeadingRenderer } from './php_frame_heading_renderer';

View file

@ -0,0 +1,30 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import { FrameHeadingRendererProps } from '.';
export function PhpFrameHeadingRenderer({
stackframe,
fileDetailComponent: FileDetail,
idx,
}: FrameHeadingRendererProps) {
const { filename, function: fn } = stackframe;
const lineNumber = stackframe.line?.number ?? 0;
const formattedIndex = idx?.split('-')[0];
return (
<>
<FileDetail>{formattedIndex && `#${formattedIndex} `}</FileDetail>
<FileDetail>{fn && `${fn}`}</FileDetail>
{' called at '}
<FileDetail>
[{filename}:{lineNumber}]
</FileDetail>
</>
);
}

View file

@ -55,6 +55,7 @@ export function Stackframe({
codeLanguage={codeLanguage}
stackframe={stackframe}
isLibraryFrame={isLibraryFrame}
idx={id}
/>
</NoContextFrameHeadingWrapper>
);
@ -67,6 +68,7 @@ export function Stackframe({
codeLanguage={codeLanguage}
stackframe={stackframe}
isLibraryFrame={isLibraryFrame}
idx={id}
/>
}
id={id}