Skip to content

Commit

Permalink
App Builder experience for Configurable Logging (#502)
Browse files Browse the repository at this point in the history
* DEVX-1244: App Builder experience for Configurable Logging
- added app:config:get:log-forwarding command
- added app:config:set:log-forwarding command
- update log forwarding config on server during app:deploy command
- save log forwarding settings to project config
- added log-forwarding lib
- update log forwarding only if actions are deployed
- save log forwarding settings returned by the Runtime `PUT` API to take into account any sanitization
- added app:config:get:log-forwarding:errors command
- `aio app logs` display info message in case custom log forwarding is configured
  • Loading branch information
buskamuza authored Jan 24, 2022
1 parent 0a4f10e commit 3c53535
Show file tree
Hide file tree
Showing 20 changed files with 1,617 additions and 115 deletions.
276 changes: 169 additions & 107 deletions README.md

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions src/commands/app/config/get/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
Copyright 2019 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

const HHelp = require('@oclif/plugin-help').default
const BaseCommand = require('../../../../BaseCommand')

class IndexCommand extends BaseCommand {
async run () {
const help = new HHelp(this.config)
help.showHelp(['app:config:get', '--help'])
}
}

IndexCommand.description = 'Get app config'
IndexCommand.aliases = ['app:config:get']

module.exports = IndexCommand
46 changes: 46 additions & 0 deletions src/commands/app/config/get/log-forwarding.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
Copyright 2019 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

const BaseCommand = require('../../../../BaseCommand')
const LogForwarding = require('../../../../lib/log-forwarding')

class LogForwardingCommand extends BaseCommand {
async run () {
const lf = await LogForwarding.init(this.getFullConfig().aio)

const localConfig = lf.getLocalConfig()
const serverConfig = await lf.getServerConfig()

if (!localConfig.isEqual(serverConfig)) {
this.log('Local and server log forwarding configuration is different')
this.log("Run either 'aio app:deploy' to update the server, " +
"or 'aio app:config:set:log-forwarding' to set new local and server configuration")
this.log('Local configuration:')
this.printConfig(localConfig)
this.log('\nServer configuration:')
}
this.printConfig(serverConfig)
}

printConfig (config) {
if (config.isDefined()) {
this.log(`destination: ${config.getDestination()}`)
this.log('settings:', config.getSettings())
} else {
this.log('Not defined')
}
}
}

LogForwardingCommand.description = 'Get log forwarding destination configuration'
LogForwardingCommand.aliases = ['app:config:get:log-forwarding', 'app:config:get:lf']

module.exports = LogForwardingCommand
46 changes: 46 additions & 0 deletions src/commands/app/config/get/log-forwarding/errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
Copyright 2019 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

const BaseCommand = require('../../../../../BaseCommand')
const rtLib = require('@adobe/aio-lib-runtime')
const ora = require('ora')

class ErrorsCommand extends BaseCommand {
async run () {
const spinner = ora()
const lf = await this.getLogForwarding()
spinner.start('Checking for errors...')
const res = await lf.getErrors()
const destinationMessage = res.configured_forwarder !== undefined
? ` for the last configured destination '${res.configured_forwarder}'`
: ''
if (res.errors && res.errors.length > 0) {
spinner.succeed(`Log forwarding errors${destinationMessage}:\n` + res.errors.join('\n'))
} else {
spinner.succeed(`No log forwarding errors${destinationMessage}`)
}
}

async getLogForwarding () {
const runtimeConfig = this.getFullConfig().aio.runtime
rtLib.utils.checkOpenWhiskCredentials({ ow: runtimeConfig })
const rt = await rtLib.init({
...runtimeConfig,
api_key: runtimeConfig.auth
})
return rt.logForwarding
}
}

ErrorsCommand.description = 'Get log forwarding errors'
ErrorsCommand.aliases = ['app:config:get:log-forwarding:errors', 'app:config:get:lf:errors']

module.exports = ErrorsCommand
25 changes: 25 additions & 0 deletions src/commands/app/config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
Copyright 2019 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

const HHelp = require('@oclif/plugin-help').default
const BaseCommand = require('../../../BaseCommand')

class IndexCommand extends BaseCommand {
async run () {
const help = new HHelp(this.config)
help.showHelp(['app:config', '--help'])
}
}

IndexCommand.description = 'Manage app config'
IndexCommand.aliases = ['app:config', 'app:config']

module.exports = IndexCommand
25 changes: 25 additions & 0 deletions src/commands/app/config/set/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
Copyright 2019 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

const HHelp = require('@oclif/plugin-help').default
const BaseCommand = require('../../../../BaseCommand')

class IndexCommand extends BaseCommand {
async run () {
const help = new HHelp(this.config)
help.showHelp(['app:config:set', '--help'])
}
}

IndexCommand.description = 'Set app config'
IndexCommand.aliases = ['app:config:set']

module.exports = IndexCommand
45 changes: 45 additions & 0 deletions src/commands/app/config/set/log-forwarding.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
Copyright 2019 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/

const BaseCommand = require('../../../../BaseCommand')
const LogForwarding = require('../../../../lib/log-forwarding')

class LogForwardingCommand extends BaseCommand {
async run () {
const lf = await LogForwarding.init(this.getFullConfig().aio)

const destination = await this.promptDestination(lf.getSupportedDestinations())
const destinationSettingsConfig = lf.getSettingsConfig(destination)
const settings = await this.prompt(destinationSettingsConfig)
const lfConfig = new LogForwarding.LogForwardingConfig(destination, settings)

const res = await lf.updateServerConfig(lfConfig)
this.log(`Log forwarding is set to '${destination}'`)

await lf.updateLocalConfig(lf.getConfigFromJson(res))
this.log('Log forwarding settings are saved to the local configuration')
}

async promptDestination (supportedDestinations) {
const responses = await this.prompt([{
name: 'type',
message: 'select log forwarding destination',
type: 'list',
choices: supportedDestinations
}])
return responses.type
}
}

LogForwardingCommand.description = 'Set log forwarding destination configuration'
LogForwardingCommand.aliases = ['app:config:set:log-forwarding', 'app:config:set:lf']

module.exports = LogForwardingCommand
34 changes: 31 additions & 3 deletions src/commands/app/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const webLib = require('@adobe/aio-lib-web')
const { flags } = require('@oclif/command')
const { createWebExportFilter, runScript, buildExtensionPointPayloadWoMetadata, buildExcShellViewExtensionMetadata } = require('../../lib/app-helper')
const rtLib = require('@adobe/aio-lib-runtime')
const LogForwarding = require('../../lib/log-forwarding')

class Deploy extends BuildCommand {
async run () {
Expand Down Expand Up @@ -55,7 +56,29 @@ class Deploy extends BuildCommand {
const spinner = ora()

try {
// 1. deploy actions and web assets for each extension
const aioConfig = this.getFullConfig().aio
// 1. update log forwarding configuration
if (flags['log-forwarding-update'] && flags.actions) {
spinner.start('Updating log forwarding configuration')
try {
const lf = await LogForwarding.init(aioConfig)
if (lf.isLocalConfigChanged()) {
const lfConfig = lf.getLocalConfigWithSecrets()
if (lfConfig.isDefined()) {
await lf.updateServerConfig(lfConfig)
spinner.succeed(chalk.green(`Log forwarding is set to '${lfConfig.getDestination()}'`))
} else {
spinner.fail(chalk.green('Log forwarding is not updated: no configuration is provided'))
}
} else {
spinner.fail(chalk.green('Log forwarding is not updated: configuration not changed since last update'))
}
} catch (error) {
spinner.fail(chalk.red('Log forwarding is not updated.'))
throw error
}
}
// 2. deploy actions and web assets for each extension
// Possible improvements:
// - parallelize
// - break into smaller pieces deploy, allowing to first deploy all actions then all web assets
Expand All @@ -64,9 +87,9 @@ class Deploy extends BuildCommand {
const v = values[i]
await this.deploySingleConfig(k, v, flags, spinner)
}
// 2. deploy extension manifest

// 3. deploy extension manifest
if (flags.publish) {
const aioConfig = this.getFullConfig().aio
const payload = await this.publishExtensionPoints(libConsoleCLI, deployConfigs, aioConfig, flags['force-publish'])
this.log(chalk.blue(chalk.bold(`New Extension Point(s) in Workspace '${aioConfig.project.workspace.name}': '${Object.keys(payload.endpoints)}'`)))
} else {
Expand Down Expand Up @@ -302,6 +325,11 @@ Deploy.flags = {
'web-optimize': flags.boolean({
description: '[default: false] Enable optimization (minification) of web js/css/html',
default: false
}),
'log-forwarding-update': flags.boolean({
description: '[default: true] Update log forwarding configuration on server',
default: true,
allowNo: true
})
}

Expand Down
11 changes: 10 additions & 1 deletion src/commands/app/logs.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ governing permissions and limitations under the License.
*/

const { flags } = require('@oclif/command')
// const { cli } = require('cli-ux')
const BaseCommand = require('../../BaseCommand')
const { wrapError } = require('../../lib/app-helper')
const rtLib = require('@adobe/aio-lib-runtime')
const LogForwarding = require('../../lib/log-forwarding')

class Logs extends BaseCommand {
_processEachAction (fullConfig, processFn) {
Expand All @@ -40,6 +40,15 @@ class Logs extends BaseCommand {
throw new Error('There are no backend implementations for this project folder.')
}

const lf = await LogForwarding.init(fullConfig.aio)
const serverConfig = await lf.getServerConfig()
const logForwardingDestination = serverConfig.getDestination()
if (logForwardingDestination !== 'adobe_io_runtime') {
this.log(`Namespace is configured with custom log forwarding destination: '${logForwardingDestination}'. ` +
'Please use corresponding logging platform to view logs.')
return
}

if (flags.limit < 1) {
this.log('--limit should be > 0, using --limit=1')
flags.limit = 1
Expand Down
Loading

0 comments on commit 3c53535

Please sign in to comment.