Skip to content

Commit

Permalink
Use FunctionRunLog type when polling and writing
Browse files Browse the repository at this point in the history
  • Loading branch information
lopert committed Aug 1, 2024
1 parent 34a10e9 commit 518a6e5
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 24 deletions.
13 changes: 11 additions & 2 deletions packages/app/src/cli/services/app-logs/dev/poll-app-logs.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {pollAppLogs} from './poll-app-logs.js'
import {writeAppLogsToFile} from './write-app-logs.js'
import {FunctionRunLog} from '../types.js'
import {partnersFqdn} from '@shopify/cli-kit/node/context/fqdn'
import {describe, expect, test, vi, beforeEach, afterEach} from 'vitest'
import {fetch} from '@shopify/cli-kit/node/http'
import * as components from '@shopify/cli-kit/node/ui/components'
import * as output from '@shopify/cli-kit/node/output'
import camelcaseKeys from 'camelcase-keys'

const JWT_TOKEN = 'jwtToken'
const API_KEY = 'apiKey'
Expand Down Expand Up @@ -264,15 +266,22 @@ describe('pollAppLogs', () => {
},
})

const appLogPayloadZero = new FunctionRunLog(
camelcaseKeys(JSON.parse(RESPONSE_DATA.app_logs[0]!.payload), {deep: true}),
)
expect(writeAppLogsToFile).toHaveBeenCalledWith({
appLog: RESPONSE_DATA.app_logs[0],
appLogPayload: JSON.parse(RESPONSE_DATA.app_logs[0]!.payload),
appLogPayload: appLogPayloadZero,
apiKey: API_KEY,
stdout,
})

const appLogPayloadOne = new FunctionRunLog(
camelcaseKeys(JSON.parse(RESPONSE_DATA.app_logs[1]!.payload), {deep: true}),
)
expect(writeAppLogsToFile).toHaveBeenCalledWith({
appLog: RESPONSE_DATA.app_logs[1],
appLogPayload: JSON.parse(RESPONSE_DATA.app_logs[1]!.payload),
appLogPayload: appLogPayloadOne,
apiKey: API_KEY,
stdout,
})
Expand Down
7 changes: 4 additions & 3 deletions packages/app/src/cli/services/app-logs/dev/poll-app-logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import {
REQUEST_EXECUTION_IN_BACKGROUND_CACHE_ABOUT_TO_EXPIRE_REASON,
handleFetchAppLogsError,
} from '../utils.js'
import {AppLogData, ErrorResponse} from '../types.js'
import {AppLogData, ErrorResponse, FunctionRunLog} from '../types.js'
import {outputContent, outputDebug, outputToken, outputWarn} from '@shopify/cli-kit/node/output'
import {useConcurrentOutputContext} from '@shopify/cli-kit/node/ui/components'
import camelcaseKeys from 'camelcase-keys'
import {Writable} from 'stream'

export const pollAppLogs = async ({
Expand Down Expand Up @@ -74,12 +75,12 @@ export const pollAppLogs = async ({
const {app_logs: appLogs} = data

for (const log of appLogs) {
const payload = JSON.parse(log.payload)

let payload = JSON.parse(log.payload)
// eslint-disable-next-line no-await-in-loop
await useConcurrentOutputContext({outputPrefix: log.source, stripAnsi: false}, async () => {
if (log.log_type === LOG_TYPE_FUNCTION_RUN) {
handleFunctionRunLog(log, payload, stdout)
payload = new FunctionRunLog(camelcaseKeys(payload, {deep: true}))
} else if (log.log_type.startsWith(LOG_TYPE_FUNCTION_NETWORK_ACCESS)) {
handleFunctionNetworkAccessLog(log, payload, stdout)
} else {
Expand Down
62 changes: 50 additions & 12 deletions packages/app/src/cli/services/app-logs/dev/write-app-logs.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {writeAppLogsToFile} from './write-app-logs.js'
import {AppLogData} from '../types.js'
import {LOG_TYPE_FUNCTION_RUN} from '../utils.js'
import {AppLogData, AppLogPayload, FunctionRunLog} from '../types.js'
import {joinPath} from '@shopify/cli-kit/node/path'
import {writeLog} from '@shopify/cli-kit/node/logs'
import {describe, expect, test, vi, beforeEach} from 'vitest'
Expand All @@ -19,6 +18,20 @@ const APP_LOG: AppLogData = {
source_namespace: 'extensions',
log_timestamp: '2024-05-22T15:06:41.827379Z',
}

const NEW_APP_LOG: AppLogData = {
shop_id: 1,
api_client_id: 2,
payload: JSON.stringify({someJson: 'someJSOn'}),
log_type: 'new_app_log_type',
cursor: '2024-05-22T15:06:43.841156Z',
status: 'success',
source: 'my-function',
source_namespace: 'extensions',
log_timestamp: '2024-05-22T15:06:41.827379Z',
}

const FUNCTION_RUN_PAYLOAD = new FunctionRunLog(camelcaseKeys(JSON.parse(APP_LOG.payload)))
const API_KEY = 'apiKey'

describe('writeAppLogsToFile', () => {
Expand All @@ -28,7 +41,7 @@ describe('writeAppLogsToFile', () => {
stdout = {write: vi.fn()}
})

test('calls writeLog with the right data', async () => {
test('calls writeLog with the FunctionRunLog payload type', async () => {
// Given
// determine the fileName and path
const fileName = `20240522_150641_827Z_${APP_LOG.source_namespace}_${APP_LOG.source}`
Expand All @@ -37,29 +50,54 @@ describe('writeAppLogsToFile', () => {
// When
const returnedPath = await writeAppLogsToFile({
appLog: APP_LOG,
appLogPayload: JSON.parse(APP_LOG.payload),
appLogPayload: FUNCTION_RUN_PAYLOAD,
apiKey: API_KEY,
stdout,
})

// Then
expect(returnedPath.fullOutputPath.startsWith(path)).toBe(true)
expect(writeLog).toHaveBeenCalledWith(expect.stringContaining(path), expectedLogDataFromAppEvent(APP_LOG))
expect(writeLog).toHaveBeenCalledWith(
expect.stringContaining(path),
expectedLogDataFromAppEvent(APP_LOG, FUNCTION_RUN_PAYLOAD),
)
})
})

function expectedLogDataFromAppEvent(event: AppLogData): string {
const payload = JSON.parse(event.payload)
test('calls writeLog with strings when no matching payload type', async () => {
// Given
// determine the fileName and path
const fileName = `20240522_150641_827Z_${APP_LOG.source_namespace}_${APP_LOG.source}`
const path = joinPath(API_KEY, fileName)

// When
const returnedPath = await writeAppLogsToFile({
appLog: NEW_APP_LOG,
appLogPayload: JSON.parse(NEW_APP_LOG.payload),
apiKey: API_KEY,
stdout,
})

if (event.log_type === LOG_TYPE_FUNCTION_RUN) {
payload.logs = payload.logs.split('\n').filter(Boolean)
}
// Then
expect(returnedPath.fullOutputPath.startsWith(path)).toBe(true)
expect(writeLog).toHaveBeenCalledWith(
expect.stringContaining(path),
expectedLogDataFromAppEvent(NEW_APP_LOG, JSON.parse(NEW_APP_LOG.payload)),
)
})
})

function expectedLogDataFromAppEvent(event: AppLogData, payload: AppLogPayload | string): string {
const data = camelcaseKeys(
{
...event,
payload,
payload: payload as any,
},
{deep: true},
)

if (payload instanceof FunctionRunLog) {
data.payload.logs = payload.logs.split('\n').filter(Boolean)
}

return JSON.stringify(data, null, 2)
}
13 changes: 6 additions & 7 deletions packages/app/src/cli/services/app-logs/dev/write-app-logs.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {AppLogData} from '../types.js'
import {LOG_TYPE_FUNCTION_RUN} from '../utils.js'
import {AppLogData, AppLogPayload, FunctionRunLog} from '../types.js'
import {joinPath} from '@shopify/cli-kit/node/path'
import {writeLog, getLogsDir} from '@shopify/cli-kit/node/logs'
import {randomUUID} from '@shopify/cli-kit/node/crypto'
Expand All @@ -19,7 +18,7 @@ export const writeAppLogsToFile = async ({
}: {
appLog: AppLogData
// eslint-disable-next-line @typescript-eslint/no-explicit-any
appLogPayload: any
appLogPayload: AppLogPayload | any
apiKey: string
stdout: Writable
}): Promise<AppLogFile> => {
Expand All @@ -31,10 +30,6 @@ export const writeAppLogsToFile = async ({
const fullOutputPath = joinPath(getLogsDir(), path)

try {
if (appLog.log_type === LOG_TYPE_FUNCTION_RUN) {
appLogPayload.logs = appLogPayload.logs.split('\n').filter(Boolean)
}

const toSaveData = camelcaseKeys(
{
...appLog,
Expand All @@ -43,6 +38,10 @@ export const writeAppLogsToFile = async ({
{deep: true},
)

if (appLogPayload instanceof FunctionRunLog) {
toSaveData.payload.logs = appLogPayload.logs.split('\n').filter(Boolean)
}

const logData = JSON.stringify(toSaveData, null, 2)

await writeLog(path, logData)
Expand Down

0 comments on commit 518a6e5

Please sign in to comment.