Skip to content

Commit

Permalink
[Monitor OpenTelemetry] Add Winston Log Instrumentation (#29321)
Browse files Browse the repository at this point in the history
### Packages impacted by this PR
@azure/monitor-opentelemetry

Adds support for winston log instrumentation.
  • Loading branch information
JacksonWeber committed Apr 26, 2024
1 parent bd4ccb1 commit 3aa135f
Show file tree
Hide file tree
Showing 11 changed files with 1,003 additions and 532 deletions.
1,464 changes: 936 additions & 528 deletions common/config/rush/pnpm-lock.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions sdk/monitor/monitor-opentelemetry/CHANGELOG.md
Expand Up @@ -17,6 +17,7 @@
### Features Added

- Add support for Trace based sampling for logs.
- Add support for Winston log instrumentation.

### Bugs Fixed

Expand Down
7 changes: 5 additions & 2 deletions sdk/monitor/monitor-opentelemetry/README.md
Expand Up @@ -72,6 +72,7 @@ const options: AzureMonitorOpenTelemetryOptions = {
redis4: { enabled: true },
// Instrumentations generating logs
bunyan: { enabled: true },
winston: { enabled: true },
},
enableLiveMetrics: true,
enableStandardMetrics: true,
Expand All @@ -92,7 +93,7 @@ useAzureMonitor(options);
| ------------------------------- |------------------------------------------------------------------------------------------------------------|-------|
| azureMonitorExporterOptions | Azure Monitor OpenTelemetry Exporter Configuration. [More info here](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/monitor/monitor-opentelemetry-exporter) | | | |
| samplingRatio | Sampling ratio must take a value in the range [0,1], 1 meaning all data will sampled and 0 all Tracing data will be sampled out. | 1|
| instrumentationOptions| Allow configuration of OpenTelemetry Instrumentations. | {"http": { enabled: true },"azureSdk": { enabled: false },"mongoDb": { enabled: false },"mySql": { enabled: false },"postgreSql": { enabled: false },"redis": { enabled: false },"bunyan": { enabled: false }}|
| instrumentationOptions| Allow configuration of OpenTelemetry Instrumentations. | {"http": { enabled: true },"azureSdk": { enabled: false },"mongoDb": { enabled: false },"mySql": { enabled: false },"postgreSql": { enabled: false },"redis": { enabled: false },"bunyan": { enabled: false }, "winston": { enabled: false } }|
| browserSdkLoaderOptions| Allow configuration of Web Instrumentations. | { enabled: false, connectionString: "" } |
| resource | Opentelemetry Resource. [More info here](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-resources) ||
| samplingRatio | Sampling ratio must take a value in the range [0,1], 1 meaning all data will sampled and 0 all Tracing data will be sampled out. |1|
Expand Down Expand Up @@ -148,7 +149,9 @@ The following OpenTelemetry Instrumentation libraries are included as part of Az


### Logs
- [Bunyan](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-bunyan)
- [Bunyan](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-bunyan)

- [Winston](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/opentelemetry-instrumentation-winston)

Other OpenTelemetry Instrumentations are available [here](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node) and could be added using TracerProvider in AzureMonitorOpenTelemetryClient.

Expand Down
4 changes: 3 additions & 1 deletion sdk/monitor/monitor-opentelemetry/package.json
Expand Up @@ -109,7 +109,9 @@
"@opentelemetry/sdk-trace-base": "^1.23.0",
"@opentelemetry/sdk-trace-node": "^1.23.0",
"@opentelemetry/semantic-conventions": "^1.23.0",
"tslib": "^2.6.2"
"tslib": "^2.6.2",
"@opentelemetry/instrumentation-winston": "^0.36.0",
"@opentelemetry/winston-transport": "^0.3.0"
},
"sideEffects": false,
"keywords": [
Expand Down
Expand Up @@ -40,6 +40,7 @@ export interface InstrumentationOptions {
postgreSql?: InstrumentationConfig;
redis?: InstrumentationConfig;
redis4?: InstrumentationConfig;
winston?: InstrumentationConfig;
}

// @public
Expand Down
Expand Up @@ -29,6 +29,12 @@ export class AzureBatchLogRecordProcessor extends BatchLogRecordProcessor {
}
}
}
// Ensure nested log attributes are serialized
for (const [key, value] of Object.entries(logRecord.attributes)) {
if (typeof value === "object") {
logRecord.attributes[key] = JSON.stringify(value);
}
}
super.onEmit(logRecord);
}
}
6 changes: 6 additions & 0 deletions sdk/monitor/monitor-opentelemetry/src/logs/handler.ts
Expand Up @@ -4,6 +4,7 @@
import { AzureMonitorLogExporter } from "@azure/monitor-opentelemetry-exporter";
import { Instrumentation } from "@opentelemetry/instrumentation";
import { BunyanInstrumentation } from "@opentelemetry/instrumentation-bunyan";
import { WinstonInstrumentation } from "@opentelemetry/instrumentation-winston";
import { BatchLogRecordProcessor } from "@opentelemetry/sdk-logs";
import { InternalConfig } from "../shared/config";
import { MetricHandler } from "../metrics/handler";
Expand Down Expand Up @@ -59,5 +60,10 @@ export class LogHandler {
new BunyanInstrumentation(this._config.instrumentationOptions.bunyan),
);
}
if (this._config.instrumentationOptions.winston?.enabled) {
this._instrumentations.push(
new WinstonInstrumentation(this._config.instrumentationOptions.winston),
);
}
}
}
4 changes: 4 additions & 0 deletions sdk/monitor/monitor-opentelemetry/src/types.ts
Expand Up @@ -55,6 +55,8 @@ export interface InstrumentationOptions {
redis4?: InstrumentationConfig;
/** Bunyan Instrumentation Config */
bunyan?: InstrumentationConfig;
/** Winston Instrumentation Config */
winston?: InstrumentationConfig;
}

/**
Expand All @@ -69,6 +71,7 @@ export interface StatsbeatOptions {
postgreSql?: boolean;
redis?: boolean;
bunyan?: boolean;
winston?: boolean;
/** Features */
liveMetrics?: boolean;
browserSdkLoader?: boolean;
Expand Down Expand Up @@ -130,4 +133,5 @@ export enum StatsbeatInstrumentation {
REDIS = 8,
POSTGRES = 16,
BUNYAN = 32,
WINSTON = 64,
}
Expand Up @@ -7,6 +7,7 @@ import nock from "nock";
import { successfulBreezeResponse } from "../../utils/breezeTestUtils";
import { TelemetryItem as Envelope } from "../../utils/models/index";

/** TODO: Add winston-transport check functional test */
describe("Log Exporter Scenarios", () => {
describe(LogBasicScenario.prototype.constructor.name, () => {
const scenario = new LogBasicScenario();
Expand Down
Expand Up @@ -78,5 +78,28 @@ describe("AzureBatchLogRecordProcessor", () => {
span.end();
});
});

it("should serialize nested log attributes", async () => {
let memoryLogExporter = new InMemoryLogRecordExporter();
let processor = new AzureBatchLogRecordProcessor(memoryLogExporter, {
enableTraceBasedSamplingForLogs: false,
});
const loggerProvider = new LoggerProvider();
loggerProvider.addLogRecordProcessor(processor);
const sampler = new ApplicationInsightsSampler(1);
const tracerProvider = new NodeTracerProvider({ sampler: sampler });
tracerProvider.getTracer("testTracere").startActiveSpan("test", async (span) => {
// Generate Log record
const logRecord: APILogRecord = {
attributes: { test: { nested: "value" } },
body: "testRecord",
};
loggerProvider.getLogger("testLoggere").emit(logRecord);
await loggerProvider.forceFlush();
span.end();
});
const logRecords = memoryLogExporter.getFinishedLogRecords();
assert.strictEqual(logRecords[0].attributes.test, '{"nested":"value"}');
});
});
});
Expand Up @@ -178,7 +178,7 @@ describe("LogHandler", () => {
});
});

it("Instrumentations", () => {
it("should add bunyan instrumentation", () => {
let config = new InternalConfig();
config.azureMonitorExporterOptions.connectionString =
"InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333";
Expand All @@ -193,5 +193,21 @@ describe("LogHandler", () => {
"Bunyan instrumentation not added",
);
});

it("should add winston instrumentation", () => {
let config = new InternalConfig();
config.azureMonitorExporterOptions.connectionString =
"InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333";
config.instrumentationOptions.winston = {
enabled: true,
};
let logHandler = new LogHandler(config, metricHandler);
assert.ok(logHandler.getInstrumentations().length > 0, "Log instrumentations not added");
assert.strictEqual(
logHandler.getInstrumentations()[0].instrumentationName,
"@opentelemetry/instrumentation-winston",
"Winston instrumentation not added",
);
});
});
});

0 comments on commit 3aa135f

Please sign in to comment.