1
1
import * as path from 'path'
2
2
import * as fs from 'fs'
3
+ import { hostname } from 'node:os'
3
4
import config from './config' // should be replaced by node-config or similar
4
5
import { createLogger , transports , format } from 'winston'
5
6
import { NextFunction , Request , Response } from 'express'
6
7
8
+ const { S3StreamLogger } = require ( 's3-streamlogger' )
9
+
7
10
const { combine, timestamp, printf, errors } = format
8
11
12
+ let s3ServerStream : any
13
+ let s3ErrorStream : any
14
+ let s3ServerReqStream : any
15
+ if ( process . env . STORAGE_TYPE === 's3' ) {
16
+ const accessKeyId = process . env . S3_STORAGE_ACCESS_KEY_ID
17
+ const secretAccessKey = process . env . S3_STORAGE_SECRET_ACCESS_KEY
18
+ const region = process . env . S3_STORAGE_REGION
19
+ const s3Bucket = process . env . S3_STORAGE_BUCKET_NAME
20
+
21
+ s3ServerStream = new S3StreamLogger ( {
22
+ bucket : s3Bucket ,
23
+ folder : 'logs/server' ,
24
+ region,
25
+ access_key_id : accessKeyId ,
26
+ secret_access_key : secretAccessKey ,
27
+ name_format : `server-%Y-%m-%d-%H-%M-%S-%L-${ hostname ( ) } .log`
28
+ } )
29
+
30
+ s3ErrorStream = new S3StreamLogger ( {
31
+ bucket : s3Bucket ,
32
+ folder : 'logs/error' ,
33
+ region,
34
+ access_key_id : accessKeyId ,
35
+ secret_access_key : secretAccessKey ,
36
+ name_format : `server-error-%Y-%m-%d-%H-%M-%S-%L-${ hostname ( ) } .log`
37
+ } )
38
+
39
+ s3ServerReqStream = new S3StreamLogger ( {
40
+ bucket : s3Bucket ,
41
+ folder : 'logs/requests' ,
42
+ region,
43
+ access_key_id : accessKeyId ,
44
+ secret_access_key : secretAccessKey ,
45
+ name_format : `server-requests-%Y-%m-%d-%H-%M-%S-%L-${ hostname ( ) } .log.jsonl`
46
+ } )
47
+ }
48
+
9
49
// expect the log dir be relative to the projects root
10
50
const logDir = config . logging . dir
11
51
@@ -29,33 +69,60 @@ const logger = createLogger({
29
69
} ,
30
70
transports : [
31
71
new transports . Console ( ) ,
32
- new transports . File ( {
33
- filename : path . join ( logDir , config . logging . server . filename ?? 'server.log' ) ,
34
- level : config . logging . server . level ?? 'info'
35
- } ) ,
36
- new transports . File ( {
37
- filename : path . join ( logDir , config . logging . server . errorFilename ?? 'server-error.log' ) ,
38
- level : 'error' // Log only errors to this file
39
- } )
72
+ ...( ! process . env . STORAGE_TYPE || process . env . STORAGE_TYPE === 'local'
73
+ ? [
74
+ new transports . File ( {
75
+ filename : path . join ( logDir , config . logging . server . filename ?? 'server.log' ) ,
76
+ level : config . logging . server . level ?? 'info'
77
+ } ) ,
78
+ new transports . File ( {
79
+ filename : path . join ( logDir , config . logging . server . errorFilename ?? 'server-error.log' ) ,
80
+ level : 'error' // Log only errors to this file
81
+ } )
82
+ ]
83
+ : [ ] ) ,
84
+ ...( process . env . STORAGE_TYPE === 's3'
85
+ ? [
86
+ new transports . Stream ( {
87
+ stream : s3ServerStream
88
+ } )
89
+ ]
90
+ : [ ] )
40
91
] ,
41
92
exceptionHandlers : [
42
- new transports . File ( {
43
- filename : path . join ( logDir , config . logging . server . errorFilename ?? 'server-error.log' )
44
- } )
93
+ ...( ! process . env . STORAGE_TYPE || process . env . STORAGE_TYPE === 'local'
94
+ ? [
95
+ new transports . File ( {
96
+ filename : path . join ( logDir , config . logging . server . errorFilename ?? 'server-error.log' )
97
+ } )
98
+ ]
99
+ : [ ] ) ,
100
+ ...( process . env . STORAGE_TYPE === 's3'
101
+ ? [
102
+ new transports . Stream ( {
103
+ stream : s3ErrorStream
104
+ } )
105
+ ]
106
+ : [ ] )
45
107
] ,
46
108
rejectionHandlers : [
47
- new transports . File ( {
48
- filename : path . join ( logDir , config . logging . server . errorFilename ?? 'server-error.log' )
49
- } )
109
+ ...( ! process . env . STORAGE_TYPE || process . env . STORAGE_TYPE === 'local'
110
+ ? [
111
+ new transports . File ( {
112
+ filename : path . join ( logDir , config . logging . server . errorFilename ?? 'server-error.log' )
113
+ } )
114
+ ]
115
+ : [ ] ) ,
116
+ ...( process . env . STORAGE_TYPE === 's3'
117
+ ? [
118
+ new transports . Stream ( {
119
+ stream : s3ErrorStream
120
+ } )
121
+ ]
122
+ : [ ] )
50
123
]
51
124
} )
52
125
53
- /**
54
- * This function is used by express as a middleware.
55
- * @example
56
- * this.app = express()
57
- * this.app.use(expressRequestLogger)
58
- */
59
126
export function expressRequestLogger ( req : Request , res : Response , next : NextFunction ) : void {
60
127
const unwantedLogURLs = [ '/api/v1/node-icon/' , '/api/v1/components-credentials-icon/' ]
61
128
if ( / \/ a p i \/ v 1 \/ / i. test ( req . url ) && ! unwantedLogURLs . some ( ( url ) => new RegExp ( url , 'i' ) . test ( req . url ) ) ) {
@@ -73,10 +140,21 @@ export function expressRequestLogger(req: Request, res: Response, next: NextFunc
73
140
}
74
141
} ,
75
142
transports : [
76
- new transports . File ( {
77
- filename : path . join ( logDir , config . logging . express . filename ?? 'server-requests.log.jsonl' ) ,
78
- level : config . logging . express . level ?? 'debug'
79
- } )
143
+ ...( ! process . env . STORAGE_TYPE || process . env . STORAGE_TYPE === 'local'
144
+ ? [
145
+ new transports . File ( {
146
+ filename : path . join ( logDir , config . logging . express . filename ?? 'server-requests.log.jsonl' ) ,
147
+ level : config . logging . express . level ?? 'debug'
148
+ } )
149
+ ]
150
+ : [ ] ) ,
151
+ ...( process . env . STORAGE_TYPE === 's3'
152
+ ? [
153
+ new transports . Stream ( {
154
+ stream : s3ServerReqStream
155
+ } )
156
+ ]
157
+ : [ ] )
80
158
]
81
159
} )
82
160
0 commit comments