Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[R20-1581] feat(@dpc-sdp/nuxt-ripple): adds logging in vue/nuxt contexts #962

Merged
merged 8 commits into from
Jan 12, 2024
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Temporary files
node_modules
*.log*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dylankelly I had to remove the trailing * from this otherwise it ignores the 00.logging.server.ts file. Not sure if I've broken something by doing this though.

*.log
.nuxt
.nitro
.cache
Expand Down
14 changes: 13 additions & 1 deletion packages/nuxt-ripple/components/TideBaseLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,13 @@

<script setup lang="ts">
// @ts-ignore
import { useAppConfig, useRoute, useNuxtApp, useTideLanguage } from '#imports'
import {
useAppConfig,
useRoute,
useNuxtApp,
useTideLanguage,
useLogger
} from '#imports'
import { computed, onMounted, provide, ref } from 'vue'
import { defu as defuMerge } from 'defu'
import { TideSiteData } from '../types'
Expand Down Expand Up @@ -164,6 +170,12 @@ const footerNav = computed(() => {
})

const nuxtApp = useNuxtApp()
const logger = useLogger()

logger.info('Calling tide:page hook...', {
label: 'TideBaseLayout'
})

/*
* This hook can be called from plugins to extend Tide managed pages behaviour - see /plugins folder for examples
*/
Expand Down
17 changes: 17 additions & 0 deletions packages/nuxt-ripple/composables/use-logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const useLogger = () => {
const { $logger } = useNuxtApp()
const noop = () => {}

if (process.server) {
return $logger
}

return {
debug: noop,
info: noop,
warning: noop,
error: noop
}
}

export default useLogger
9 changes: 9 additions & 0 deletions packages/nuxt-ripple/composables/use-section-id.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useRequestHeaders } from '#imports'

export const useSectionId = (): string => {
const sectionIdHeaderName = 'section-io-id'
const requestHeaders = useRequestHeaders([sectionIdHeaderName])
return requestHeaders[sectionIdHeaderName] || 'no section id'
}

export default useSectionId
81 changes: 70 additions & 11 deletions packages/nuxt-ripple/composables/use-tide-page.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import type { TidePageBase } from './../types'
import { useCookie, isPreviewPath, AuthCookieNames } from '#imports'
import {
useCookie,
isPreviewPath,
AuthCookieNames,
useLogger,
useSectionId
} from '#imports'

const isCacheTimeExpired = (date: number, expiryInMinutes = 5) => {
// 5 minute default expiry in step with varnish cache
Expand All @@ -8,7 +14,7 @@ const isCacheTimeExpired = (date: number, expiryInMinutes = 5) => {
return date < timePlusExpiry
}

const checkForRedirect = async (page: TidePageBase) => {
const checkForRedirect = async (page: TidePageBase, debugLogger) => {
// Redirect on the 6 codes that Drupal supplies
if (page?.type === 'redirect') {
switch (page.status_code) {
Expand All @@ -18,6 +24,13 @@ const checkForRedirect = async (page: TidePageBase) => {
case '304':
case '305':
case '307':
debugLogger(`Redirecting to ${page?.redirect_url}`, {
pageType: page?.type,
pageRedirectUrl: page?.redirect_url,
pageRedirectType: page?.redirect_type,
pageStatusCode: page?.status_code
})

await navigateTo(page.redirect_url, {
replace: true,
redirectCode: page.status_code,
Expand All @@ -33,19 +46,41 @@ export const useTidePage = async (
slug?: string,
site?: number
): Promise<TidePageBase> => {
const logger = useLogger()
const route = useRoute()

const path = slug || route.path
const { public: config } = useRuntimeConfig()
const siteId = site || config.tide?.site

const sectionRequestId = useSectionId()

const debugLogger = (message: string, data = {}) => {
logger.debug(message, {
label: 'useTidePage',
section_io_id: sectionRequestId,
...data
})
}

debugLogger('Route requested', {
path,
siteId
})

// check we dont add too many keys to cache
const nuxt = useNuxtApp()
const maxCacheItems = 50
if (nuxt.payload.data) {
if (Object.keys(nuxt.payload.data).length > maxCacheItems + 1) {
if (process.dev) {
console.log('clear nuxt cache')
debugLogger(
`Nuxt cache length is: ${Object.keys(nuxt.payload.data).length}`,
{
nuxtCacheKeys: Object.keys(nuxt.payload.data)
}
)

if (Object.keys(nuxt.payload.data).length > maxCacheItems + 1) {
debugLogger(`Cache is larger than max ${maxCacheItems} items, clearing...`)
clearNuxtData()
}
}
Expand All @@ -55,14 +90,22 @@ export const useTidePage = async (
// Refresh data so it doesnt go stale whilst client side nav
if (pageData.value && pageData.value._fetched) {
if (isCacheTimeExpired(pageData.value._fetched)) {
if (process.dev) {
console.log('Cache reset for page', `page-${path}`)
}

debugLogger(
'Cached data for this page is stale, clearing nuxt cache just for this page...',
{
cacheKey: `page-${path}`
}
)

await clearNuxtData(`page-${path}`)
}
}

const headers = {}
const headers: {
cookie?: string
'x-section-request-id'?: string
} = {}

// Need to manually pass the cookies needed for auth as they aren't automatically added when server rendered
if (isPreviewPath(path)) {
Expand All @@ -73,9 +116,15 @@ export const useTidePage = async (
headers.cookie = `${AuthCookieNames.ACCESS_TOKEN}=${accessTokenCookie.value};${AuthCookieNames.ACCESS_TOKEN_EXPIRY}=${accessTokenExpiryCookie.value}`
}

if (process.server) {
headers['x-section-request-id'] = sectionRequestId
}

let sectionCacheTags: string | null = null

if (!pageData.value) {
debugLogger('No cached page found, fetching the page data...')

const { data, error } = await useFetch('/api/tide/page', {
key: `page-${path}`,
baseURL: config.apiUrl || '',
Expand All @@ -102,12 +151,22 @@ export const useTidePage = async (
useTideError(error.value?.statusCode)
}

await checkForRedirect(data.value)
debugLogger('Page data fetched', {
pageTitle: data.value.title,
pageNodeId: data.value.nid
})

await checkForRedirect(data.value, debugLogger)

return data.value
}

await checkForRedirect(pageData.value)
debugLogger('Cached data for this page was found and is being used...', {
pageTitle: pageData.value.title,
pageNodeId: pageData.value.nid
})

await checkForRedirect(pageData.value, debugLogger)

return pageData.value
}
Expand Down
12 changes: 12 additions & 0 deletions packages/nuxt-ripple/composables/use-tide-site.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import type { TideSiteData } from './../types'
import { useSectionId } from '#imports'

export const useTideSite = async (id?: number): Promise<TideSiteData> => {
const { public: config } = useRuntimeConfig()
const siteId = id || config.tide?.site
const { data: siteData } = useNuxtData(`site-${siteId}`)
const nuxt = useNuxtApp()

const sectionRequestId = useSectionId()

const headers: {
'x-section-request-id'?: string
} = {}

if (process.server) {
headers['x-section-request-id'] = sectionRequestId
}

let sectionCacheTags: string | null = null

if (!siteData.value) {
Expand All @@ -15,6 +26,7 @@ export const useTideSite = async (id?: number): Promise<TideSiteData> => {
params: {
id: siteId
},
headers,
async onResponse({ response }) {
sectionCacheTags = response.headers.get('section-cache-tags')
}
Expand Down
10 changes: 10 additions & 0 deletions packages/nuxt-ripple/plugins/00.logging.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineNuxtPlugin } from '#app'
import { logger } from '@dpc-sdp/ripple-tide-api'

export default defineNuxtPlugin(() => {
return {
provide: {
logger
}
}
})
8 changes: 7 additions & 1 deletion packages/nuxt-ripple/plugins/site-theme.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useAppConfig, useHead } from '#imports'
import { useAppConfig, useHead, useLogger } from '#imports'
import { defu as defuMerge } from 'defu'

const formatThemeStyle = (themeObj) => {
Expand All @@ -13,6 +13,12 @@ const formatThemeStyle = (themeObj) => {

export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook('tide:page', ({ site }) => {
const logger = useLogger()

logger.info('tide:page hook was triggered', {
label: 'site-theme.ts'
})

const siteTheme = defuMerge(
site?.theme,
useAppConfig()?.ripple?.theme || {}
Expand Down
8 changes: 6 additions & 2 deletions packages/nuxt-ripple/server/api/tide/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
getQuery,
H3Event,
getCookie,
setResponseHeader
setResponseHeader,
getHeader
} from 'h3'
import { createHandler, TidePageApi } from '@dpc-sdp/ripple-tide-api'
import { BadRequestError } from '@dpc-sdp/ripple-tide-api/errors'
Expand Down Expand Up @@ -41,11 +42,14 @@ export const createPageHandler = async (
headers['X-OAuth2-Authorization'] = `Bearer ${tokenCookie}`
}

const sectionId = getHeader(event, 'x-section-request-id')

const pageResponse = await tidePageApi.getPageByPath(
query.path,
query.site,
{},
headers
headers,
sectionId
)

// Need to pass on the section cache tags to the nuxt app
Expand Down
4 changes: 3 additions & 1 deletion packages/nuxt-ripple/server/api/tide/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ export const createSiteHandler = async (
throw new BadRequestError('Site id is required')
}

const siteResponse = await tideSiteApi.getSiteData(query.id)
const sectionId = getHeader(event, 'x-section-request-id')

const siteResponse = await tideSiteApi.getSiteData(query.id, sectionId)

// Need to pass on the section cache tags to the nuxt app
if (siteResponse.headers && siteResponse.headers['section-cache-tags']) {
Expand Down
10 changes: 8 additions & 2 deletions packages/ripple-tide-api/src/services/http-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ export default class HttpClient {
`${request.method?.toUpperCase()} request to ${this.client.getUri(
request
)}`,
{ label: this.logLabel }
{
label: this.logLabel,
// _logId is a custom property added by us https://github.com/axios/axios/issues/2203
section_io_id: (request as any)._logId || 'no section id'
}
)
return request
},
Expand All @@ -62,7 +66,9 @@ export default class HttpClient {
error.request.path
}`,
{
label: this.logLabel
label: this.logLabel,
// _logId is a custom property added by us https://github.com/axios/axios/issues/2203
section_io_id: error.request?._logId || 'no section id'
}
)
} else {
Expand Down
Loading
Loading