• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

RobotWebTools / rclnodejs / 19071410104

04 Nov 2025 02:08PM UTC coverage: 83.072% (+0.4%) from 82.711%
19071410104

Pull #1320

github

web-flow
Merge 9cad4567e into 3ad842cc4
Pull Request #1320: feat: add structured error handling with class error hierarchy

1032 of 1365 branches covered (75.6%)

Branch coverage included in aggregate %.

161 of 239 new or added lines in 25 files covered. (67.36%)

29 existing lines in 1 file now uncovered.

2354 of 2711 relevant lines covered (86.83%)

459.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.19
/lib/logging.js
1
// Copyright (c) 2018 Intel Corporation. All rights reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
'use strict';
16

17
const path = require('path');
26✔
18
const rclnodejs = require('./native_loader.js');
26✔
19
const { TypeValidationError } = require('./errors.js');
26✔
20

21
/**
22
 * Enum for LoggingSeverity
23
 * @readonly
24
 * @enum {number}
25
 */
26
let LoggingSeverity = {
26✔
27
  /** @member {number} */
28
  UNSET: 0,
29
  /** @member {number} */
30
  DEBUG: 10,
31
  /** @member {number} */
32
  INFO: 20,
33
  /** @member {number} */
34
  WARN: 30,
35
  /** @member {number} */
36
  ERROR: 40,
37
  /** @member {number} */
38
  FATAL: 50,
39
};
40

41
class Caller {
42
  constructor() {
43
    this._info = {
157✔
44
      functionName: 'unknown',
45
      fileName: 'unknown',
46
      lineNumber: 'unknown',
47
    };
48

49
    const stackLines = new Error().stack.split('\n');
157✔
50

51
    // Adjust the index (usually 3 or 4) to correctly point to the caller frame.
52
    const callerFrame = stackLines[4] || stackLines[3];
157!
53
    // Match both named and anonymous function stack frames.
54
    const frameRegex = /^\s*at\s+(?:(.+)\s+\()?(.+):(\d+):(\d+)\)?$/;
157✔
55
    const match = callerFrame.match(frameRegex);
157✔
56
    if (match && match.length === 5) {
157!
57
      this._info.functionName = match[1] || '(anonymous)';
157✔
58
      this._info.fileName = path.basename(match[2]);
157✔
59
      this._info.lineNumber = match[3];
157✔
60
    } else {
61
      // Handle anonymous functions or different stack formats.
62
      const altMatch = callerFrame.match(/at\s+(.*):(\d+):(\d+)/i);
×
63
      if (altMatch && altMatch.length >= 4) {
×
64
        this._info.functionName = '(anonymous)';
×
65
        this._info.fileName = path.basename(altMatch[1]);
×
66
        this._info.lineNumber = altMatch[2];
×
67
      }
68
    }
69
  }
70

71
  get functionName() {
72
    return this._info.functionName;
157✔
73
  }
74

75
  get lineNumber() {
76
    return this._info.lineNumber;
157✔
77
  }
78

79
  get fileName() {
80
    return this._info.fileName;
157✔
81
  }
82
}
83

84
/**
85
 * @class - Class representing logger in ROS
86
 * @hideconstructor
87
 */
88

89
class Logging {
90
  constructor(name) {
91
    this._name = name;
704✔
92
  }
93

94
  /**
95
   * Set the logging severity level.
96
   * @param {LoggingSeverity} level - The logging severity level.
97
   * @function
98
   * @return {undefined}
99
   */
100
  setLoggerLevel(level) {
101
    if (typeof level !== 'number') {
3!
NEW
102
      throw new TypeValidationError('level', level, 'number', {
×
103
        entityType: 'logger',
104
        entityName: this._name,
105
      });
106
    }
107
    rclnodejs.setLoggerLevel(this._name, level);
3✔
108
  }
109

110
  /**
111
   * Get the logging severity level.
112
   * @function
113
   * @return {LoggingSeverity} - The severity level of the logger.
114
   */
115
  get loggerEffectiveLevel() {
116
    return rclnodejs.getLoggerEffectiveLevel(this._name);
8✔
117
  }
118

119
  /**
120
   * Log a message with the DEBUG severity.
121
   * @param {string} message - message to be logged.
122
   * @function
123
   * @return {bool} Return true if the message has been logged.
124
   */
125
  debug(message) {
126
    return this._log(message, LoggingSeverity.DEBUG);
136✔
127
  }
128

129
  /**
130
   * Log a message with the INFO severity.
131
   * @param {string} message - message to be logged.
132
   * @function
133
   * @return {bool} Return true if the message has been logged.
134
   */
135
  info(message) {
136
    return this._log(message, LoggingSeverity.INFO);
6✔
137
  }
138

139
  /**
140
   * Log a message with the WARN severity.
141
   * @param {string} message - message to be logged.
142
   * @function
143
   * @return {bool} Return true if the message has been logged.
144
   */
145
  warn(message) {
146
    return this._log(message, LoggingSeverity.WARN);
8✔
147
  }
148

149
  /**
150
   * Log a message with the ERROR severity.
151
   * @param {string} message - message to be logged.
152
   * @function
153
   * @return {bool} Return true if the message has been logged.
154
   */
155
  error(message) {
156
    return this._log(message, LoggingSeverity.ERROR);
4✔
157
  }
158

159
  /**
160
   * Log a message with the FATAL severity.
161
   * @param {string} message - message to be logged.
162
   * @function
163
   * @return {bool} Return true if the message has been logged.
164
   */
165
  fatal(message) {
166
    return this._log(message, LoggingSeverity.FATAL);
3✔
167
  }
168

169
  _log(message, severity) {
170
    if (typeof message !== 'string') {
157!
NEW
171
      throw new TypeValidationError('message', message, 'string', {
×
172
        entityType: 'logger',
173
        entityName: this._name,
174
      });
175
    }
176

177
    let caller = new Caller();
157✔
178
    return rclnodejs.log(
157✔
179
      this._name,
180
      severity,
181
      message,
182
      caller.functionName,
183
      parseInt(caller.lineNumber, 10),
184
      caller.fileName
185
    );
186
  }
187

188
  /**
189
   * Get LoggingSeverity enum.
190
   * @function
191
   * @return {LoggingSeverity} Return LoggingSeverity enum.
192
   */
193
  get LoggingSeverity() {
194
    return LoggingSeverity;
11✔
195
  }
196

197
  /**
198
   * Get name of the logger.
199
   * @function
200
   * @return {string} logger's name.
201
   */
202
  get name() {
203
    return this._name;
2✔
204
  }
205

206
  /**
207
   * Create a logger by name.
208
   * @param {string} name - name of the logger.
209
   * @function
210
   * @return {Logging} Return the logger object.
211
   */
212
  static getLogger(name) {
213
    if (typeof name !== 'string') {
14!
NEW
214
      throw new TypeValidationError('name', name, 'string', {
×
215
        entityType: 'logger',
216
      });
217
    }
218
    return new Logging(name);
14✔
219
  }
220
}
221

222
module.exports = Logging;
26✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc