Skip to content

Commit 02c8d19

Browse files
committed
feat: add optional logFile argument for ConsumerPact/ConsumerMessagePact/VerifierOptions
1 parent d6f6034 commit 02c8d19

File tree

10 files changed

+86
-27
lines changed

10 files changed

+86
-27
lines changed

native/addon.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Napi::Object Init(Napi::Env env, Napi::Object exports) {
88
exports.Set(Napi::String::New(env, "pactffiVersion"), Napi::Function::New(env, PactffiVersion));
99
exports.Set(Napi::String::New(env, "pactffiInit"), Napi::Function::New(env, PactffiInit));
1010
exports.Set(Napi::String::New(env, "pactffiInitWithLogLevel"), Napi::Function::New(env, PactffiInitWithLogLevel));
11+
exports.Set(Napi::String::New(env, "pactffiLogToFile"), Napi::Function::New(env, PactffiLogToFile));
1112

1213
// Consumer
1314
exports.Set(Napi::String::New(env, "pactffiMockServerMatched"), Napi::Function::New(env, PactffiMockServerMatched));

native/ffi.cc

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,64 @@ Napi::Value PactffiInitWithLogLevel(const Napi::CallbackInfo& info) {
4949
return env.Undefined();
5050
}
5151

52+
LevelFilter integerToLevelFilter(Napi::Env &env, uint32_t number) {
53+
LevelFilter logLevel = LevelFilter::LevelFilter_Off;
54+
55+
switch(number) {
56+
case 0:
57+
logLevel = LevelFilter::LevelFilter_Off;
58+
break;
59+
case 1:
60+
logLevel = LevelFilter::LevelFilter_Error;
61+
break;
62+
case 2:
63+
logLevel = LevelFilter::LevelFilter_Warn;
64+
break;
65+
case 3:
66+
logLevel = LevelFilter::LevelFilter_Info;
67+
break;
68+
case 4:
69+
logLevel = LevelFilter::LevelFilter_Debug;
70+
break;
71+
case 5:
72+
logLevel = LevelFilter::LevelFilter_Trace;
73+
break;
74+
default:
75+
std::string err = "pact-js-core C integration: Unable to parse log level number: ";
76+
err += number;
77+
78+
throw Napi::Error::New(env, err);
79+
}
80+
81+
return logLevel;
82+
}
83+
84+
85+
Napi::Value PactffiLogToFile(const Napi::CallbackInfo& info) {
86+
// return: int
87+
Napi::Env env = info.Env();
88+
89+
if (info.Length() < 2) {
90+
throw Napi::Error::New(env, "PactffiLogToFile(envVar) received < 2 arguments");
91+
}
92+
93+
if (!info[0].IsString()) {
94+
throw Napi::Error::New(env, "PactffiLogToFile(envVar) expected a string");
95+
}
96+
97+
if (!info[1].IsNumber()) {
98+
throw Napi::Error::New(env, "PactffiLogToFile(envVar) expected a number");
99+
}
100+
101+
// Extract log level
102+
std::string fileName = info[0].As<Napi::String>().Utf8Value();
103+
uint32_t levelFilterNumber = info[1].As<Napi::Number>().Uint32Value();
104+
LevelFilter levelFilter = integerToLevelFilter(env, levelFilterNumber);
105+
106+
int res = pactffi_log_to_file(fileName.c_str(), levelFilter);
107+
108+
return Napi::Number::New(env, res);
109+
}
52110
/*
53111
54112
Napi::Value Pactffi_log_message(const Napi::CallbackInfo& info) {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116
"build": "tsc --project tsconfig.build.json",
117117
"prerelease": "npm run snyk-protect",
118118
"release": "commit-and-tag-version",
119-
"test": "cross-env LOGLEVEL=debug PACT_DO_NOT_TRACK=true mocha \"{src,test}/**/*.spec.ts\"",
119+
"test": "cross-env PACT_DO_NOT_TRACK=true mocha \"{src,test}/**/*.spec.ts\"",
120120
"snyk-protect": "snyk-protect",
121121
"format:base": "prettier --parser typescript",
122122
"format:check": "npm run format:base -- --list-different \"{src,test}/**/*.{ts,tsx}\"",

src/consumer/index.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,13 @@ export const makeConsumerPact = (
6262
consumer: string,
6363
provider: string,
6464
version: FfiSpecificationVersion = 3,
65-
logLevel = getLogLevel()
65+
logLevel = getLogLevel(),
66+
logFile?: string
6667
): ConsumerPact => {
67-
const ffi = getFfiLib(logLevel);
6868
if (logLevel) {
6969
setLogLevel(logLevel);
7070
}
71+
const ffi = getFfiLib(logLevel, logFile);
7172

7273
const pactPtr = ffi.pactffiNewPact(consumer, provider);
7374
if (!ffi.pactffiWithSpecification(pactPtr, version)) {
@@ -370,12 +371,13 @@ export const makeConsumerMessagePact = (
370371
consumer: string,
371372
provider: string,
372373
version: FfiSpecificationVersion = 4,
373-
logLevel = getLogLevel()
374+
logLevel = getLogLevel(),
375+
logFile?: string
374376
): ConsumerMessagePact => {
375-
const ffi = getFfiLib(logLevel);
376377
if (logLevel) {
377378
setLogLevel(logLevel);
378379
}
380+
const ffi = getFfiLib(logLevel, logFile);
379381

380382
const pactPtr = ffi.pactffiNewPact(consumer, provider);
381383
if (!ffi.pactffiWithSpecification(pactPtr, version) || version < 4) {

src/ffi/index.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import path from 'node:path';
22
import bindings = require('node-gyp-build');
33
import logger, { DEFAULT_LOG_LEVEL } from '../logger';
44
import { LogLevel } from '../logger/types';
5-
import { Ffi } from './types';
5+
import { Ffi, FfiLogLevelFilter } from './types';
66

77
export const PACT_FFI_VERSION = '0.4.22';
88

@@ -85,18 +85,15 @@ const renderBinaryErrorMessage = (error: unknown) => {
8585
};
8686

8787
let ffi: typeof ffiLib;
88-
let ffiLogLevel: LogLevel;
8988

90-
const initialiseFfi = (logLevel: LogLevel): typeof ffi => {
89+
const initialiseFfi = (): typeof ffi => {
9190
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
9291
// @ts-ignore
9392
if (process.stdout._handle) {
9493
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
9594
// @ts-ignore
9695
process.stdout._handle.setBlocking(true);
9796
}
98-
logger.debug(`Initalising native core at log level '${logLevel}'`);
99-
ffiLogLevel = logLevel;
10097
try {
10198
bindingPaths.every((bindingPath, i) => {
10299
try {
@@ -114,7 +111,6 @@ const initialiseFfi = (logLevel: LogLevel): typeof ffi => {
114111
return true;
115112
}
116113
});
117-
ffiLib.pactffiInitWithLogLevel(logLevel);
118114
} catch (error) {
119115
renderBinaryErrorMessage(error);
120116
throw new Error(
@@ -125,18 +121,24 @@ const initialiseFfi = (logLevel: LogLevel): typeof ffi => {
125121
};
126122

127123
export const getFfiLib = (
128-
logLevel: LogLevel = DEFAULT_LOG_LEVEL
124+
logLevel: LogLevel = DEFAULT_LOG_LEVEL,
125+
logFile: string | undefined = undefined
129126
): typeof ffi => {
130127
if (!ffi) {
131-
logger.trace('Initiliasing ffi for the first time');
132-
ffi = initialiseFfi(logLevel);
133-
} else {
134-
logger.trace('Ffi has already been initialised, no need to repeat it');
135-
if (logLevel !== ffiLogLevel) {
136-
logger.warn(
137-
`The pact native core has already been initialised at log level '${ffiLogLevel}'`
128+
logger.trace('Initialising ffi for the first time');
129+
ffi = initialiseFfi();
130+
logger.debug(
131+
`Initialising native core at log level '${logLevel}'`,
132+
logFile
133+
);
134+
if (logFile) {
135+
logger.debug(
136+
`writing log file at level ${FfiLogLevelFilter[logLevel]} to ${logFile}`
138137
);
139-
logger.warn(`The new requested log level '${logLevel}' will be ignored`);
138+
const res = ffiLib.pactffiLogToFile(logFile, FfiLogLevelFilter[logLevel]);
139+
logger.debug(`result of writing to file '${res}'`);
140+
} else {
141+
ffiLib.pactffiInitWithLogLevel(logLevel);
140142
}
141143
}
142144
return ffi;

src/verifier/nativeVerifier.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const verify = (opts: VerifierOptions): Promise<string> => {
1414
if (opts.logLevel) {
1515
setLogLevel(opts.logLevel);
1616
}
17-
const ffi = getFfiLib(opts.logLevel);
17+
const ffi = getFfiLib(opts.logLevel, opts.logFile);
1818

1919
const handle = ffi.pactffiVerifierNewForApplication(
2020
pkg.name.split('/')[1],

src/verifier/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export interface VerifierOptions {
4646
consumerVersionSelectors?: ConsumerVersionSelector[];
4747
timeout?: number;
4848
logLevel?: LogLevel;
49+
logFile?: string;
4950
disableSslVerification?: boolean;
5051
buildUrl?: string;
5152
customProviderHeaders?: CustomHeaders | string[];

src/verifier/validateOptions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ export const validationRules: ArgumentValidationRules<InternalPactVerifierOption
247247
verbose: [deprecatedFunction],
248248
monkeypatch: [deprecatedFunction],
249249
logDir: [deprecatedFunction],
250+
logFile: [assertNonEmptyString],
250251
consumerFilters: [assertNonEmptyString],
251252
failIfNoPactsFound: [assertBoolean],
252253
transports: [],

test/consumer.integration.spec.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import zlib = require('zlib');
77
import FormData = require('form-data');
88
import fs = require('fs');
99
import { load } from 'protobufjs';
10-
import { setLogLevel } from '../src/logger';
1110
import {
1211
ConsumerPact,
1312
makeConsumerPact,
@@ -21,8 +20,6 @@ const { expect } = chai;
2120
const HOST = '127.0.0.1';
2221

2322
describe('FFI integration test for the HTTP Consumer API', () => {
24-
setLogLevel('trace');
25-
2623
let port: number;
2724
let pact: ConsumerPact;
2825
const bytes: Buffer = zlib.gzipSync('this is an encoded string');

test/matt.consumer.integration.spec.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
makeConsumerMessagePact,
1010
makeConsumerPact,
1111
} from '../src';
12-
import { setLogLevel } from '../src/logger';
1312
import { FfiSpecificationVersion } from '../src/ffi/types';
1413

1514
chai.use(chaiAsPromised);
@@ -45,8 +44,6 @@ const sendMattMessageTCP = (
4544

4645
const skipPluginTests = process.env['SKIP_PLUGIN_TESTS'] === 'true';
4746
(skipPluginTests ? describe.skip : describe)('MATT protocol test', () => {
48-
setLogLevel('trace');
49-
5047
let provider: ConsumerPact;
5148
let tcpProvider: ConsumerMessagePact;
5249
let port: number;

0 commit comments

Comments
 (0)