source: trip-planner-front/node_modules/log4js/lib/categories.js@ b738035

Last change on this file since b738035 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 7.0 KB
Line 
1const debug = require('debug')('log4js:categories');
2const configuration = require('./configuration');
3const levels = require('./levels');
4const appenders = require('./appenders');
5
6const categories = new Map();
7
8/**
9 * Add inherited config to this category. That includes extra appenders from parent,
10 * and level, if none is set on this category.
11 * This is recursive, so each parent also gets loaded with inherited appenders.
12 * Inheritance is blocked if a category has inherit=false
13 * @param {*} config
14 * @param {*} category the child category
15 * @param {string} categoryName dotted path to category
16 * @return {void}
17 */
18function inheritFromParent(config, category, categoryName) {
19 if (category.inherit === false) return;
20 const lastDotIndex = categoryName.lastIndexOf('.');
21 if (lastDotIndex < 0) return; // category is not a child
22 const parentCategoryName = categoryName.substring(0, lastDotIndex);
23 let parentCategory = config.categories[parentCategoryName];
24
25
26 if (!parentCategory) {
27 // parent is missing, so implicitly create it, so that it can inherit from its parents
28 parentCategory = { inherit: true, appenders: [] };
29 }
30
31 // make sure parent has had its inheritance taken care of before pulling its properties to this child
32 inheritFromParent(config, parentCategory, parentCategoryName);
33
34 // if the parent is not in the config (because we just created it above),
35 // and it inherited a valid configuration, add it to config.categories
36 if (!config.categories[parentCategoryName]
37 && parentCategory.appenders
38 && parentCategory.appenders.length
39 && parentCategory.level) {
40 config.categories[parentCategoryName] = parentCategory;
41 }
42
43 category.appenders = category.appenders || [];
44 category.level = category.level || parentCategory.level;
45
46 // merge in appenders from parent (parent is already holding its inherited appenders)
47 parentCategory.appenders.forEach((ap) => {
48 if (!category.appenders.includes(ap)) {
49 category.appenders.push(ap);
50 }
51 });
52 category.parent = parentCategory;
53}
54
55
56/**
57 * Walk all categories in the config, and pull down any configuration from parent to child.
58 * This includes inherited appenders, and level, where level is not set.
59 * Inheritance is skipped where a category has inherit=false.
60 * @param {*} config
61 */
62function addCategoryInheritance(config) {
63 if (!config.categories) return;
64 const categoryNames = Object.keys(config.categories);
65 categoryNames.forEach((name) => {
66 const category = config.categories[name];
67 // add inherited appenders and level to this category
68 inheritFromParent(config, category, name);
69 });
70}
71
72configuration.addPreProcessingListener(config => addCategoryInheritance(config));
73
74configuration.addListener((config) => {
75 configuration.throwExceptionIf(
76 config,
77 configuration.not(configuration.anObject(config.categories)),
78 'must have a property "categories" of type object.'
79 );
80
81 const categoryNames = Object.keys(config.categories);
82 configuration.throwExceptionIf(
83 config,
84 configuration.not(categoryNames.length),
85 'must define at least one category.'
86 );
87
88 categoryNames.forEach((name) => {
89 const category = config.categories[name];
90 configuration.throwExceptionIf(
91 config,
92 [
93 configuration.not(category.appenders),
94 configuration.not(category.level)
95 ],
96 `category "${name}" is not valid (must be an object with properties "appenders" and "level")`
97 );
98
99 configuration.throwExceptionIf(
100 config,
101 configuration.not(Array.isArray(category.appenders)),
102 `category "${name}" is not valid (appenders must be an array of appender names)`
103 );
104
105 configuration.throwExceptionIf(
106 config,
107 configuration.not(category.appenders.length),
108 `category "${name}" is not valid (appenders must contain at least one appender name)`
109 );
110
111 if (Object.prototype.hasOwnProperty.call(category, 'enableCallStack')) {
112 configuration.throwExceptionIf(
113 config,
114 typeof category.enableCallStack !== 'boolean',
115 `category "${name}" is not valid (enableCallStack must be boolean type)`
116 );
117 }
118
119 category.appenders.forEach((appender) => {
120 configuration.throwExceptionIf(
121 config,
122 configuration.not(appenders.get(appender)),
123 `category "${name}" is not valid (appender "${appender}" is not defined)`
124 );
125 });
126
127 configuration.throwExceptionIf(
128 config,
129 configuration.not(levels.getLevel(category.level)),
130 `category "${name}" is not valid (level "${category.level}" not recognised;`
131 + ` valid levels are ${levels.levels.join(', ')})`
132 );
133 });
134
135 configuration.throwExceptionIf(
136 config,
137 configuration.not(config.categories.default),
138 'must define a "default" category.'
139 );
140});
141
142const setup = (config) => {
143 categories.clear();
144
145 const categoryNames = Object.keys(config.categories);
146 categoryNames.forEach((name) => {
147 const category = config.categories[name];
148 const categoryAppenders = [];
149 category.appenders.forEach((appender) => {
150 categoryAppenders.push(appenders.get(appender));
151 debug(`Creating category ${name}`);
152 categories.set(
153 name,
154 {
155 appenders: categoryAppenders,
156 level: levels.getLevel(category.level),
157 enableCallStack: category.enableCallStack || false
158 }
159 );
160 });
161 });
162};
163
164setup({ categories: { default: { appenders: ['out'], level: 'OFF' } } });
165configuration.addListener(setup);
166
167const configForCategory = (category) => {
168 debug(`configForCategory: searching for config for ${category}`);
169 if (categories.has(category)) {
170 debug(`configForCategory: ${category} exists in config, returning it`);
171 return categories.get(category);
172 }
173 if (category.indexOf('.') > 0) {
174 debug(`configForCategory: ${category} has hierarchy, searching for parents`);
175 return configForCategory(category.substring(0, category.lastIndexOf('.')));
176 }
177 debug('configForCategory: returning config for default category');
178 return configForCategory('default');
179};
180
181const appendersForCategory = category => configForCategory(category).appenders;
182const getLevelForCategory = category => configForCategory(category).level;
183
184const setLevelForCategory = (category, level) => {
185 let categoryConfig = categories.get(category);
186 debug(`setLevelForCategory: found ${categoryConfig} for ${category}`);
187 if (!categoryConfig) {
188 const sourceCategoryConfig = configForCategory(category);
189 debug('setLevelForCategory: no config found for category, '
190 + `found ${sourceCategoryConfig} for parents of ${category}`);
191 categoryConfig = { appenders: sourceCategoryConfig.appenders };
192 }
193 categoryConfig.level = level;
194 categories.set(category, categoryConfig);
195};
196
197const getEnableCallStackForCategory = category => configForCategory(category).enableCallStack === true;
198const setEnableCallStackForCategory = (category, useCallStack) => {
199 configForCategory(category).enableCallStack = useCallStack;
200};
201
202module.exports = {
203 appendersForCategory,
204 getLevelForCategory,
205 setLevelForCategory,
206 getEnableCallStackForCategory,
207 setEnableCallStackForCategory,
208};
Note: See TracBrowser for help on using the repository browser.