diff --git a/ActivatePubKey/__tests__/handler.test.ts b/ActivatePubKey/__tests__/handler.test.ts index aa24754..c79c181 100644 --- a/ActivatePubKey/__tests__/handler.test.ts +++ b/ActivatePubKey/__tests__/handler.test.ts @@ -1,3 +1,4 @@ +import * as jose from "jose"; import * as TE from "fp-ts/lib/TaskEither"; import * as E from "fp-ts/lib/Either"; import { @@ -29,9 +30,14 @@ import { toEncodedJwk } from "../../__mocks__/lollipopPubKey.mock"; import { AssertionRef } from "../../generated/definitions/internal/AssertionRef"; -import { ErrorKind } from "../../utils/errors"; +import { ErrorKind, InternalError } from "../../utils/errors"; import { contextMock } from "../../__mocks__/context.mock"; import { AssertionFileName } from "../../generated/definitions/internal/AssertionFileName"; +import { useWinstonFor } from "@pagopa/winston-ts"; +import { LoggerId } from "@pagopa/winston-ts/dist/types/logging"; +import { withApplicationInsight } from "@pagopa/io-functions-commons/dist/src/utils/transports/application_insight"; +import { AzureContextTransport } from "@pagopa/io-functions-commons/dist/src/utils/logging"; +import { TelemetryClient } from "applicationinsights"; const aFiscalCode = "SPNDNL80A13Y555X" as FiscalCode; const expiresAtDate = new Date(); // Now @@ -100,6 +106,33 @@ const aValidPayload: ActivatePubKeyPayload = { expired_at: expiresAtDate }; +const FN_LOG_NAME = "activate-pubkey"; + +const loggerMock = { + trackEvent: jest.fn(e => { + return void 0; + }) +}; + +const azureContextTransport = new AzureContextTransport( + () => contextMock.log, + {} +); +useWinstonFor({ + loggerId: LoggerId.event, + transports: [ + withApplicationInsight( + (loggerMock as unknown) as TelemetryClient, + "lollipop" + ), + azureContextTransport + ] +}); +useWinstonFor({ + loggerId: LoggerId.default, + transports: [azureContextTransport] +}); + describe("activatePubKey handler", () => { beforeEach(() => { jest.clearAllMocks(); @@ -261,6 +294,17 @@ describe("ActivatePubKey - Errors", () => { aValidPayload ); + expect(loggerMock.trackEvent).toHaveBeenCalledWith({ + name: "lollipop.error.activate-pubkey", + properties: { + assertion_ref: aValidSha256AssertionRef, + message: `Error while reading pop document: ${ErrorKind.NotFound}` + }, + tagOverrides: { + samplingEnabled: "false" + } + }); + expect(res).toMatchObject({ kind: "IResponseErrorInternal", detail: @@ -297,6 +341,17 @@ describe("ActivatePubKey - Errors", () => { aValidPayload ); + expect(loggerMock.trackEvent).toHaveBeenCalledWith({ + name: "lollipop.error.activate-pubkey", + properties: { + assertion_ref: aValidSha256AssertionRef, + message: `Unexpected status on pop document during activation: ${PubKeyStatusEnum.REVOKED}` + }, + tagOverrides: { + samplingEnabled: "false" + } + }); + expect(res).toMatchObject( expect.objectContaining({ kind: "IResponseErrorForbiddenNotAuthorized" @@ -331,6 +386,17 @@ describe("ActivatePubKey - Errors", () => { aValidPayload ); + expect(loggerMock.trackEvent).toHaveBeenCalledWith({ + name: "lollipop.error.activate-pubkey", + properties: { + assertion_ref: aValidSha256AssertionRef, + message: `Error while reading pop document: ${ErrorKind.Internal}` + }, + tagOverrides: { + samplingEnabled: "false" + } + }); + expect(res).toMatchObject({ kind: "IResponseErrorInternal", detail: @@ -344,6 +410,42 @@ describe("ActivatePubKey - Errors", () => { expect(popDocumentWriterMock).not.toHaveBeenCalled(); }); + it("should return 500 Internal Error when AssertionFileName fail decoding", async () => { + const handler = ActivatePubKeyHandler( + publicKeyDocumentReaderMock, + popDocumentWriterMock, + assertionWriterMock + ); + + const res = await handler(contextMock, aValidSha256AssertionRef, { + ...aValidPayload, + fiscal_code: "invalid_fiscal_code" as FiscalCode // this will make AssertionFileName decoder fail + }); + + expect(loggerMock.trackEvent).toHaveBeenCalledWith({ + name: "lollipop.error.activate-pubkey", + properties: { + assertion_ref: aValidSha256AssertionRef, + message: `Could not decode assertionFileName` + }, + tagOverrides: { + samplingEnabled: "false" + } + }); + + expect(res).toMatchObject({ + kind: "IResponseErrorInternal", + detail: + 'Internal server error: Could not decode assertionFileName' + }); + + expect(publicKeyDocumentReaderMock).toHaveBeenCalledWith( + aValidSha256AssertionRef + ); + expect(assertionWriterMock).not.toHaveBeenCalled(); + expect(popDocumentWriterMock).not.toHaveBeenCalled(); + }); + it("should return 500 Internal Error when an error occurred writing assertion into storage", async () => { assertionWriterMock.mockImplementationOnce(() => TE.left({ @@ -365,6 +467,17 @@ describe("ActivatePubKey - Errors", () => { aValidPayload ); + expect(loggerMock.trackEvent).toHaveBeenCalledWith({ + name: "lollipop.error.activate-pubkey", + properties: { + assertion_ref: aValidSha256AssertionRef, + message: `an Error on storage` + }, + tagOverrides: { + samplingEnabled: "false" + } + }); + expect(res).toMatchObject({ kind: "IResponseErrorInternal", detail: "Internal server error: an Error on storage" @@ -384,13 +497,16 @@ describe("ActivatePubKey - Errors", () => { expect(popDocumentWriterMock).not.toHaveBeenCalled(); }); - it("should return 500 Internal Error when an error occurred storing master key", async () => { - popDocumentWriterMock.mockImplementationOnce(() => - TE.left({ - kind: ErrorKind.Internal, - detail: "an Error on cosmos update", - message: "a detail Error on cosmos update" - }) + it("should return 500 Internal Error when JwkPublicKeyFromToken fail decoding", async () => { + publicKeyDocumentReaderMock.mockImplementationOnce( + () => + TE.of({ + ...aRetrievedPendingLollipopPubKeySha256, + pubKey: "", // this will make JwkPublicKeyFromToken decoder fail + assertionRef: aValidSha256AssertionRef, + id: `${aValidSha256AssertionRef}-000000`, + version: 0 + }) as ReturnType ); const handler = ActivatePubKeyHandler( @@ -405,6 +521,61 @@ describe("ActivatePubKey - Errors", () => { aValidPayload ); + expect(loggerMock.trackEvent).toHaveBeenCalledWith({ + name: "lollipop.error.activate-pubkey", + properties: { + assertion_ref: aValidSha256AssertionRef, + message: `Could not decode public key | value \"\" at root is not a valid [JwkPublicKeyFromToken]` + }, + tagOverrides: { + samplingEnabled: "false" + } + }); + + expect(res).toMatchObject({ + kind: "IResponseErrorInternal", + detail: + 'Internal server error: Could not decode public key | value "" at root is not a valid [JwkPublicKeyFromToken]' + }); + + expect(publicKeyDocumentReaderMock).toHaveBeenCalledWith( + aValidSha256AssertionRef + ); + expect(popDocumentWriterMock).not.toHaveBeenCalled(); + }); + + it("should return 500 Internal Error when an error occurred storing master key", async () => { + const error = { + kind: ErrorKind.Internal, + detail: "an Error on cosmos update", + message: "a detail Error on cosmos update" + } as InternalError; + + popDocumentWriterMock.mockImplementationOnce(() => TE.left(error)); + + const handler = ActivatePubKeyHandler( + publicKeyDocumentReaderMock, + popDocumentWriterMock, + assertionWriterMock + ); + + const res = await handler( + contextMock, + aValidSha256AssertionRef, + aValidPayload + ); + + expect(loggerMock.trackEvent).toHaveBeenCalledWith({ + name: "lollipop.error.activate-pubkey", + properties: { + assertion_ref: aValidSha512AssertionRef, + message: `Error while writing pop document: ${error.kind} - ${error.detail} - ${error.message}` + }, + tagOverrides: { + samplingEnabled: "false" + } + }); + expect(res).toMatchObject({ kind: "IResponseErrorInternal", detail: "Internal server error: an Error on cosmos update" @@ -425,6 +596,12 @@ describe("ActivatePubKey - Errors", () => { }); it("should return 500 Internal Error when an error occurred storing used key", async () => { + const error = { + kind: ErrorKind.Internal, + detail: "an Error on cosmos update", + message: "a detail Error on cosmos update" + } as InternalError; + popDocumentWriterMock // First insert OK .mockImplementationOnce( @@ -437,13 +614,7 @@ describe("ActivatePubKey - Errors", () => { }) as ReturnType ) // Second insert KO - .mockImplementationOnce(() => - TE.left({ - kind: ErrorKind.Internal, - detail: "an Error on cosmos update", - message: "a detail Error on cosmos update" - }) - ); + .mockImplementationOnce(() => TE.left(error)); const handler = ActivatePubKeyHandler( publicKeyDocumentReaderMock, @@ -457,6 +628,17 @@ describe("ActivatePubKey - Errors", () => { aValidPayload ); + expect(loggerMock.trackEvent).toHaveBeenCalledWith({ + name: "lollipop.error.activate-pubkey", + properties: { + assertion_ref: aValidSha256AssertionRef, + message: `Error while writing pop document: ${error.kind} - ${error.detail} - ${error.message}` + }, + tagOverrides: { + samplingEnabled: "false" + } + }); + expect(res).toMatchObject({ kind: "IResponseErrorInternal", detail: "Internal server error: an Error on cosmos update" diff --git a/ActivatePubKey/handler.ts b/ActivatePubKey/handler.ts index 0a0f7cf..4aa9b73 100644 --- a/ActivatePubKey/handler.ts +++ b/ActivatePubKey/handler.ts @@ -21,6 +21,7 @@ import * as TE from "fp-ts/lib/TaskEither"; import { readableReportSimplified } from "@pagopa/ts-commons/lib/reporters"; import { JwkPublicKeyFromToken } from "@pagopa/ts-commons/lib/jwk"; import { NonEmptyString } from "@pagopa/ts-commons/lib/strings"; +import { eventLog } from "@pagopa/winston-ts"; import { ActivatedPubKey } from "../generated/definitions/internal/ActivatedPubKey"; import { AssertionRef } from "../generated/definitions/internal/AssertionRef"; import { ActivatePubKeyPayload } from "../generated/definitions/internal/ActivatePubKeyPayload"; @@ -39,11 +40,11 @@ import { getAlgoFromAssertionRef, getAllAssertionsRef } from "../utils/lollipopKeys"; -import { logAndReturnResponse } from "../utils/errors"; + +const FN_LOG_NAME = "activate-pubkey"; export const activatePubKeyForAssertionRef = ( - popDocumentWriter: PopDocumentWriter, - context: Context + popDocumentWriter: PopDocumentWriter ) => ( assertionFileName: AssertionFileName, assertionRef: AssertionRef, @@ -60,11 +61,14 @@ export const activatePubKeyForAssertionRef = ( pubKey, status: PubKeyStatusEnum.VALID }), - TE.mapLeft(error => { - const err = error.detail; - context.log.error(err); - return ResponseErrorInternal(err); - }) + eventLog.taskEither.errorLeft(error => [ + `Error while writing pop document: ${error.kind} - ${error.detail} - ${error.message}`, + { + assertion_ref: assertionRef, + name: FN_LOG_NAME + } + ]), + TE.mapLeft(error => ResponseErrorInternal(error.detail)) ); // ------------------------------- @@ -92,17 +96,27 @@ export const ActivatePubKeyHandler = ( ): ReturnType => pipe( publicKeyDocumentReader(assertion_ref), + eventLog.taskEither.errorLeft(error => [ + `Error while reading pop document: ${error.kind}`, + { + assertion_ref, + name: FN_LOG_NAME + } + ]), TE.mapLeft(error => - logAndReturnResponse( - context, - ResponseErrorInternal(`Error while reading pop document: ${error.kind}`) - ) + ResponseErrorInternal(`Error while reading pop document: ${error.kind}`) ), - TE.filterOrElseW(isPendingLollipopPubKey, doc => - logAndReturnResponse( - context, - ResponseErrorForbiddenNotAuthorized, - `Unexpected status on pop document during activation: ${doc.status}` + TE.filterOrElseW( + isPendingLollipopPubKey, + flow( + eventLog.peek.error(doc => [ + `Unexpected status on pop document during activation: ${doc.status}`, + { + assertion_ref, + name: FN_LOG_NAME + } + ]), + _ => ResponseErrorForbiddenNotAuthorized ) ), TE.bindTo("popDocument"), @@ -111,22 +125,29 @@ export const ActivatePubKeyHandler = ( `${body.fiscal_code}-${assertion_ref}`, AssertionFileName.decode, TE.fromEither, - TE.mapLeft(errors => - logAndReturnResponse( - context, - ResponseErrorInternal( - `Could not decode assertionFileName | ${readableReportSimplified( - errors - )}` - ) - ) + eventLog.taskEither.errorLeft(_ => [ + // we do not log decoding errors for AssertionFilename + // because we can leak fiscal code to logs + `Could not decode assertionFileName`, + { + assertion_ref, + name: FN_LOG_NAME + } + ]), + TE.mapLeft(_ => + ResponseErrorInternal(`Could not decode assertionFileName`) ), TE.chainFirst(assertionFileName => pipe( assertionWriter(assertionFileName, body.assertion), - TE.mapLeft(error => - logAndReturnResponse(context, ResponseErrorInternal(error.detail)) - ) + eventLog.taskEither.errorLeft(error => [ + `${error.detail}`, + { + assertion_ref, + name: FN_LOG_NAME + } + ]), + TE.mapLeft(error => ResponseErrorInternal(error.detail)) ) ) ) @@ -136,16 +157,18 @@ export const ActivatePubKeyHandler = ( popDocument.pubKey, JwkPublicKeyFromToken.decode, TE.fromEither, - TE.mapLeft(errors => - logAndReturnResponse( - context, - ResponseErrorInternal( - `Could not decode public key | ${readableReportSimplified( - errors - )}` - ) - ) - ) + TE.mapLeft( + errors => + `Could not decode public key | ${readableReportSimplified(errors)}` + ), + eventLog.taskEither.errorLeft(err => [ + err, + { + assertion_ref, + name: FN_LOG_NAME + } + ]), + TE.mapLeft(ResponseErrorInternal) ) ), TE.bindW("assertionRefs", ({ popDocument, jwkPubKeyFromString }) => @@ -155,15 +178,20 @@ export const ActivatePubKeyHandler = ( getAlgoFromAssertionRef(popDocument.assertionRef), jwkPubKeyFromString ), - TE.mapLeft((error: Error) => - logAndReturnResponse(context, ResponseErrorInternal(error.message)) - ) + eventLog.taskEither.errorLeft(error => [ + `${error.message}`, + { + assertion_ref, + name: FN_LOG_NAME + } + ]), + TE.mapLeft(error => ResponseErrorInternal(error.message)) ) ), TE.bindW( "retrievedPopDocument", ({ popDocument, assertionRefs, assertionFileName }) => - activatePubKeyForAssertionRef(popDocumentWriter, context)( + activatePubKeyForAssertionRef(popDocumentWriter)( assertionFileName, assertionRefs.master, body, @@ -178,7 +206,7 @@ export const ActivatePubKeyHandler = ( retrievedPopDocument }) => assertionRefs.used - ? activatePubKeyForAssertionRef(popDocumentWriter, context)( + ? activatePubKeyForAssertionRef(popDocumentWriter)( assertionFileName, assertionRefs.used, body, @@ -189,11 +217,16 @@ export const ActivatePubKeyHandler = ( TE.chainW( flow( TE.fromPredicate(isValidLollipopPubKey, () => - logAndReturnResponse( - context, - ResponseErrorInternal( - `Unexpected retrievedPopDocument with a not VALID status` - ) + pipe( + `Unexpected retrievedPopDocument with a not VALID status`, + eventLog.peek.error(msg => [ + `${msg}`, + { + assertion_ref, + name: FN_LOG_NAME + } + ]), + ResponseErrorInternal ) ), TE.map(retrievedLollipopKeysToApiActivatedPubKey), diff --git a/ActivatePubKey/index.ts b/ActivatePubKey/index.ts index 1b8dddf..09a40e7 100644 --- a/ActivatePubKey/index.ts +++ b/ActivatePubKey/index.ts @@ -4,6 +4,10 @@ import { secureExpressApp } from "@pagopa/io-functions-commons/dist/src/utils/ex import { setAppContext } from "@pagopa/io-functions-commons/dist/src/utils/middlewares/context_middleware"; import createAzureFunctionHandler from "@pagopa/express-azure-functions/dist/src/createAzureFunctionsHandler"; import { createBlobService } from "azure-storage"; +import { withApplicationInsight } from "@pagopa/io-functions-commons/dist/src/utils/transports/application_insight"; +import { AzureContextTransport } from "@pagopa/io-functions-commons/dist/src/utils/logging"; +import { useWinstonFor } from "@pagopa/winston-ts"; +import { LoggerId } from "@pagopa/winston-ts/dist/types/logging"; import { LolliPOPKeysModel, LOLLIPOPKEYS_COLLECTION_NAME @@ -12,6 +16,7 @@ import { cosmosdbInstance } from "../utils/cosmosdb"; import { getConfigOrThrow } from "../utils/config"; import { getPublicKeyDocumentReader } from "../utils/readers"; import { getAssertionWriter, getPopDocumentWriter } from "../utils/writers"; +import { initTelemetryClient } from "../utils/appinsights"; import { ActivatePubKey } from "./handler"; const config = getConfigOrThrow(); @@ -28,6 +33,25 @@ const assertionBlobService = createBlobService( config.LOLLIPOP_ASSERTION_STORAGE_CONNECTION_STRING ); +const telemetryClient = initTelemetryClient( + config.APPINSIGHTS_INSTRUMENTATIONKEY +); + +// eslint-disable-next-line functional/no-let +let logger: Context["log"]; +const azureContextTransport = new AzureContextTransport(() => logger, {}); +useWinstonFor({ + loggerId: LoggerId.event, + transports: [ + withApplicationInsight(telemetryClient, "lollipop"), + azureContextTransport + ] +}); +useWinstonFor({ + loggerId: LoggerId.default, + transports: [azureContextTransport] +}); + // Add express route app.put( "/api/v1/pubKeys/:assertion_ref", @@ -44,6 +68,7 @@ app.put( const azureFunctionHandler = createAzureFunctionHandler(app); const httpStart: AzureFunction = (context: Context): void => { + logger = context.log; setAppContext(app, context); azureFunctionHandler(context); }; diff --git a/ReservePubKey/__tests__/handler.test.ts b/ReservePubKey/__tests__/handler.test.ts index df677f3..4190474 100644 --- a/ReservePubKey/__tests__/handler.test.ts +++ b/ReservePubKey/__tests__/handler.test.ts @@ -20,6 +20,12 @@ import { } from "../../__mocks__/lollipopkeysMock"; import * as handler from "../handler"; import { AssertionRef } from "../../generated/definitions/external/AssertionRef"; +import { contextMock } from "../../__mocks__/context.mock"; +import { useWinstonFor } from "@pagopa/winston-ts"; +import { LoggerId } from "@pagopa/winston-ts/dist/types/logging"; +import { withApplicationInsight } from "@pagopa/io-functions-commons/dist/src/utils/transports/application_insight"; +import { AzureContextTransport } from "@pagopa/io-functions-commons/dist/src/utils/logging"; +import { TelemetryClient } from "applicationinsights"; const mockCreatePendingLollipop = (pendingLollipop: PendingLolliPopPubKeys) => Promise.resolve({ @@ -32,6 +38,33 @@ const mockCreatePendingLollipop = (pendingLollipop: PendingLolliPopPubKeys) => } }); + const FN_LOG_NAME = "reserve-pubkey"; + + const loggerMock = { + trackEvent: jest.fn(e => { + return void 0; + }) + }; + + const azureContextTransport = new AzureContextTransport( + () => contextMock.log, + {} + ); + useWinstonFor({ + loggerId: LoggerId.event, + transports: [ + withApplicationInsight( + (loggerMock as unknown) as TelemetryClient, + "lollipop" + ), + azureContextTransport + ] + }); + useWinstonFor({ + loggerId: LoggerId.default, + transports: [azureContextTransport] + }); + describe("reserveSingleKey", () => { test("GIVEN a working model WHEN reserve a pub_key THEN call the cosmos create and return the RetriveLollipop", async () => { const mockedContainer = mockContainer(); @@ -74,6 +107,16 @@ describe("reserveSingleKey", () => { pubKey.pub_key )(assertionRef)(); + expect(loggerMock.trackEvent).toHaveBeenCalledWith({ + name: "lollipop.error.reserve-pubkey", + properties: { + message: `${FN_LOG_NAME} | COSMOS_ERROR_RESPONSE`, + }, + tagOverrides: { + samplingEnabled: "false" + } + }); + expect(result).toEqual( expect.objectContaining({ left: expect.objectContaining({ @@ -146,6 +189,17 @@ describe("reservePubKeys", () => { const model = new LolliPOPKeysModel(mockedContainer.container); const pubKey = aSha512PubKey; const result = await handler.reservePubKeys(model)(pubKey); + + expect(loggerMock.trackEvent).toHaveBeenCalledWith({ + name: "lollipop.error.reserve-pubkey", + properties: { + message: `${FN_LOG_NAME} | COSMOS_ERROR_RESPONSE`, + }, + tagOverrides: { + samplingEnabled: "false" + } + }); + expect(mockedContainer.mock.create).toHaveBeenCalledTimes(1); expect(result).toEqual( expect.objectContaining({ @@ -164,6 +218,17 @@ describe("reservePubKeys", () => { algo: JwkPubKeyHashAlgorithmEnum.sha256 }; const result = await handler.reservePubKeys(model)(pubKey); + + expect(loggerMock.trackEvent).toHaveBeenCalledWith({ + name: "lollipop.error.reserve-pubkey", + properties: { + message: `${FN_LOG_NAME} | COSMOS_ERROR_RESPONSE`, + }, + tagOverrides: { + samplingEnabled: "false" + } + }); + expect(mockedContainer.mock.create).toHaveBeenCalledTimes(2); expect(result).toEqual( expect.objectContaining({ diff --git a/ReservePubKey/handler.ts b/ReservePubKey/handler.ts index 14ae6b1..b8ca17a 100644 --- a/ReservePubKey/handler.ts +++ b/ReservePubKey/handler.ts @@ -19,6 +19,7 @@ import { NonNegativeInteger } from "@pagopa/ts-commons/lib/numbers"; import * as A from "fp-ts/Apply"; import * as R from "fp-ts/Record"; import { isDefined } from "@pagopa/io-functions-commons/dist/src/utils/types"; +import { eventLog } from "@pagopa/winston-ts"; import { encodeBase64 } from "../utils/thumbprint"; import { MASTER_HASH_ALGO } from "../utils/lollipopKeys"; import { NewPubKey } from "../generated/definitions/internal/NewPubKey"; @@ -32,6 +33,8 @@ import { getAllAssertionsRef } from "../utils/lollipopKeys"; import { AssertionRef } from "../generated/definitions/external/AssertionRef"; import { JwkPubKey } from "../generated/definitions/internal/JwkPubKey"; +const FN_LOG_NAME = "reserve-pubkey"; + type IReservePubKeyHandler = ( inputPubkeys: NewPubKeyPayload ) => Promise< @@ -65,6 +68,12 @@ export const reserveSingleKey = ( pendingPubKey => pipe( lollipopPubkeysModel.create(pendingPubKey), + eventLog.taskEither.errorLeft(error => [ + `${FN_LOG_NAME} | ${error.kind}`, + { + name: FN_LOG_NAME + } + ]), TE.mapLeft(cosmosErrorsToResponse) ) ); @@ -78,6 +87,12 @@ export const reservePubKeys = ( inputPubkeys.algo, inputPubkeys.pub_key ), + eventLog.taskEither.errorLeft(error => [ + `${FN_LOG_NAME} | ${error.name} - ${error.message}`, + { + name: FN_LOG_NAME + } + ]), TE.mapLeft(err => ResponseErrorInternal(err.message)), TE.chain( flow( @@ -103,6 +118,12 @@ export const reservePubKeys = ( newPubKey ) ), + eventLog.taskEither.errorLeft(error => [ + `${FN_LOG_NAME} | ${error.kind} ${error.detail}`, + { + name: FN_LOG_NAME + } + ]), TE.toUnion )(); diff --git a/ReservePubKey/index.ts b/ReservePubKey/index.ts index f326dda..4c4093e 100644 --- a/ReservePubKey/index.ts +++ b/ReservePubKey/index.ts @@ -3,13 +3,21 @@ import * as express from "express"; import { secureExpressApp } from "@pagopa/io-functions-commons/dist/src/utils/express"; import { setAppContext } from "@pagopa/io-functions-commons/dist/src/utils/middlewares/context_middleware"; import createAzureFunctionHandler from "@pagopa/express-azure-functions/dist/src/createAzureFunctionsHandler"; +import { withApplicationInsight } from "@pagopa/io-functions-commons/dist/src/utils/transports/application_insight"; +import { AzureContextTransport } from "@pagopa/io-functions-commons/dist/src/utils/logging"; +import { useWinstonFor } from "@pagopa/winston-ts"; +import { LoggerId } from "@pagopa/winston-ts/dist/types/logging"; import { cosmosdbInstance } from "../utils/cosmosdb"; import { LolliPOPKeysModel, LOLLIPOPKEYS_COLLECTION_NAME } from "../model/lollipop_keys"; +import { getConfigOrThrow } from "../utils/config"; +import { initTelemetryClient } from "../utils/appinsights"; import { getReservePubKeyHandler } from "./handler"; +const config = getConfigOrThrow(); + // Setup Express const app = express(); secureExpressApp(app); @@ -18,12 +26,32 @@ const lollipopPubkeysModel = new LolliPOPKeysModel( cosmosdbInstance.container(LOLLIPOPKEYS_COLLECTION_NAME) ); +const telemetryClient = initTelemetryClient( + config.APPINSIGHTS_INSTRUMENTATIONKEY +); + +// eslint-disable-next-line functional/no-let +let logger: Context["log"]; +const azureContextTransport = new AzureContextTransport(() => logger, {}); +useWinstonFor({ + loggerId: LoggerId.event, + transports: [ + withApplicationInsight(telemetryClient, "lollipop"), + azureContextTransport + ] +}); +useWinstonFor({ + loggerId: LoggerId.default, + transports: [azureContextTransport] +}); + // Add express route app.post("/api/v1/pubkeys", getReservePubKeyHandler(lollipopPubkeysModel)); const azureFunctionHandler = createAzureFunctionHandler(app); const httpStart: AzureFunction = (context: Context): void => { + logger = context.log; setAppContext(app, context); azureFunctionHandler(context); }; diff --git a/utils/errors.ts b/utils/errors.ts index fee96ff..48dd78e 100644 --- a/utils/errors.ts +++ b/utils/errors.ts @@ -1,4 +1,3 @@ -import { Context } from "@azure/functions"; import * as t from "io-ts"; import * as O from "fp-ts/lib/Option"; import { pipe } from "fp-ts/lib/function"; @@ -6,7 +5,6 @@ import { CosmosErrors } from "@pagopa/io-functions-commons/dist/src/utils/cosmos import { NonEmptyString } from "@pagopa/ts-commons/lib/strings"; import { errorsToReadableMessages } from "@pagopa/ts-commons/lib/reporters"; import { - IResponse, IResponseErrorInternal, IResponseErrorNotFound, ResponseErrorInternal, @@ -121,17 +119,3 @@ export const domainErrorToResponseError = ( error.kind === ErrorKind.NotFound ? ResponseErrorNotFound(error.kind, "Could not find requested resource") : ResponseErrorInternal(error.detail); - -/** - * Log a Response detail and return it - */ -export const logAndReturnResponse = >( - context: Context, - returnValue: T, - logDetail?: string -): T => { - context.log.error( - `${returnValue.detail}${logDetail ? ` | ${logDetail}` : ""}` - ); - return returnValue; -};