azify-logger 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -12
- package/index.js +2 -2
- package/middleware-express.js +1 -1
- package/middleware-restify.js +1 -1
- package/package.json +15 -2
- package/server.js +39 -2
- package/store.js +2 -3
- package/streams/bunyan.js +2 -2
- package/streams/pino.js +2 -2
package/README.md
CHANGED
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
Sistema de logging centralizado com OpenTelemetry e OpenSearch para múltiplas aplicações.
|
|
4
4
|
|
|
5
|
+
## 🔌 Integração Rápida
|
|
6
|
+
|
|
7
|
+
### URLs para configurar nas aplicações:
|
|
8
|
+
|
|
9
|
+
| Ambiente | URL |
|
|
10
|
+
|----------|-------------------------------------------------------|
|
|
11
|
+
| **Development** | `http://localhost:3001` |
|
|
12
|
+
| **Staging** | `https://logsdashboard.azify.dev/send` |
|
|
13
|
+
| **Production** | `https://logsdashboard.azify.prd/send` (a configurar) |
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### URLs para acessar os logs e dashs:
|
|
17
|
+
|
|
18
|
+
| Ambiente | URL |
|
|
19
|
+
|----------|--------------------------------------------------|
|
|
20
|
+
| **Development** | `http://localhost:5601` |
|
|
21
|
+
| **Staging** | `https://logsdashboard.azify.dev` |
|
|
22
|
+
| **Production** | `https://logsdashboard.azify.com` (a configurar) |
|
|
23
|
+
|
|
24
|
+
|
|
5
25
|
## 📦 Instalação
|
|
6
26
|
|
|
7
27
|
Na sua aplicação, adicione ao `package.json`:
|
|
@@ -65,14 +85,41 @@ const app = express()
|
|
|
65
85
|
| Variável | Padrão | Descrição |
|
|
66
86
|
|----------|-------|-----------|
|
|
67
87
|
| `APP_NAME` | - | Nome da aplicação |
|
|
68
|
-
| `AZIFY_LOGGER_URL` | `http://localhost:
|
|
88
|
+
| `AZIFY_LOGGER_URL` | `http://localhost:3001` | URL do logger |
|
|
69
89
|
| `OTEL_EXPORTER_OTLP_ENDPOINT` | `http://localhost:4318/v1/traces` | OTLP endpoint |
|
|
70
90
|
| `NODE_ENV` | `development` | Ambiente |
|
|
71
91
|
| `AZIFY_LOGGER_AUTOREG_DISABLE` | `""` | Se `"1"`, desativa auto-registro do OTEL |
|
|
72
92
|
|
|
73
|
-
|
|
93
|
+
### 🌐 URLs por Ambiente
|
|
94
|
+
|
|
95
|
+
**Desenvolvimento (Local):**
|
|
96
|
+
```env
|
|
97
|
+
APP_NAME=minha-app
|
|
98
|
+
AZIFY_LOGGER_URL=http://localhost:3001
|
|
99
|
+
NODE_ENV=development
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Staging:**
|
|
103
|
+
```env
|
|
104
|
+
APP_NAME=minha-app
|
|
105
|
+
AZIFY_LOGGER_URL=http://logs.azify.dev
|
|
106
|
+
NODE_ENV=staging
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Production:**
|
|
110
|
+
```env
|
|
111
|
+
APP_NAME=minha-app
|
|
112
|
+
AZIFY_LOGGER_URL=http://logs.azify.com
|
|
113
|
+
NODE_ENV=production
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 🐳 Docker Compose (mesma network)
|
|
74
117
|
|
|
75
|
-
|
|
118
|
+
Apenas se estiver usando Docker Compose com rede compartilhada:
|
|
119
|
+
|
|
120
|
+
```env
|
|
121
|
+
AZIFY_LOGGER_URL=http://azify-logger:3001
|
|
122
|
+
```
|
|
76
123
|
|
|
77
124
|
### Docker e Node antigos
|
|
78
125
|
|
|
@@ -118,7 +165,7 @@ if (createAzifyBunyanStream) {
|
|
|
118
165
|
level: 'info',
|
|
119
166
|
type: 'raw',
|
|
120
167
|
stream: createAzifyBunyanStream({
|
|
121
|
-
loggerUrl: process.env.AZIFY_LOGGER_URL || 'http://localhost:
|
|
168
|
+
loggerUrl: process.env.AZIFY_LOGGER_URL || 'http://localhost:3001',
|
|
122
169
|
serviceName: process.env.APP_NAME || 'app'
|
|
123
170
|
})
|
|
124
171
|
})
|
|
@@ -146,7 +193,7 @@ const { streams } = require('azify-logger')
|
|
|
146
193
|
const pino = require('pino')
|
|
147
194
|
|
|
148
195
|
const logger = pino({ level: 'info' }, streams.createPinoStream({
|
|
149
|
-
loggerUrl: 'http://localhost:
|
|
196
|
+
loggerUrl: 'http://localhost:3001',
|
|
150
197
|
serviceName: 'nome-app'
|
|
151
198
|
}))
|
|
152
199
|
|
|
@@ -160,7 +207,7 @@ const { createAzifyLogger } = require('azify-logger')
|
|
|
160
207
|
|
|
161
208
|
const logger = createAzifyLogger({
|
|
162
209
|
serviceName: 'nome-app',
|
|
163
|
-
loggerUrl: 'http://localhost:
|
|
210
|
+
loggerUrl: 'http://localhost:3001'
|
|
164
211
|
})
|
|
165
212
|
|
|
166
213
|
logger.info('Mensagem', { userId: '123' })
|
|
@@ -185,14 +232,14 @@ Aguarde alguns minutos. Você verá:
|
|
|
185
232
|
✅ Tudo pronto!
|
|
186
233
|
📊 OpenSearch: http://localhost:9200
|
|
187
234
|
🎨 OpenSearch Dashboards: http://localhost:5601
|
|
188
|
-
📝 Logger API: http://localhost:
|
|
235
|
+
📝 Logger API: http://localhost:3001
|
|
189
236
|
🔭 OTEL Collector: http://localhost:4318
|
|
190
237
|
```
|
|
191
238
|
|
|
192
239
|
### 2. Testar
|
|
193
240
|
|
|
194
241
|
```bash
|
|
195
|
-
curl -X POST http://localhost:
|
|
242
|
+
curl -X POST http://localhost:3001/log \
|
|
196
243
|
-H "Content-Type: application/json" \
|
|
197
244
|
-d '{
|
|
198
245
|
"level": "info",
|
|
@@ -244,6 +291,8 @@ Cada log no OpenSearch contém:
|
|
|
244
291
|
3. **Logger** envia ambos os logs com **traceId e spanId iguais**
|
|
245
292
|
4. **OpenSearch** indexa e permite buscar por traceId
|
|
246
293
|
|
|
294
|
+
---
|
|
295
|
+
|
|
247
296
|
## 📖 Arquitetura
|
|
248
297
|
|
|
249
298
|
```
|
|
@@ -285,11 +334,18 @@ O azify-logger usa OpenSearch Dashboards para visualização dos logs:
|
|
|
285
334
|
- **Erros 4xx/5xx** - Contador de erros
|
|
286
335
|
- **Requisições por Minuto** - Gráfico temporal
|
|
287
336
|
|
|
288
|
-
###
|
|
337
|
+
### ⚠️ Preservação de Dados
|
|
338
|
+
|
|
339
|
+
**IMPORTANTE:** Logs do OpenSearch são armazenados em volume Docker persistente.
|
|
289
340
|
|
|
341
|
+
**Comandos seguros** (preservam dados):
|
|
290
342
|
```bash
|
|
291
|
-
|
|
292
|
-
|
|
343
|
+
docker-compose stop
|
|
344
|
+
docker-compose restart
|
|
345
|
+
pm2 stop azify-logger
|
|
346
|
+
```
|
|
293
347
|
|
|
294
|
-
|
|
348
|
+
**Comandos destrutivos** (APAGAM logs):
|
|
349
|
+
```bash
|
|
350
|
+
docker-compose down -v # ⚠️ APAGA VOLUMES!
|
|
295
351
|
```
|
package/index.js
CHANGED
|
@@ -12,7 +12,7 @@ class AzifyLogger {
|
|
|
12
12
|
constructor(options = {}) {
|
|
13
13
|
this.options = {
|
|
14
14
|
serviceName: options.serviceName || 'azipay',
|
|
15
|
-
loggerUrl: options.loggerUrl || 'http://localhost:
|
|
15
|
+
loggerUrl: options.loggerUrl || 'http://localhost:3001',
|
|
16
16
|
environment: options.environment || process.env.NODE_ENV || 'development',
|
|
17
17
|
...options
|
|
18
18
|
}
|
|
@@ -96,7 +96,7 @@ function createAzifyLogger(options = {}) {
|
|
|
96
96
|
function createAzifyLoggerFromEnv() {
|
|
97
97
|
return createAzifyLogger({
|
|
98
98
|
serviceName: process.env.APP_NAME || 'azipay',
|
|
99
|
-
loggerUrl: process.env.AZIFY_LOGGER_URL || 'http://localhost:
|
|
99
|
+
loggerUrl: process.env.AZIFY_LOGGER_URL || 'http://localhost:3001',
|
|
100
100
|
environment: process.env.NODE_ENV || 'development'
|
|
101
101
|
})
|
|
102
102
|
}
|
package/middleware-express.js
CHANGED
|
@@ -4,7 +4,7 @@ const { als, runWithRequestContext, startRequestContext, getRequestContext } = r
|
|
|
4
4
|
function createExpressLoggingMiddleware(options = {}) {
|
|
5
5
|
const config = {
|
|
6
6
|
serviceName: options.serviceName || process.env.APP_NAME || 'assemble',
|
|
7
|
-
loggerUrl: options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:
|
|
7
|
+
loggerUrl: options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:3001',
|
|
8
8
|
environment: options.environment || process.env.NODE_ENV || 'development'
|
|
9
9
|
}
|
|
10
10
|
|
package/middleware-restify.js
CHANGED
|
@@ -4,7 +4,7 @@ const { als, runWithRequestContext, startRequestContext, getRequestContext } = r
|
|
|
4
4
|
function createRestifyLoggingMiddleware(options = {}) {
|
|
5
5
|
const config = {
|
|
6
6
|
serviceName: options.serviceName || process.env.APP_NAME || 'azipay',
|
|
7
|
-
loggerUrl: options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:
|
|
7
|
+
loggerUrl: options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:3001',
|
|
8
8
|
environment: options.environment || process.env.NODE_ENV || 'development'
|
|
9
9
|
}
|
|
10
10
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "azify-logger",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "Azify Logger Client - Centralized logging for OpenSearch",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "echo \"No tests specified\" && exit 0"
|
|
8
|
+
"test": "echo \"No tests specified\" && exit 0",
|
|
9
|
+
"start": "node server.js",
|
|
10
|
+
"dev": "node server.js",
|
|
11
|
+
"dev:full": "docker-compose up -d && sleep 10 && npm start",
|
|
12
|
+
"pm2:start": "pm2 start ecosystem.config.js",
|
|
13
|
+
"pm2:stop": "pm2 stop ecosystem.config.js",
|
|
14
|
+
"pm2:restart": "pm2 restart ecosystem.config.js",
|
|
15
|
+
"pm2:logs": "pm2 logs azify-logger",
|
|
16
|
+
"docker:up": "docker-compose up -d",
|
|
17
|
+
"docker:down": "docker-compose down",
|
|
18
|
+
"docker:logs": "docker-compose logs -f"
|
|
9
19
|
},
|
|
10
20
|
"keywords": [
|
|
11
21
|
"logging",
|
|
@@ -26,6 +36,9 @@
|
|
|
26
36
|
"axios": "^1.6.0",
|
|
27
37
|
"cors": "^2.8.5",
|
|
28
38
|
"express": "^4.18.2",
|
|
39
|
+
"express-session": "^1.17.3",
|
|
40
|
+
"passport": "^0.6.0",
|
|
41
|
+
"passport-azure-ad": "^4.3.5",
|
|
29
42
|
"require-in-the-middle": "^7.4.0",
|
|
30
43
|
"uuid": "^9.0.1"
|
|
31
44
|
},
|
package/server.js
CHANGED
|
@@ -8,9 +8,25 @@ const { trace, context, propagation } = require('@opentelemetry/api')
|
|
|
8
8
|
const { W3CTraceContextPropagator } = require('@opentelemetry/core')
|
|
9
9
|
|
|
10
10
|
const app = express()
|
|
11
|
+
|
|
12
|
+
app.set('trust proxy', 1)
|
|
13
|
+
|
|
11
14
|
app.use(express.json())
|
|
12
15
|
app.use(cors())
|
|
13
16
|
|
|
17
|
+
const authEnabled = process.env.AZURE_AD_AUTH_ENABLED === 'true'
|
|
18
|
+
let ensureAuthenticated = (req, res, next) => next()
|
|
19
|
+
|
|
20
|
+
if (authEnabled) {
|
|
21
|
+
const { setupAuth, setupAuthRoutes, ensureAuthenticated: authMiddleware } = require('./auth')
|
|
22
|
+
ensureAuthenticated = authMiddleware
|
|
23
|
+
setupAuth(app)
|
|
24
|
+
setupAuthRoutes(app)
|
|
25
|
+
console.log('✅ Autenticação Azure AD habilitada')
|
|
26
|
+
} else {
|
|
27
|
+
console.log('⚠️ Autenticação Azure AD desabilitada')
|
|
28
|
+
}
|
|
29
|
+
|
|
14
30
|
const tracer = trace.getTracer('azify-logger', '1.0.0')
|
|
15
31
|
const propagator = new W3CTraceContextPropagator()
|
|
16
32
|
|
|
@@ -116,7 +132,28 @@ function getOrCreateTraceContext(requestId) {
|
|
|
116
132
|
}
|
|
117
133
|
|
|
118
134
|
app.get('/health', (req, res) => {
|
|
119
|
-
res.json({
|
|
135
|
+
res.json({
|
|
136
|
+
status: 'ok',
|
|
137
|
+
service: 'azify-logger',
|
|
138
|
+
authEnabled: authEnabled
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
app.get('/', ensureAuthenticated, (req, res) => {
|
|
143
|
+
res.json({
|
|
144
|
+
service: 'azify-logger',
|
|
145
|
+
version: '1.0.0',
|
|
146
|
+
endpoints: {
|
|
147
|
+
health: '/health',
|
|
148
|
+
testLog: '/test-log',
|
|
149
|
+
auth: authEnabled ? {
|
|
150
|
+
login: '/auth/login',
|
|
151
|
+
logout: '/auth/logout',
|
|
152
|
+
me: '/auth/me'
|
|
153
|
+
} : null
|
|
154
|
+
},
|
|
155
|
+
user: req.user || null
|
|
156
|
+
})
|
|
120
157
|
})
|
|
121
158
|
|
|
122
159
|
app.post('/log', async (req, res) => {
|
|
@@ -212,7 +249,7 @@ app.post('/log', async (req, res) => {
|
|
|
212
249
|
}
|
|
213
250
|
})
|
|
214
251
|
|
|
215
|
-
const port = process.env.PORT ||
|
|
252
|
+
const port = process.env.PORT || 3001
|
|
216
253
|
|
|
217
254
|
app.listen(port, () => {
|
|
218
255
|
console.log(`🚀 Azify Logger rodando na porta ${port}`)
|
package/store.js
CHANGED
|
@@ -7,14 +7,13 @@ function generateId(bytes = 16) {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
function toTraceId(hex32) {
|
|
10
|
-
// ensure 32 hex chars
|
|
11
10
|
const h = (hex32 || '').padStart(32, '0').slice(0, 32)
|
|
12
11
|
return `${h.substring(0, 8)}-${h.substring(8, 12)}-${h.substring(12, 16)}-${h.substring(16, 20)}-${h.substring(20, 32)}`
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
function startRequestContext(initial = {}) {
|
|
16
|
-
const traceHex = initial.traceHex || generateId(16)
|
|
17
|
-
const spanHex = initial.spanHex || generateId(8)
|
|
15
|
+
const traceHex = initial.traceHex || generateId(16)
|
|
16
|
+
const spanHex = initial.spanHex || generateId(8)
|
|
18
17
|
const ctx = {
|
|
19
18
|
traceId: toTraceId(traceHex),
|
|
20
19
|
spanId: spanHex,
|
package/streams/bunyan.js
CHANGED
|
@@ -4,7 +4,7 @@ const axios = require('axios')
|
|
|
4
4
|
const globalContext = new Map()
|
|
5
5
|
|
|
6
6
|
function createBunyanStream(options = {}) {
|
|
7
|
-
const loggerUrl = options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:
|
|
7
|
+
const loggerUrl = options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:3001'
|
|
8
8
|
const serviceName = options.serviceName || process.env.APP_NAME || 'app'
|
|
9
9
|
const environment = options.environment || process.env.NODE_ENV || 'development'
|
|
10
10
|
|
|
@@ -52,7 +52,7 @@ function createBunyanStream(options = {}) {
|
|
|
52
52
|
|
|
53
53
|
const payload = { level, message: record.msg || record.message || 'log', meta }
|
|
54
54
|
|
|
55
|
-
axios.post(`${loggerUrl}/log`, payload, { headers, timeout:
|
|
55
|
+
axios.post(`${loggerUrl}/log`, payload, { headers, timeout: 3001 }).catch(() => {})
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
}
|
package/streams/pino.js
CHANGED
|
@@ -3,7 +3,7 @@ const { W3CTraceContextPropagator } = require('@opentelemetry/core')
|
|
|
3
3
|
const axios = require('axios')
|
|
4
4
|
|
|
5
5
|
function createPinoStream(options = {}) {
|
|
6
|
-
const loggerUrl = options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:
|
|
6
|
+
const loggerUrl = options.loggerUrl || process.env.AZIFY_LOGGER_URL || 'http://localhost:3001'
|
|
7
7
|
const serviceName = options.serviceName || process.env.APP_NAME || 'app'
|
|
8
8
|
const environment = options.environment || process.env.NODE_ENV || 'development'
|
|
9
9
|
|
|
@@ -47,7 +47,7 @@ function createPinoStream(options = {}) {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
const payload = { level, message: record.msg || record.message || 'log', meta }
|
|
50
|
-
axios.post(`${loggerUrl}/log`, payload, { headers, timeout:
|
|
50
|
+
axios.post(`${loggerUrl}/log`, payload, { headers, timeout: 3001 }).catch(() => {})
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
}
|