Skip to content

Commit

Permalink
Merge pull request #962 from dpc-sdp/feature/nuxt-logging
Browse files Browse the repository at this point in the history
[R20-1581] feat(@dpc-sdp/nuxt-ripple): adds logging in vue/nuxt contexts
  • Loading branch information
dylankelly authored Jan 12, 2024
2 parents e4f64ea + e70e098 commit e4b7da2
Show file tree
Hide file tree
Showing 13 changed files with 183 additions and 32 deletions.
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*
*.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

0 comments on commit e4b7da2

Please sign in to comment.