Skip to content

Commit 8dd47e1

Browse files
committed
feat: add packages/logging
closes #1575
1 parent 8e012da commit 8dd47e1

File tree

14 files changed

+775
-0
lines changed

14 files changed

+775
-0
lines changed

packages/logging/.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
node_modules
2+
dist
3+
test
4+
src/**.js
5+
6+
/coverage
7+
/docs
8+
.nyc_output
9+
*.log
10+
11+
wallaby.conf.js
12+
13+
.DS_Store

packages/logging/.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package.json
2+
src/copy
3+
CHANGELOG.md

packages/logging/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License (MIT)
2+
3+
Copyright (c) 2018 Norsk rikskringkasting AS (NRK)
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

packages/logging/README.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# Sofie: The Modern TV News Studio Automation System (Logging library)
2+
3+
[![npm](https://img.shields.io/npm/v/@sofie-automation/logging)](https://www.npmjs.com/package/@sofie-automation/logging)
4+
5+
This is a part of the [**Sofie** TV News Studio Automation System](https://github.com/Sofie-Automation/Sofie-TV-automation/).
6+
7+
## What is it?
8+
9+
This is a thin wrapper around the LogTape library (https://logtape.org) with some Sofie-recommended defaults and restrictions.
10+
11+
The reason for using this package is:
12+
13+
- To have a unified logging setup across the Sofie Automation projects
14+
- To ensure logs are easily parsable by log collectors such as Elasticsearch by avoiding logging arbitrary data structures.
15+
16+
## Usage
17+
18+
_Note: The official LogTape documentation applies to this as well, see https://logtape.org_
19+
20+
### In application: Configuration
21+
22+
#### Configure and initialize logging at startup
23+
24+
_It is mandatory that the application sets the configuration upon standup_
25+
26+
```typescript
27+
import { loggingDefaultConfigure, getDefaultConfiguration, loggingConfigure } from '@sofie-automation/logging'
28+
29+
await loggingDefaultConfigure() // Sets up logging with Sofie-recommended defaults
30+
31+
// or:
32+
33+
await loggingDefaultConfigure({
34+
logLevel: 'debug', // Set a log level
35+
logPath: '/var/logs/my-application', // Enable logging to disk
36+
})
37+
38+
// or:
39+
40+
// This is equivalent to calling loggingDefaultConfigure():
41+
const config = getDefaultConfiguration()
42+
await loggingConfigure(config)
43+
```
44+
45+
#### Reconfigure logging at runtime
46+
47+
```typescript
48+
import { loggingDefaultConfigure } from '@sofie-automation/logging'
49+
50+
// Example: Change the log level:
51+
await loggingDefaultConfigure({
52+
reset: true, // Reset previous configuration
53+
logLevel: 'debug', // Set a log level
54+
})
55+
56+
// Note: If you have a custom logging configuration, you have to instead modify modify it and pass it into loggingConfigure() again.
57+
```
58+
59+
### Logging
60+
61+
```typescript
62+
import { getLogger, SofieLogger } from '@sofie-automation/logging'
63+
64+
class MyLibraryClass {
65+
logger: SofieLogger
66+
constructor() {
67+
// Setup a logger for this class.
68+
// Set the category so that the origin of the logs can be identified:
69+
this.logger = getLogger(['my-library', 'MyLibraryClass'])
70+
}
71+
logAMessage() {
72+
logger.info('Hello world!')
73+
}
74+
}
75+
```
76+
77+
It is possible to provide the logger with additional context data.
78+
By default, only the `data` field is allowed:
79+
80+
```typescript
81+
const logger = getLogger(['my-test-category'])
82+
logger.info('got some data', { data: myDataObject }) // The `data` field is always converted to JSON-string before logged.
83+
```
84+
85+
If you want to log some custom data fields, you need to extend the SofieLogger type to allow those fields:
86+
87+
```typescript
88+
declare module '@sofie-automation/logging' {
89+
interface SofieLoggerContext {
90+
userId?: string
91+
sessionId?: string
92+
}
93+
}
94+
95+
const logger = getLogger(['my-test-category'])
96+
logger.info('user logged in', {
97+
// These fields are now allowed:
98+
userId: 'user-1234',
99+
session: 'session-5678',
100+
})
101+
```
102+
103+
The reason for not allowing any data in the context (as is the LogTape way),
104+
it turns out that logging arbitrary data structures can lead to issues with log collectors,
105+
as they may not be able to parse and index all data structures correctly.
106+
107+
#### Inheritance and contextual loggers
108+
109+
```typescript
110+
import { getLogger } from '@sofie-automation/logging'
111+
declare module '@sofie-automation/logging' {
112+
interface SofieLoggerContext {
113+
userId?: string
114+
}
115+
}
116+
117+
const parentLogger = getLogger('my-library')
118+
119+
// Example of creating a child logger with a sub-category:
120+
const childLogger = parentLogger.getChild('child-category')
121+
childLogger.info('This is from the child logger') // outputs category "my-library.child-category"
122+
123+
// Example of creating a contextual logger:
124+
const withContextLogger = parentLogger.with({ userId: 'user-1234' })
125+
withContextLogger.info('User did something') // outputs with userId in the log context
126+
```
127+
128+
#### Advanced: Custom filters
129+
130+
An application may implement custom log filters, for example to omit logs from certain categories.
131+
132+
```typescript
133+
import { getLogger, getDefaultConfiguration, loggingConfigure } from '@sofie-automation/logging'
134+
135+
const config = getDefaultConfiguration({
136+
reset: true,
137+
logLevel: 'debug', // debug and above
138+
})
139+
140+
// Add a filter:
141+
const filters = (config.filters = config.filters ?? {})
142+
filters.myCustomFilter = (log) => {
143+
if (log.category.includes('special-category')) return false // Don't log this
144+
return true
145+
}
146+
147+
// Assign the filter to all loggers:
148+
config.loggers.forEach((logger) => (logger.filters = [...(logger.filters || []), 'myCustomFilter']))
149+
150+
await loggingConfigure(config)
151+
152+
const logger = getLogger('my-category')
153+
const specialLogger = logger.getChild('special-category')
154+
155+
logger.info('This message will appear')
156+
specialLogger.info('This message will NOT appear')
157+
```

packages/logging/eslint.config.mjs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { generateEslintConfig } from '@sofie-automation/code-standard-preset/eslint/main.mjs'
2+
3+
export default generateEslintConfig({})

packages/logging/jest.config.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module.exports = {
2+
globals: {},
3+
moduleFileExtensions: ['js', 'ts'],
4+
transform: {
5+
'^.+\\.(ts|tsx)$': [
6+
'ts-jest',
7+
{
8+
tsconfig: 'tsconfig.json',
9+
},
10+
],
11+
},
12+
moduleNameMapper: {
13+
'(.+)\\.js$': '$1',
14+
},
15+
testMatch: ['**/__tests__/**/*.(spec|test).(ts|js)'],
16+
testPathIgnorePatterns: ['integrationTests'],
17+
testEnvironment: 'node',
18+
// coverageThreshold: {
19+
// global: {
20+
// branches: 80,
21+
// functions: 100,
22+
// lines: 95,
23+
// statements: 90,
24+
// },
25+
// },
26+
coverageDirectory: './coverage/',
27+
coverageProvider: 'v8',
28+
collectCoverage: true,
29+
preset: 'ts-jest',
30+
}

packages/logging/package.json

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"name": "@sofie-automation/logging",
3+
"version": "1.53.0-in-development",
4+
"description": "Library for logging, based on LogTape",
5+
"main": "dist/index.js",
6+
"typings": "dist/index.d.ts",
7+
"license": "MIT",
8+
"repository": {
9+
"type": "git",
10+
"url": "git+https://github.com/nrkno/sofie-core.git",
11+
"directory": "packages/shared-lib"
12+
},
13+
"bugs": {
14+
"url": "https://github.com/nrkno/sofie-core/issues"
15+
},
16+
"homepage": "https://github.com/nrkno/sofie-core/blob/master/packages/logging#readme",
17+
"scripts": {
18+
"build": "run -T rimraf dist && run build:main",
19+
"build:main": "run -T tsc -p tsconfig.build.json",
20+
"lint:raw": "run -T eslint",
21+
"lint": "run lint:raw .",
22+
"unit": "run -T jest",
23+
"test": "run lint && run unit",
24+
"watch": "run -T jest --watch",
25+
"cov": "run -T jest --coverage; open-cli coverage/lcov-report/index.html",
26+
"cov-open": "open-cli coverage/lcov-report/index.html",
27+
"validate:dependencies": "yarn npm audit --environment production && run license-validate",
28+
"validate:dev-dependencies": "yarn npm audit --environment development",
29+
"license-validate": "run -T sofie-licensecheck"
30+
},
31+
"engines": {
32+
"node": ">=22.20.0"
33+
},
34+
"files": [
35+
"/dist",
36+
"/CHANGELOG.md",
37+
"/README.md",
38+
"/LICENSE"
39+
],
40+
"dependencies": {
41+
"@logtape/file": "^1.2.3",
42+
"@logtape/logtape": "^1.3.6",
43+
"tslib": "^2.8.1"
44+
},
45+
"prettier": "@sofie-automation/code-standard-preset/.prettierrc.json",
46+
"lint-staged": {
47+
"*.{js,css,json,md,scss}": [
48+
"yarn run -T prettier"
49+
],
50+
"*.{ts,tsx}": [
51+
"yarn lint:raw"
52+
]
53+
},
54+
"publishConfig": {
55+
"access": "public"
56+
},
57+
"packageManager": "[email protected]"
58+
}

0 commit comments

Comments
 (0)