Skip to content

Commit aa64f08

Browse files
authored
[Feature] otel context injection (#133)
* Add `_addOpentelemetryContext()` * update dependencies * Add unit tests * Update dependencies * Update log * Add `addOtelContext` configuration option * docs * refactor tests
1 parent 540ad6f commit aa64f08

File tree

5 files changed

+335
-29
lines changed

5 files changed

+335
-29
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ logger.log(obj);
5454
* **compress** - If true the the logs are compressed in gzip format. Default: `false`
5555
* **internalLogger** - set internal logger that supports the function log. Default: console.
5656
* **extraFields** - Adds your own custom fields to each log. Add in JSON Format, for example: `extraFields : { field_1: "val_1", field_2: "val_2" , ... }`.
57+
* **addOtelContext** - Add `trace_id`, `span_id`, `service_name` fields to logs when opentelemetry context is available. Default: `true`
5758

5859

5960
## Using UDP
@@ -99,6 +100,17 @@ logger.log('This is a log message');
99100
}
100101
```
101102

103+
## Add opentelemetry context
104+
If you're sending traces with OpenTelemetry instrumentation (auto or manual), you can correlate your logs with the trace context. That way, your logs will have traces data in it, such as service name, span id and trace id (version >= `2.2.0`). This feature is enabled by default, To disable it, set the `AddOtelContext` param in your handler configuration to `false`, like in this example:
105+
106+
```javascript
107+
var logger = require('logzio-nodejs').createLogger({
108+
token: 'token',
109+
type: 'no-otel-context',
110+
addOtelContext: false
111+
});
112+
```
113+
102114
## Build and test locally
103115
1. Clone the repository:
104116
```bash
@@ -112,6 +124,10 @@ logger.log('This is a log message');
112124
```
113125

114126
## Update log
127+
**2.2.0**
128+
- Add `addOtelContext` configuration option:
129+
- `trace_id`, `span_id`, `service_name` fields to logs when opentelemetry context is available.
130+
115131
**2.1.8**
116132
- Make `User-Agent` not optional and add the version to it.
117133

lib/logzio-nodejs.js

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const assign = require('lodash.assign');
44
const dgram = require('dgram');
55
const zlib = require('zlib');
66
const axiosInstance = require('./axiosInstance');
7-
7+
const { trace, context } = require('@opentelemetry/api');
88

99
const nanoSecDigits = 9;
1010

@@ -53,6 +53,7 @@ class LogzioLogger {
5353
protocol = 'http',
5454
port,
5555
timeout,
56+
addOtelContext = true,
5657
sleepUntilNextRetry = 2 * 1000,
5758
callback = this._defaultCallback,
5859
extraFields = {},
@@ -103,11 +104,13 @@ class LogzioLogger {
103104
this.timeout = timeout;
104105

105106
// build the url for logging
106-
107107
this.messages = [];
108108
this.bulkId = 1;
109109
this.extraFields = extraFields;
110110
this.typeOfIP = 'IPv4';
111+
112+
// OpenTelemetry context
113+
this.addOtelContext = addOtelContext
111114
}
112115

113116
_setProtocol(port) {
@@ -231,31 +234,47 @@ class LogzioLogger {
231234
}
232235
}
233236
}
234-
237+
/**
238+
* Attach OpenTelemetry context to the log record.
239+
* @param msg - The message (Object) to append the OpenTelemetry context to.
240+
* @private
241+
*/
242+
_addOpentelemetryContext(msg) {
243+
if (!this.addOtelContext) {
244+
return;
245+
}
246+
let span = trace.getSpan(context.active());
247+
if (span) {
248+
msg.trace_id = span.spanContext().traceId;
249+
msg.span_id = span.spanContext().spanId;
250+
msg.service_name = span.resource._attributes['service.name'];
251+
}
252+
}
235253
log(msg, obj) {
236-
if (this.closed === true) {
237-
throw new Error('Logging into a logger that has been closed!');
238-
}
239-
if (![null, undefined].includes(obj)) {
240-
msg += JSON.stringify(obj);
241-
}
242-
if (typeof msg === 'string') {
243-
msg = {
244-
message: msg,
245-
};
246-
}
247-
this._addSourceIP(msg);
248-
msg = assign(msg, this.extraFields);
249-
if (!msg.type) {
250-
msg.type = this.type;
251-
}
252-
this._addTimestamp(msg);
253-
254-
this.messages.push(msg);
255-
if (this.messages.length >= this.bufferSize) {
256-
this._debug('Buffer is full - sending bulk');
257-
this._popMsgsAndSend();
258-
}
254+
if (this.closed === true) {
255+
throw new Error('Logging into a logger that has been closed!');
256+
}
257+
if (![null, undefined].includes(obj)) {
258+
msg += JSON.stringify(obj);
259+
}
260+
if (typeof msg === 'string') {
261+
msg = { message: msg };
262+
}
263+
264+
this._addSourceIP(msg);
265+
msg = assign(msg, this.extraFields);
266+
if (!msg.type) {
267+
msg.type = this.type;
268+
}
269+
this._addTimestamp(msg);
270+
this._addOpentelemetryContext(msg);
271+
272+
273+
this.messages.push(msg);
274+
if (this.messages.length >= this.bufferSize) {
275+
this._debug('Buffer is full - sending bulk');
276+
this._popMsgsAndSend();
277+
}
259278
}
260279

261280
_popMsgsAndSend() {

package-lock.json

Lines changed: 224 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)