diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8d07dbbc38d..f12588989db 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,6 +13,7 @@ env: ECR_REPO: '720541322708.dkr.ecr.eu-west-2.amazonaws.com/medic' ECR_PUBLIC_REPO: 'public.ecr.aws/medic' COUCHDB_LOG_LEVEL: 'debug' + LOG_LEVEL: 'debug' TAG: ${{ (github.ref_type == 'tag' && github.ref_name) || '' }} BRANCH: ${{ github.head_ref || github.ref_name }} BUILD_NUMBER: ${{ github.run_id }} diff --git a/package.json b/package.json index 7579026f49f..4dcb71308c9 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,8 @@ "build-webapp-dev": "cd webapp && npm run build -- --configuration=development && npm run compile", "build-cht-form": "./scripts/build/build-prepare.sh && cd webapp && npm run build:cht-form", "copy-api-resources": "cp -r api/src/public/* api/build/static/", - "dev-api": "./scripts/build/copy-static-files.sh && (npm run --prefix shared-libs/cht-datasource build-watch & npm run --prefix api run-watch)", - "dev-sentinel": "npm run --prefix shared-libs/cht-datasource build-watch & npm run --prefix sentinel run-watch", + "dev-api": "export LOG_LEVEL=debug && ./scripts/build/copy-static-files.sh && (npm run --prefix shared-libs/cht-datasource build-watch & npm run --prefix api run-watch)", + "dev-sentinel": "export LOG_LEVEL=debug; npm run --prefix shared-libs/cht-datasource build-watch & npm run --prefix sentinel run-watch", "local-images": "export VERSION=$(node ./scripts/build/get-version.js) && ./scripts/build/build-service-images.sh && node scripts/build/cli localDockerComposeFiles", "update-service-worker": "node scripts/build/cli updateServiceWorker", "-- DEV TEST SCRIPTS": "-----------------------------------------------------------------------------------------------", diff --git a/scripts/build/helm/templates/api/deployment.yaml b/scripts/build/helm/templates/api/deployment.yaml index 3d50e406a68..da68bbbe389 100644 --- a/scripts/build/helm/templates/api/deployment.yaml +++ b/scripts/build/helm/templates/api/deployment.yaml @@ -19,6 +19,8 @@ spec: terminationGracePeriodSeconds: 0 containers: - env: + - name: LOG_LEVEL + value: '{{ .Values.api.log_level | default "info" }}' - name: BUILDS_URL value: {{ .Values.upstream_servers.builds_url | default "https://staging.dev.medicmobile.org/_couch/builds_4" }} - name: COUCH_URL diff --git a/scripts/build/helm/templates/sentinel/deployment.yaml b/scripts/build/helm/templates/sentinel/deployment.yaml index 13a05b91455..03f7479ae79 100644 --- a/scripts/build/helm/templates/sentinel/deployment.yaml +++ b/scripts/build/helm/templates/sentinel/deployment.yaml @@ -18,6 +18,8 @@ spec: spec: containers: - env: + - name: LOG_LEVEL + value: '{{ .Values.sentinel.log_level | default "info" }}' - name: API_HOST value: api.{{ .Values.namespace }}.svc.cluster.local - name: COUCH_URL diff --git a/scripts/build/helm/tests/integration-k3d-values.yaml.template b/scripts/build/helm/tests/integration-k3d-values.yaml.template index c14c8fa1fb9..722f7a56197 100644 --- a/scripts/build/helm/tests/integration-k3d-values.yaml.template +++ b/scripts/build/helm/tests/integration-k3d-values.yaml.template @@ -27,3 +27,10 @@ local_storage: preExistingDiskPath-2: "{{{data_path}}}/srv2" preExistingDiskPath-3: "{{{data_path}}}/srv3" +# API log level for integration tests +api: + log_level: "debug" + +# Sentinel log level for integration tests +sentinel: + log_level: "debug" \ No newline at end of file diff --git a/scripts/build/helm/values/base.yaml b/scripts/build/helm/values/base.yaml index f9d03b654ae..28829c0644e 100644 --- a/scripts/build/helm/values/base.yaml +++ b/scripts/build/helm/values/base.yaml @@ -8,6 +8,11 @@ cht_image_tag: "{{cht_image_tag}}" # TEMPLATE: This is a template variable, not api: service: type: ClusterIP # DEFAULT: Good default for internal services + log_level: "info" # DEFAULT: Log level for API service + +# Sentinel Service configuration +sentinel: + log_level: "info" # DEFAULT: Log level for Sentinel service # If images are cached, the same image tag will never be pulled twice. For development, this means that it's not # possible to upgrade to a newer version of the same branch, as the old image will always be reused. diff --git a/shared-libs/logger/src/node-logger.js b/shared-libs/logger/src/node-logger.js index 4488aa17e2b..3744c382d11 100644 --- a/shared-libs/logger/src/node-logger.js +++ b/shared-libs/logger/src/node-logger.js @@ -1,5 +1,7 @@ const { createLogger, format, transports } = require('winston'); -const env = process.env.NODE_ENV || 'development'; +// LOG_LEVEL controls logging globally. Defaults to 'info' if not explicitly set. +const logLevel = process.env.LOG_LEVEL || 'info'; + const cleanUpErrorsFromSymbolProperties = (info) => { if (!info) { @@ -61,7 +63,7 @@ module.exports.create = (dateFormat) => createLogger({ transports: [ new transports.Console({ // change level if in dev environment versus production - level: env === 'development' ? 'debug' : 'info', + level: logLevel, format: format.combine( // https://github.com/winstonjs/winston/issues/1345 format(info => { diff --git a/shared-libs/logger/test/index.spec.js b/shared-libs/logger/test/index.spec.js index 5cf28b171ed..9426af55782 100644 --- a/shared-libs/logger/test/index.spec.js +++ b/shared-libs/logger/test/index.spec.js @@ -123,10 +123,30 @@ describe('node-logger internals', () => { }); describe('create', () => { - it('uses info level in production environment', () => { - nodeLogger.__set__('env', 'production'); - const logger = nodeLogger.create('YYYY-MM-DD'); + it('defaults to info level when LOG_LEVEL is not set', () => { + const originalLogLevel = process.env.LOG_LEVEL; + delete process.env.LOG_LEVEL; + const freshLogger = rewire('../src/node-logger'); + const logger = freshLogger.create('YYYY-MM-DD'); expect(logger).to.be.ok; + expect(freshLogger.__get__('logLevel')).to.equal('info'); + if (originalLogLevel !== undefined) { + process.env.LOG_LEVEL = originalLogLevel; + } + }); + + it('uses LOG_LEVEL when set', () => { + const originalLogLevel = process.env.LOG_LEVEL; + process.env.LOG_LEVEL = 'debug'; + const freshLogger = rewire('../src/node-logger'); + const logger = freshLogger.create('YYYY-MM-DD'); + expect(logger).to.be.ok; + expect(freshLogger.__get__('logLevel')).to.equal('debug'); + if (originalLogLevel !== undefined) { + process.env.LOG_LEVEL = originalLogLevel; + } else { + delete process.env.LOG_LEVEL; + } }); }); diff --git a/tests/cht-core-test.override.yml b/tests/cht-core-test.override.yml new file mode 100644 index 00000000000..b55d0dd8cf2 --- /dev/null +++ b/tests/cht-core-test.override.yml @@ -0,0 +1,7 @@ +services: + api: + environment: + - "LOG_LEVEL=debug" + sentinel: + environment: + - "LOG_LEVEL=debug" diff --git a/tests/utils/index.js b/tests/utils/index.js index 6c854a0b4c6..0e23cfb2aa5 100644 --- a/tests/utils/index.js +++ b/tests/utils/index.js @@ -63,6 +63,7 @@ const CONTAINER_NAMES = {}; const originalTranslations = {}; const COUCH_USER_ID_PREFIX = 'org.couchdb.user:'; const COMPOSE_FILES = ['cht-core', 'cht-couchdb-cluster']; +const COMPOSE_OVERRIDE_FILE = path.resolve(__dirname, '../cht-core-test.override.yml'); const PERMANENT_TYPES = [DOC_TYPES.TRANSLATIONS, 'translations-backup', 'user-settings', 'info']; const db = new PouchDB(`${constants.BASE_URL}/${constants.DB_NAME}`, { auth }); const sentinelDb = new PouchDB(`${constants.BASE_URL}/${constants.DB_NAME}-sentinel`, { auth }); @@ -918,6 +919,7 @@ const listenForApi = async () => { const dockerComposeCmd = (params) => { const composeFiles = COMPOSE_FILES.map(file => ['-f', getTestComposeFilePath(file)]).flat(); + composeFiles.push('-f', COMPOSE_OVERRIDE_FILE); params = `docker compose ${composeFiles.join(' ')} -p ${PROJECT_NAME} ${params}`; return runCommand(params); @@ -1207,7 +1209,8 @@ const generateComposeFiles = async () => { const testComposePath = getTestComposeFilePath(file); const template = await fs.promises.readFile(templatePath, 'utf-8'); - await fs.promises.writeFile(testComposePath, mustache.render(template, view)); + const compiled = mustache.render(template, view); + await fs.promises.writeFile(testComposePath, compiled); } };