1 | # advanced-logger
|
2 |
|
3 | [![Build Status](https://travis-ci.org/AlexeyPopovUA/advanced-logger.svg?branch=master)](https://travis-ci.org/AlexeyPopovUA/advanced-logger)
|
4 | [![npm version](https://badge.fury.io/js/advanced-logger.svg)](https://badge.fury.io/js/advanced-logger)
|
5 | [![dependencies Status](https://david-dm.org/AlexeyPopovUA/advanced-logger/status.svg)](https://david-dm.org/AlexeyPopovUA/advanced-logger)
|
6 | [![install size](https://packagephobia.now.sh/badge?p=advanced-logger)](https://packagephobia.now.sh/result?p=advanced-logger)
|
7 | [![](https://data.jsdelivr.com/v1/package/npm/advanced-logger/badge)](https://www.jsdelivr.com/package/npm/advanced-logger)
|
8 | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FAlexeyPopovUA%2Fadvanced-logger.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2FAlexeyPopovUA%2Fadvanced-logger?ref=badge_shield)
|
9 |
|
10 | [![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=advanced-logger&metric=alert_status)](https://sonarcloud.io/dashboard/index/advanced-logger)
|
11 | [![Reliability](https://sonarcloud.io/api/project_badges/measure?project=advanced-logger&metric=reliability_rating)](https://sonarcloud.io/dashboard/index/advanced-logger)
|
12 | [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=advanced-logger&metric=coverage)](https://sonarcloud.io/dashboard/index/advanced-logger)
|
13 | [![Bugs](https://sonarcloud.io/api/project_badges/measure?project=advanced-logger&metric=bugs)](https://sonarcloud.io/dashboard/index/advanced-logger)
|
14 | [![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=advanced-logger&metric=code_smells)](https://sonarcloud.io/dashboard/index/advanced-logger)
|
15 | [![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=advanced-logger&metric=vulnerabilities)](https://sonarcloud.io/dashboard/index/advanced-logger)
|
16 | [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org)
|
17 |
|
18 | ## The idea
|
19 |
|
20 | The main idea of this module is to create an isomorphic log sending tool, that can be extended by internal/external plugins.
|
21 |
|
22 | It has bundles for browser and nodejs environments.
|
23 |
|
24 | It can be extended with custom strategy ("when to send logs") and service ("where to send logs"). See usage examples.
|
25 |
|
26 | It does not restrict you with conventions, for example, existence of "logSeverity", "ErrorId" or "message" fields in log.
|
27 |
|
28 | It supports any format of logs via custom serializer.
|
29 |
|
30 | ## Features
|
31 |
|
32 | * It works in browsers and nodejs
|
33 | * It is able to send single logs and bundles of them to an external logger
|
34 | * It supports different log sending strategies:
|
35 | 1. interval (for example, every 10 seconds)
|
36 | 2. on request (only when you ask)
|
37 | 3. mixed ("interval" + "on request") (will be done soon)
|
38 | 4. on bundle size (for example, sends bundles of 100 logs)
|
39 | 5. instant (received 1 log -> sent 1 log)
|
40 | * It is able to group duplicated logs in certain time interval (for rapid fire of the same logs)
|
41 | * It is not afraid of circular links in log objects
|
42 | * It supports custom format for logs (custom serializer)
|
43 | * It supports different remote logger endpoints (SumoLogic, Loggly and Elasticsearch). Who is the next? ᕙ(ಠ.ಠ)ᕗ
|
44 |
|
45 | ## Runtime environment support
|
46 |
|
47 | Builds are generated as ES5 bundles for nodejs and browser environments.
|
48 |
|
49 | NodeJS - tested on latest lts
|
50 |
|
51 | Browser - all latest browsers + IE10, IE11 (fetch polyfill)
|
52 |
|
53 | ## Usage
|
54 |
|
55 | Please, find working examples for browser and nodejs environments in **/example** folder.
|
56 |
|
57 | ### Add to the project
|
58 |
|
59 | In browser:
|
60 |
|
61 | ```html
|
62 | <script src="./node-modules/advance-logger/dist/browser/advanced-logger.browser.min.js"></script>
|
63 | ```
|
64 |
|
65 | or
|
66 |
|
67 | ```html
|
68 | <script src="https://cdn.jsdelivr.net/npm/advanced-logger@latest/dist/browser/advanced-logger.browser.min.js"></script>
|
69 | <script src="https://cdn.jsdelivr.net/npm/advanced-logger@latest/dist/browser-debug/advanced-logger.browser.js"></script>
|
70 | ```
|
71 |
|
72 | In nodejs:
|
73 |
|
74 | ```javascript
|
75 | const {AdvancedLogger, service, strategy} = require('advanced-logger');
|
76 | ```
|
77 |
|
78 | ### Simplest usage
|
79 |
|
80 | Lets initiate a logger that sends all logs instantly to Sumologic service.
|
81 |
|
82 | In browser
|
83 |
|
84 | ```javascript
|
85 | const {AdvancedLogger, service, strategy} = window.advancedLogger;
|
86 |
|
87 | const defaultLogConfig = {
|
88 | UserAgent: window.userAgent,
|
89 | Channel: "my-company",
|
90 | BuildVersion: 123,
|
91 | Platform: "browser",
|
92 | Severity: "DEBUG",
|
93 | Data: "",
|
94 | Timestamp: "",
|
95 | Message: "",
|
96 | Category: ""
|
97 | };
|
98 |
|
99 | const serviceConfig = {
|
100 | url: "https://www.google.nl",
|
101 | sourceName: "advancedLoggerTest",
|
102 | host: "advanced-logger",
|
103 | sourceCategory: "MY/SUMO/namespace",
|
104 | method: "POST"
|
105 | };
|
106 |
|
107 | const config = {serviceConfig, defaultLogConfig};
|
108 |
|
109 | const logger = new AdvancedLogger({
|
110 | service: new service.SumologicService(config),
|
111 | strategy: new strategy.InstantStrategy()
|
112 | });
|
113 |
|
114 | logger.log({test: "instant log u1"});
|
115 | logger.log({test: "instant log u2"});
|
116 | logger.log({test: "instant log u3"});
|
117 | ```
|
118 |
|
119 | ### Strategies
|
120 |
|
121 | Strategies are components that "know" when is it right time to send logs.
|
122 |
|
123 | There are next strategies available:
|
124 |
|
125 | * InstantStrategy
|
126 | * OnBundleSizeStrategy
|
127 | * OnIntervalStrategy
|
128 | * OnRequestStrategy
|
129 |
|
130 | #### InstantStrategy
|
131 |
|
132 | Does not require parameters. It just sends the log as soon as it appears in logger.
|
133 |
|
134 | ```javascript
|
135 | const {strategy} = require("advanced-logger");
|
136 | const strategy = new strategy.InstantStrategy();
|
137 | ```
|
138 |
|
139 | #### OnBundleSizeStrategy
|
140 |
|
141 | Can accept a configuration object with an optional "maxBundle" value, which determines what is a maximal amount of logs it should collect before sending to the service. Default number is 100.
|
142 |
|
143 | ```javascript
|
144 | const {strategy} = require("advanced-logger");
|
145 | const config = {
|
146 | maxBundle: 123
|
147 | };
|
148 | const strategy = new strategy.OnBundleSizeStrategy(config);
|
149 | ```
|
150 |
|
151 | #### OnIntervalStrategy
|
152 |
|
153 | Can accept a configuration object with an optional "interval" value, which determines what is a time interval for collecting logs before sending them to the service. Default number is 15000.
|
154 |
|
155 | ```javascript
|
156 | const {strategy} = require("advanced-logger");
|
157 | const config = {
|
158 | interval: 10000
|
159 | };
|
160 | const strategy = new strategy.OnIntervalStrategy(config);
|
161 | ```
|
162 |
|
163 | #### OnRequestStrategy
|
164 |
|
165 | This strategy does not do anything :) . It will send logs only after manual call to ```logger.sendAllLogs();``` method.
|
166 |
|
167 | ```javascript
|
168 | const {strategy} = require("advanced-logger");
|
169 |
|
170 | const strategy = new strategy.OnRequestStrategy();
|
171 |
|
172 | //"logger" is an instance of AdvancedLogger
|
173 |
|
174 | logger.sendAllLogs();
|
175 | ```
|
176 |
|
177 | #### Custom implementation of strategy
|
178 |
|
179 | TODO
|
180 |
|
181 | ### Services
|
182 |
|
183 | Currently, module supports only Sumologic and Loggly services out of the box.
|
184 |
|
185 | #### Sumologic (see https://www.sumologic.com/)
|
186 |
|
187 | ```javascript
|
188 | //Configuration for communication with Sumologic.
|
189 | //Url should be taken from the logger's source category configuration page.
|
190 | const serviceConfig = {
|
191 | url: "https://www.google.nl",
|
192 | sourceName: "advancedLoggerTest",
|
193 | host: "advanced-logger",
|
194 | sourceCategory: "MY/SUMO/namespace",
|
195 | method: "POST"
|
196 | };
|
197 |
|
198 | //Default log configuration.
|
199 | //It is used like a template with default values for each new log.
|
200 | //Can be of any structure. It will be shallowly copied during creation of a new log record.
|
201 | const defaultLogConfig = {
|
202 | UserAgent: window.userAgent,
|
203 | BuildVersion: 123,
|
204 | Platform: "browser",
|
205 | Severity: "DEBUG",
|
206 | Data: "",
|
207 | Timestamp: "",
|
208 | Message: "",
|
209 | Category: ""
|
210 | };
|
211 |
|
212 | //general config
|
213 | const config = {serviceConfig, defaultLogConfig};
|
214 |
|
215 | const service = new service.SumologicService(config);
|
216 | ```
|
217 |
|
218 | #### Loggly (see https://www.loggly.com/)
|
219 |
|
220 | ```javascript
|
221 | //Configuration for communication with Loggly.
|
222 | //Url should be taken from the logger's source category configuration page.
|
223 | const serviceConfig = {
|
224 | // this should be the url for **bulk** log sending
|
225 | url: "https://logs-01.loggly.com/bulk/<customertoken>/tag/bulk/",
|
226 | method: "POST"
|
227 | };
|
228 |
|
229 | //Default log configuration.
|
230 | //It is used like a template with default values for each new log.
|
231 | //Can be of any structure. It will be shallowly copied during creation of a new log record.
|
232 | const defaultLogConfig = {
|
233 | UserAgent: window.userAgent,
|
234 | BuildVersion: 123,
|
235 | Platform: "browser",
|
236 | Severity: "DEBUG",
|
237 | Data: "",
|
238 | Timestamp: "",
|
239 | Message: "",
|
240 | Category: ""
|
241 | };
|
242 |
|
243 | //general config
|
244 | const config = {serviceConfig, defaultLogConfig};
|
245 |
|
246 | const service = new service.LogglyService(config);
|
247 | ```
|
248 |
|
249 | #### Elastic Search Service (see https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg-upload-data.html)
|
250 |
|
251 | Logger supports sending data to Elasticsearch service endpoint. It was tested on AWS-based instance of Elasticsearch and Kibana. Ideally, it should work also on instance of any other cloud provider.
|
252 |
|
253 | ```javascript
|
254 | //Configuration for communication with Elastic Search.
|
255 | //Url should be taken from the logger's source category configuration page.
|
256 | const serviceConfig = {
|
257 | // this should be the url for **bulk** log sending
|
258 | url: "https://<endpoint_url>/_bulk",
|
259 | method: "POST",
|
260 | //this field will be used to send index value in meta information for each log
|
261 | logMetaIndexField: "IndexField"
|
262 | };
|
263 |
|
264 | //Default log configuration.
|
265 | //It is used like a template with default values for each new log.
|
266 | //Can be of any structure. It will be shallowly copied during creation of a new log record.
|
267 | const defaultLogConfig = {
|
268 | BuildVersion: 123,
|
269 | Platform: "browser",
|
270 | Severity: "DEBUG",
|
271 | Data: "",
|
272 | Timestamp: "",
|
273 | Message: "",
|
274 | IndexField: "web-app"
|
275 | };
|
276 |
|
277 | //general config
|
278 | const config = {serviceConfig, defaultLogConfig};
|
279 |
|
280 | const service = new service.ElasticsearchService(config);
|
281 | ```
|
282 |
|
283 | #### Custom serializer
|
284 |
|
285 | There are situations when you need a "special" representation of logs instead of JSON before sending them to remote storage. For example, key-value pairs:
|
286 |
|
287 | ```
|
288 | [Timestamp=1234567890] [Message="test message"] [Category="MyController"]
|
289 | ```
|
290 |
|
291 | In order to serialize logs in your own way, you can use ```serializer``` configuration with services:
|
292 |
|
293 | ```javascript
|
294 | const serializer = logObject =>
|
295 | Object.keys(logObject)
|
296 | .map(key => `[${key}=${JSON.stringify(logObject[key])}]`)
|
297 | .join(" ");
|
298 |
|
299 | const configWithSerializer = {serviceConfig, defaultLogConfig, serializer};
|
300 | const testLogs = [
|
301 | {test: "test123"},
|
302 | {test: "test321"}
|
303 | ];
|
304 |
|
305 | service = new LogglyService(configWithSerializer);
|
306 | ```
|
307 |
|
308 | #### Custom implementation of service
|
309 |
|
310 | TODO
|
311 |
|
312 | ## Development
|
313 |
|
314 | ### Build and debugging
|
315 |
|
316 | In order to run full build of all bundles run:
|
317 | ```
|
318 | npm run build
|
319 | ```
|
320 |
|
321 | This script will create all types of build:
|
322 | * browser compressed
|
323 | * browser debugging
|
324 | * nodejs compressed (do we need it? :) )
|
325 | * nodejs debugging
|
326 |
|
327 | Also, you can run a specific build for each platform separately:
|
328 | ```
|
329 | npm run build-prod-browser
|
330 | npm run build-prod-node
|
331 | npm run build-dev-browser
|
332 | npm run build-dev-node
|
333 | ```
|
334 |
|
335 | For debugging purposes it should be convenient to use the watch mode:
|
336 |
|
337 | ```
|
338 | npm run watch-prod-browser
|
339 | npm run watch-prod-node
|
340 | npm run watch-dev-browser
|
341 | npm run watch-dev-node
|
342 | ```
|
343 |
|
344 | ### Running tests
|
345 |
|
346 | In order to run unit tests run:
|
347 |
|
348 | ```
|
349 | npm run test
|
350 | ```
|
351 |
|
352 | In order to run unit tests with coverage run:
|
353 |
|
354 | ```
|
355 | npm run coverage
|
356 | ```
|
357 |
|
358 | It will build a beautiful code coverage report which you can check by running html file ```coverage/lcov-report/index.html```.
|
359 |
|
360 | ### Deployment
|
361 |
|
362 | Please, find the ```.travis.yml``` file for the library lifecycle: install -> test -> build -> sonar analysis -> deploy.
|
363 |
|
364 | In order to deploy a new version, you need to run:
|
365 |
|
366 | ```
|
367 | npx standard-version
|
368 | ```
|
369 |
|
370 | This command bumps up the library version in all required files, builds the changelog and makes a new commit with a "version" tag. Using this tag travis will assemble and deploy the npm package.
|
371 |
|
372 | **Please note**, that releasing happens only from master branch for each tagged commit.
|
373 |
|
374 | ### Git workflow
|
375 |
|
376 | #### Commits
|
377 |
|
378 | Commits should follow the "conventional commit" agreement. It will be validated by Husky plugin on pre-commit git hook.
|
379 |
|
380 | #### Branches and pull requests
|
381 |
|
382 | Feel free to do anything you want in branches. All final commits should be rebased and clean. Please, create pull request for delivering your changes to master. All PR checks should be green. All sonar suggestions should be resolved and/or discussed if not applicable.
|
383 |
|
384 | ## Thanks to
|
385 |
|
386 | creators of https://github.com/DxCx/ts-library-starter. Their repository was used as a start point for the library
|
387 |
|
\ | No newline at end of file |