@@ -59,7 +59,6 @@ class Collector {
5959
6060 start ( ) {
6161 ensureDir ( this . outputDir )
62- migrateLegacyServiceFiles ( this . outputDir )
6362
6463 const server = createServer ( this . handleData . bind ( this ) )
6564 this . server = server
@@ -161,169 +160,6 @@ function appendLegacyNormalizedLogRow(outputDir, serviceName, row) {
161160 fs . appendFileSync ( filePath , JSON . stringify ( row ) + '\n' )
162161}
163162
164- /**
165- * Convert previously written raw service envelope files into normalized rows.
166- *
167- * Older builds accidentally wrote raw OTLP envelopes to services/<service>/.
168- * The services tree is now the normalized browse view, so migrate those files
169- * in place and preserve the originals under services-raw/.
170- *
171- * @param {string } outputDir
172- * @returns {void }
173- */
174- function migrateLegacyServiceFiles ( outputDir ) {
175- const servicesDir = path . join ( outputDir , 'services' )
176- if ( ! fs . existsSync ( servicesDir ) ) return
177- /** @type {{ filePath: string, fileName: string, serviceDirName: string, rawText: string, rows: NormalizedServiceRow[] }[] } */
178- const legacyFiles = [ ]
179-
180- for ( const serviceDirName of fs . readdirSync ( servicesDir ) ) {
181- const serviceDir = path . join ( servicesDir , serviceDirName )
182- if ( ! safeStat ( serviceDir ) ?. isDirectory ( ) ) continue
183-
184- for ( const fileName of fs . readdirSync ( serviceDir ) ) {
185- const match = fileName . match ( / ^ ( l o g s | t r a c e s | m e t r i c s ) - \d { 4 } - \d { 2 } - \d { 2 } \. j s o n l $ / )
186- if ( ! match ) continue
187-
188- const signal = match [ 1 ]
189- const collectionKey = signalCollectionKey ( signal )
190- if ( ! collectionKey ) continue
191-
192- const filePath = path . join ( serviceDir , fileName )
193- if ( ! fileContainsLegacyRawEnvelope ( filePath , collectionKey ) ) continue
194-
195- const rawText = fs . readFileSync ( filePath , 'utf8' )
196- legacyFiles . push ( {
197- filePath,
198- fileName,
199- serviceDirName,
200- rawText,
201- rows : flattenSignalText ( signal , rawText ) ,
202- } )
203- }
204- }
205-
206- /** @type {Map<string, NormalizedServiceRow[]> } */
207- const migratedRowsByFilePath = new Map ( )
208- for ( const legacyFile of legacyFiles ) {
209- preserveLegacyServiceRawFile ( outputDir , legacyFile . serviceDirName , legacyFile . fileName , legacyFile . rawText )
210- groupMigratedRowsByTargetFile ( servicesDir , legacyFile . fileName , legacyFile . rows , migratedRowsByFilePath )
211- }
212-
213- const legacyFilePaths = new Set ( legacyFiles . map ( ( legacyFile ) => legacyFile . filePath ) )
214- for ( const legacyFile of legacyFiles ) {
215- writeRowsFile ( legacyFile . filePath , migratedRowsByFilePath . get ( legacyFile . filePath ) ?? [ ] )
216- }
217-
218- for ( const [ filePath , rows ] of migratedRowsByFilePath ) {
219- if ( legacyFilePaths . has ( filePath ) ) continue
220- appendRowsFile ( filePath , rows )
221- }
222- }
223-
224- /**
225- * @param {string } outputDir
226- * @param {string } serviceDirName
227- * @param {string } fileName
228- * @param {string } rawText
229- * @returns {void }
230- */
231- function preserveLegacyServiceRawFile ( outputDir , serviceDirName , fileName , rawText ) {
232- const rawDir = path . join ( outputDir , 'services-raw' , serviceDirName )
233- ensureDir ( rawDir )
234- const rawPath = path . join ( rawDir , fileName )
235- if ( fs . existsSync ( rawPath ) ) {
236- fs . appendFileSync ( rawPath , rawText )
237- return
238- }
239- fs . writeFileSync ( rawPath , rawText )
240- }
241-
242- /**
243- * Legacy raw service files can contain rows for multiple actual services, so
244- * repartition them by each normalized row's serviceName before rewriting.
245- *
246- * @param {string } servicesDir
247- * @param {string } fileName
248- * @param {NormalizedServiceRow[] } rows
249- * @param {Map<string, NormalizedServiceRow[]> } rowsByFilePath
250- * @returns {void }
251- */
252- function groupMigratedRowsByTargetFile ( servicesDir , fileName , rows , rowsByFilePath ) {
253- for ( const row of rows ) {
254- const serviceName = sanitizePathSegment ( row . serviceName || '_unknown' )
255- const filePath = path . join ( servicesDir , serviceName , fileName )
256- const existingRows = rowsByFilePath . get ( filePath )
257- if ( existingRows ) {
258- existingRows . push ( row )
259- } else {
260- rowsByFilePath . set ( filePath , [ row ] )
261- }
262- }
263- }
264-
265- /**
266- * @param {string } filePath
267- * @param {NormalizedServiceRow[] } rows
268- * @returns {void }
269- */
270- function writeRowsFile ( filePath , rows ) {
271- ensureDir ( path . dirname ( filePath ) )
272- const text = rows . map ( ( row ) => JSON . stringify ( row ) ) . join ( '\n' )
273- fs . writeFileSync ( filePath , text ? `${ text } \n` : '' )
274- }
275-
276- /**
277- * @param {string } filePath
278- * @param {NormalizedServiceRow[] } rows
279- * @returns {void }
280- */
281- function appendRowsFile ( filePath , rows ) {
282- if ( ! rows . length ) return
283- ensureDir ( path . dirname ( filePath ) )
284- const text = rows . map ( ( row ) => JSON . stringify ( row ) ) . join ( '\n' )
285- fs . appendFileSync ( filePath , `${ text } \n` )
286- }
287-
288- /**
289- * @param {string } filePath
290- * @param {'resourceLogs' | 'resourceSpans' | 'resourceMetrics' } collectionKey
291- * @returns {boolean }
292- */
293- function fileContainsLegacyRawEnvelope ( filePath , collectionKey ) {
294- const text = fs . readFileSync ( filePath , 'utf8' )
295- const firstLine = text . split ( '\n' ) . find ( line => line . trim ( ) . length > 0 )
296- if ( ! firstLine ) return false
297-
298- try {
299- const parsed = JSON . parse ( firstLine )
300- return Array . isArray ( objectRecord ( parsed ) ?. [ collectionKey ] )
301- } catch {
302- return false
303- }
304- }
305-
306- /**
307- * @param {string } signal
308- * @param {string } text
309- * @returns {NormalizedServiceRow[] }
310- */
311- function flattenSignalText ( signal , text ) {
312- /** @type {NormalizedServiceRow[] } */
313- const rows = [ ]
314-
315- for ( const line of text . split ( '\n' ) ) {
316- if ( ! line . trim ( ) ) continue
317- try {
318- rows . push ( ...flattenSignalRows ( signal , JSON . parse ( line ) ) )
319- } catch {
320- // skip malformed lines during migration
321- }
322- }
323-
324- return rows
325- }
326-
327163/**
328164 * @param {string } signal
329165 * @param {unknown } data
@@ -336,16 +172,6 @@ function flattenSignalRows(signal, data) {
336172 return [ ]
337173}
338174
339- /**
340- * @param {string } signal
341- * @returns {'resourceLogs' | 'resourceSpans' | 'resourceMetrics' | undefined }
342- */
343- function signalCollectionKey ( signal ) {
344- if ( signal === 'logs' ) return 'resourceLogs'
345- if ( signal === 'traces' ) return 'resourceSpans'
346- if ( signal === 'metrics' ) return 'resourceMetrics'
347- }
348-
349175/**
350176 * Flatten OTLP log export envelopes into one normalized row per log record.
351177 *
@@ -922,18 +748,6 @@ function ensureDir(dir) {
922748 }
923749}
924750
925- /**
926- * @param {string } filePath
927- * @returns {fs.Stats | undefined }
928- */
929- function safeStat ( filePath ) {
930- try {
931- return fs . statSync ( filePath )
932- } catch {
933- return undefined
934- }
935- }
936-
937751/**
938752 * @param {unknown } value
939753 * @returns {Record<string, unknown> | undefined }
0 commit comments