|
1 | 1 | import { getCurrentHub } from '@sentry/core';
|
2 |
| -import { Event, EventProcessor, Integration } from '@sentry/types'; |
| 2 | +import { Event, EventProcessor, Integration, StackFrame } from '@sentry/types'; |
3 | 3 | import { addContextToFrame } from '@sentry/utils';
|
4 | 4 | import { readFile } from 'fs';
|
5 | 5 | import { LRUMap } from 'lru_map';
|
@@ -73,68 +73,56 @@ export class ContextLines implements Integration {
|
73 | 73 |
|
74 | 74 | /** Processes an event and adds context lines */
|
75 | 75 | public async addSourceContext(event: Event, contextLines: number): Promise<Event> {
|
76 |
| - const frames = event.exception?.values?.[0].stacktrace?.frames; |
77 |
| - |
78 |
| - if (frames && contextLines > 0) { |
79 |
| - const filenames: Set<string> = new Set(); |
80 |
| - |
81 |
| - for (const frame of frames) { |
82 |
| - if (frame.filename) { |
83 |
| - filenames.add(frame.filename); |
84 |
| - } |
| 76 | + if (contextLines > 0 && event.exception?.values) { |
| 77 | + for (const exception of event.exception.values) { |
| 78 | + await this._addSourceContextToFrames(exception.stacktrace?.frames, contextLines); |
85 | 79 | }
|
| 80 | + } |
86 | 81 |
|
87 |
| - const sourceFiles = await readSourceFiles(filenames); |
| 82 | + return event; |
| 83 | + } |
88 | 84 |
|
| 85 | + /** Adds context lines to frames */ |
| 86 | + public async _addSourceContextToFrames(frames: StackFrame[] | undefined, contextLines: number): Promise<void> { |
| 87 | + if (frames) { |
89 | 88 | for (const frame of frames) {
|
90 |
| - if (frame.filename && sourceFiles[frame.filename]) { |
91 |
| - try { |
92 |
| - const lines = (sourceFiles[frame.filename] as string).split('\n'); |
93 |
| - addContextToFrame(lines, frame, contextLines); |
94 |
| - } catch (e) { |
95 |
| - // anomaly, being defensive in case |
96 |
| - // unlikely to ever happen in practice but can definitely happen in theory |
| 89 | + if (frame.filename) { |
| 90 | + const sourceFile = await _readSourceFile(frame.filename); |
| 91 | + |
| 92 | + if (sourceFile) { |
| 93 | + try { |
| 94 | + const lines = sourceFile.split('\n'); |
| 95 | + addContextToFrame(lines, frame, contextLines); |
| 96 | + } catch (e) { |
| 97 | + // anomaly, being defensive in case |
| 98 | + // unlikely to ever happen in practice but can definitely happen in theory |
| 99 | + } |
97 | 100 | }
|
98 | 101 | }
|
99 | 102 | }
|
100 | 103 | }
|
101 |
| - |
102 |
| - return event; |
103 | 104 | }
|
104 | 105 | }
|
105 | 106 |
|
106 | 107 | /**
|
107 |
| - * This function reads file contents and caches them in a global LRU cache. |
| 108 | + * Reads file contents and caches them in a global LRU cache. |
108 | 109 | *
|
109 |
| - * @param filenames Array of filepaths to read content from. |
| 110 | + * @param filename filepath to read content from. |
110 | 111 | */
|
111 |
| -async function readSourceFiles(filenames: Set<string>): Promise<Record<string, string | null>> { |
112 |
| - const sourceFiles: Record<string, string | null> = {}; |
113 |
| - |
114 |
| - for (const filename of filenames) { |
115 |
| - const cachedFile = FILE_CONTENT_CACHE.get(filename); |
116 |
| - // We have a cache hit |
117 |
| - if (cachedFile !== undefined) { |
118 |
| - // If stored value is null, it means that we already tried, but couldn't read the content of the file. Skip. |
119 |
| - if (cachedFile === null) { |
120 |
| - continue; |
121 |
| - } |
122 |
| - |
123 |
| - // Otherwise content is there, so reuse cached value. |
124 |
| - sourceFiles[filename] = cachedFile; |
125 |
| - continue; |
126 |
| - } |
127 |
| - |
128 |
| - let content: string | null = null; |
129 |
| - try { |
130 |
| - content = await readTextFileAsync(filename); |
131 |
| - } catch (_) { |
132 |
| - // |
133 |
| - } |
| 112 | +async function _readSourceFile(filename: string): Promise<string | null> { |
| 113 | + const cachedFile = FILE_CONTENT_CACHE.get(filename); |
| 114 | + // We have a cache hit |
| 115 | + if (cachedFile !== undefined) { |
| 116 | + return cachedFile; |
| 117 | + } |
134 | 118 |
|
135 |
| - FILE_CONTENT_CACHE.set(filename, content); |
136 |
| - sourceFiles[filename] = content; |
| 119 | + let content: string | null = null; |
| 120 | + try { |
| 121 | + content = await readTextFileAsync(filename); |
| 122 | + } catch (_) { |
| 123 | + // |
137 | 124 | }
|
138 | 125 |
|
139 |
| - return sourceFiles; |
| 126 | + FILE_CONTENT_CACHE.set(filename, content); |
| 127 | + return content; |
140 | 128 | }
|
0 commit comments