@@ -3,7 +3,7 @@ import { addContextToFrame } from '@sentry/utils';
3
3
import { readFile } from 'fs' ;
4
4
import { LRUMap } from 'lru_map' ;
5
5
6
- const FILE_CONTENT_CACHE = new LRUMap < string , string | null > ( 100 ) ;
6
+ const FILE_CONTENT_CACHE = new LRUMap < string , string [ ] | null > ( 100 ) ;
7
7
const DEFAULT_LINES_OF_CONTEXT = 7 ;
8
8
9
9
// TODO: Replace with promisify when minimum supported node >= v8
@@ -65,7 +65,7 @@ export class ContextLines implements Integration {
65
65
// keep a lookup map of which files we've already enqueued to read,
66
66
// so we don't enqueue the same file multiple times which would cause multiple i/o reads
67
67
const enqueuedReadSourceFileTasks : Record < string , number > = { } ;
68
- const readSourceFileTasks : Promise < string | null > [ ] = [ ] ;
68
+ const readSourceFileTasks : Promise < string [ ] | null > [ ] = [ ] ;
69
69
70
70
if ( this . _contextLines > 0 && event . exception ?. values ) {
71
71
for ( const exception of event . exception . values ) {
@@ -102,8 +102,8 @@ export class ContextLines implements Integration {
102
102
// and attempt to add source context to frames.
103
103
if ( this . _contextLines > 0 && event . exception ?. values ) {
104
104
for ( const exception of event . exception . values ) {
105
- if ( exception . stacktrace ? .frames ) {
106
- this . addSourceContextToFrames ( exception . stacktrace . frames ) ;
105
+ if ( exception . stacktrace && exception . stacktrace . frames ) {
106
+ await this . addSourceContextToFrames ( exception . stacktrace . frames ) ;
107
107
}
108
108
}
109
109
}
@@ -116,12 +116,11 @@ export class ContextLines implements Integration {
116
116
for ( const frame of frames ) {
117
117
// Only add context if we have a filename and it hasn't already been added
118
118
if ( frame . filename && frame . context_line === undefined ) {
119
- const sourceFile = FILE_CONTENT_CACHE . get ( frame . filename ) ;
119
+ const sourceFileLines = FILE_CONTENT_CACHE . get ( frame . filename ) ;
120
120
121
- if ( sourceFile ) {
121
+ if ( sourceFileLines ) {
122
122
try {
123
- const lines = sourceFile . split ( '\n' ) ;
124
- addContextToFrame ( lines , frame , this . _contextLines ) ;
123
+ addContextToFrame ( sourceFileLines , frame , this . _contextLines ) ;
125
124
} catch ( e ) {
126
125
// anomaly, being defensive in case
127
126
// unlikely to ever happen in practice but can definitely happen in theory
@@ -134,25 +133,34 @@ export class ContextLines implements Integration {
134
133
135
134
/**
136
135
* Reads file contents and caches them in a global LRU cache.
136
+ * If reading fails, mark the file as null in the cache so we don't try again.
137
137
*
138
138
* @param filename filepath to read content from.
139
139
*/
140
- async function _readSourceFile ( filename : string ) : Promise < string | null > {
140
+ async function _readSourceFile ( filename : string ) : Promise < string [ ] | null > {
141
141
const cachedFile = FILE_CONTENT_CACHE . get ( filename ) ;
142
- // We have a cache hit
142
+
143
+ // We have already attempted to read this file and failed, do not try again
144
+ if ( cachedFile === null ) {
145
+ return null ;
146
+ }
147
+
148
+ // We have a cache hit, return it
143
149
if ( cachedFile !== undefined ) {
144
150
return cachedFile ;
145
151
}
146
152
147
- let content : string | null = null ;
148
-
149
153
// Guard from throwing if readFile fails, this enables us to use Promise.all and
150
154
// not have it short circuiting if one of the promises rejects + since context lines are added
151
155
// on a best effort basis, we want to throw here anyways.
156
+
157
+ // If we made it to here, it means that our file is not cache nor marked as failed, so attempt to read it
158
+ let content : string [ ] | null = null ;
152
159
try {
153
- content = await readTextFileAsync ( filename ) ;
160
+ const rawFileContents = await readTextFileAsync ( filename ) ;
161
+ content = rawFileContents . split ( '\n' ) ;
154
162
} catch ( _ ) {
155
- //
163
+ // if we fail, we will mark the file as null in the cache and short circuit next time we try to read it
156
164
}
157
165
158
166
FILE_CONTENT_CACHE . set ( filename , content ) ;
0 commit comments