diff --git a/views/docs/best-practices/deployment.md b/views/docs/best-practices/deployment.md index 0334a6c..cfe639b 100644 --- a/views/docs/best-practices/deployment.md +++ b/views/docs/best-practices/deployment.md @@ -4,9 +4,9 @@ Adhearsion can be deployed any way you like, but here are some guidelines to make the process easier. These will evolve over time: -## Deploying to Heroku +## Deploying to PaaS -Heroku is the current preferred deployment environment, because of the simplicity with which applications may be deployed there. +Heroku is one of the easiest deployment targets to get up and running with. Other PaaS systems follow similar patterns to Heroku, and you should consult their documentation in order to figure out how to deploy an Adhearsion app to them. The first step is to generate an Adhearsion application: @@ -308,20 +308,33 @@ Scaling ahn processes... done, now running 1 Scaling web processes... done, now running 0 -## Deploying to the cloud/a VPS/bare metal +## Deploying to IaaS/a VPS/bare metal -[Foreman](http://ddollar.github.com/foreman) is a good option for managing your application's processes both in development and production. In development, you should run foreman start, but in production you should probably export to something like Ubuntu Upstart. +If you wish to deploy an Adhearsion application to your own servers, be they IaaS-based, traditional VMs or bare metal, it is suggested to utilise a 12factor-compliant pipeline. Our suggestion is to utilise [pkgr](https://github.com/crohr/pkgr) (or the hosted version, [Packager.io](https://packager.io/)). This way, you can ship your applications as a fully self-contained package compatible with various operating systems and already setup for a PaaS-like management approach. -It is possible to instruct Foreman to include extra environment variables when executing your application. This is done by including an `.env` file in the app directory when running foreman or exporting to Upstart. The file should be similar to this: +You should build packages as part of your application build pipeline, perhaps using a CI system like Jenkins. Your packages should then be stored in a package repository, which you might host on your own infrastructure, or rent from a SaaS provider. If you utilise the hosted version of Packager, both of these things are provided for you. Note that if you are installing on CentOS, you will need to explicitly specify a dependency on PCRE in your `.pkgr.yml`. On other platforms, you can simply run `pkgr package` on a freshly generated Adhearsion app to produce a working package. + +```yaml +targets: + centos-6: + build_dependencies: + - pcre-devel +``` + +Once you have your package safely in a repository, you can then install it on your system using your operating system's standard package management, in much the same way as you would install other software such as Apache or MySQL. + +Once installed, a pkgr-built Adhearsion application will install a command-line utility for managing your application. It will be named after the name of your app directory or source control repository (or you can manually specify a name in `.pkgr.yml`) and you can run it without any arguments to see using info. + +Importantly, you can set your application config in a 12factor compatible way using `myapp config:set`, including viewing your application configuration using `myapp run rake config:show`. If you want to manage your application configuration using some configuration management system, you can simply write key-value pairs of environment variables to a file in `/etc/myapp` and these will be read on startup. The file should be similar to this: ```ruby AHN_PUNCHBLOCK_USERNAME=foobar AHN_PUNCHBLOCK_PASSWORD=barfoo ``` -You can optionally place this file elsewhere and specify its location using `--env`. +You can run your application in the foreground using `myapp run ahn`. Alternatively, you can daemonize your application by running `myapp scale ahn=1` and manipulate the service by running `service myapp start/stop/restart/status`; your operating system's standard service management (systemd, upstart or SysV init) will be used to manage the process, and your application's logs will be written to `/var/log/myapp`. -Check the Foreman docs for more details. +Check the [pkgr docs](https://github.com/crohr/pkgr) for more details. docs-nav-best-practices diff --git a/views/docs/best-practices/sysadmin.md b/views/docs/best-practices/sysadmin.md index 3e91792..1a65506 100644 --- a/views/docs/best-practices/sysadmin.md +++ b/views/docs/best-practices/sysadmin.md @@ -12,7 +12,6 @@ Starting with Adhearsion 2.0, all Adhearsion applications will appear in your pr Adhearsion 2.0 processes respond to several signals: -* On SIGHUP, Adhearsion will close and reopen all logfiles. Make sure you do this after rotating log files, for example, with logrotate. * On SIGALRM, Adhearsion will toggle on or off TRACE level logging. This can be very helpful when debugging a production system. * On SIGINT or SIGTERM Adhearsion does several things: - On first signal, Adhearsion marks its internal state as "shutting down" but continues to take and process calls normally. @@ -23,11 +22,7 @@ Adhearsion 2.0 processes respond to several signals: ## Starting and Stopping Adhearsion Processes -There are two ways to start an Adhearsion process: - -* In the foreground with an Adhearsion console. This is the common case while developing Adhearsion applications. To start in this mode call ahn with the "start" argument: `ahn start /path/to/my/application` - -* In the background as a daemon. This is typical for deployment scenarios. To start in this mode call ahn with the "daemon" argument: `ahn daemon /path/to/my/application` +To start an application, run `ahn start` like so: `ahn start /path/to/my/application`. You may also pass `--no-console` to boot the app without a console attached. docs-nav-best-practices diff --git a/views/docs/call-controllers.md b/views/docs/call-controllers.md index 9929e69..9748c81 100644 --- a/views/docs/call-controllers.md +++ b/views/docs/call-controllers.md @@ -180,6 +180,107 @@ end As usual, check out the [#say API documentation](http://rubydoc.info/github/adhearsion/adhearsion/Adhearsion/CallController/Output:say) for more. +### Internationalisation + +Adhearsion supports internationalisation of prompts in your CallControllers using the `CallController#t` method, via the [i18n gem](https://github.com/svenfuchs/i18n). + +Make sure to create your locales in `config/locales` within your Adhearsion app, and you can change the default locale by putting something like this in config/adhearsion.rb: + +```ruby +I18n.default_locale = :de +``` + +More docs (though admittedly Rails-specific - read carefully) can be found at http://guides.rubyonrails.org/i18n.html + +#### Examples + +en.yml: + +```yaml +en: + string1: + audio: /path/to/string1.wav + text: 'String One' + + string2: + audio: '/path/to/string2.wav' + + string3: + text: 'String Three' +``` + +example_controller.rb: + +```ruby +class ExampleController < Adhearsion::CallController + def run + answer + + play t(:string1) + # SSML generated: + + play t(:string2) + # SSML generated: + + play t(:string3) + # SSML generated: String Three + end +end +``` + +#### String interpolations + +Adhearsion supports string interpolations just as i18n itself does. However there are some guidelines we recommend: + +* When you want to craft TTS strings that contain variable data, use SSML instead +* Use interpolations only for audio files, not for TTS text strings + +The reason for this is that it is not practical to assume that you can interpolate text into a recorded audio file. Thus while your app may start with TTS-only today, following this practice will ensure that you can more easily convert to recorded audio in the future. + +Example: + +Bad: + +```ruby +play t(:hello, name: 'Ben') +``` + +Good: + +```ruby +play t(:hello), 'Ben' +``` + +Further discussion on this issue can be found in [adhearsion-i18n issue #3](https://github.com/adhearsion/adhearsion-i18n/issues/3). + +#### Verifying audio prompts + +Adhearsion includes a rake task that will check to ensure each defined audio file is present in the application. This assumes that the audio files are kept in the Adhearsion application itself and not hosted externally. + +Given a YAML locale file like: + +```yaml +en: + hello: + audio: hello.wav + missing_prompt: + audio: missing_prompt.wav +``` + +Assuming the default location of `#{Adhearsion.root}/audio`, this example assumes that `hello.wav` is present, but `missing_prompt.wav` is missing. + +Then run the rake task to validate the prompts and see output like this: + +```Bash +$ rake i18n:validate_files +[2014-05-07 16:03:00.792] DEBUG Adhearsion::Initializer: Adding /Users/bklang/myapp/config/locales to the I18n load path + +Adhearsion configured environment: development +[2014-05-07 16:03:00.833] INFO Object: [en] Missing audio file: /Users/bklang/myapp/audio/en/missing_prompt.wav +[2014-05-07 16:03:00.833] ERROR Object: Errors detected! Number of errors by locale: +[2014-05-07 16:03:00.833] ERROR Object: [en]: 1 missing prompts +``` + ### Asterisk setup If a text-to-speech engine is configured, all output will be rendered by the engine; otherwise, only file playback will be supported on Asterisk. The adhearsion-asterisk plugin provides helpers for Asterisk's built in complex-data rendering methods, and [its documentation](http://adhearsion.github.com/adhearsion-asterisk) is the appropriate place to find documentation for those. @@ -219,16 +320,106 @@ class MyController < Adhearsion::CallController def run answer result = ask "How many woodchucks? Enter a number followed by #.", terminator: '#' - say "Wow, #{result.response} is a lot of woodchucks!" + case result.status + when :match + say "Wow, #{result.utterance} is a lot of woodchucks!" + when :noinput + speak "Hellooo? Anyone there?" + when :nomatch + speak "That doesn't make sense." + end + end +end +``` + +Here, we choose to cease input using a terminator digit. Alternative strategies include a `:timeout`, or a digit `:limit`, which are described in the [#ask API documentation](http://rubydoc.info/github/adhearsion/adhearsion/Adhearsion/CallController/Input:ask), as well as the option of passing custom SRGS grammars for more complex input formats. + +Some examples of usage follow: + +#### Simple collection of 5 DTMF digits + +```ruby +class MyController < Adhearsion::CallController + def run + result = ask limit: 5 + case result.status + when :match + speak "You entered #{result.utterance}" + when :noinput + speak "Hellooo? Anyone there?" + when :nomatch + speak "That doesn't make sense." + end + end +end +``` + +#### Collecting an arbitrary number of digits until '#' is received: + +```ruby +class MyController < Adhearsion::CallController + def run + result = ask terminator: '#' + case result.status + when :match + speak "You entered #{result.utterance}" + when :noinput + speak "Hellooo? Anyone there?" + when :nomatch + speak "That doesn't make sense." + end + end +end +``` + +#### Collecting input from an inline speech grammar + +```ruby +class MyController < Adhearsion::CallController + def run + grammar = RubySpeech::GRXML.draw root: 'main', language: 'en-us', mode: :voice do + rule id: 'main', scope: 'public' do + one_of do + item { 'yes' } + item { 'no' } + end + end + end + + result = ask grammar: grammar, input_options: { mode: :voice } + case result.status + when :match + speak "You said #{result.utterance}" + when :noinput + speak "Hellooo? Anyone there?" + when :nomatch + speak "That doesn't make sense." + end end end ``` -Here, we choose to cease input using a terminator digit. Alternative strategies include a `:timeout`, or a digit `:limit`, which are described in the [#ask API documentation](http://rubydoc.info/github/adhearsion/adhearsion/Adhearsion/CallController/Input:ask). Additionally, it is possible to pass a block, to which `#ask` will yield the digit buffer after each digit is received, in order to validate the input and optionally terminate early. If the block returns a truthy value when invoked, the input will be terminated early. +#### Collecting input from a speech grammar by URL + +```ruby +class MyController < Adhearsion::CallController + def run + result = ask grammar_url: 'http://example.com/mygrammar.grxml', input_options: { mode: :voice } + case result.status + when :match + speak "You said #{result.utterance}" + when :noinput + speak "Hellooo? Anyone there?" + when :nomatch + speak "That doesn't make sense." + end + end +end +``` ### #menu -Rapid and painless creation of complex IVRs has always been one of the defining features of Adhearsion for beginning and advanced programmers alike. Through the `#menu` DSL method, the framework abstracts and packages the output and input management and the complex state machine needed to implement a complete menu with audio prompts, digit checking, retries and failure handling, making creating menus a breeze. +Rapid and painless creation of complex IVRs has always been one of the defining features of Adhearsion for beginner and advanced programmers alike. Through the `#menu` DSL method, the framework abstracts and packages the output and input management and the complex state machine needed to implement a complete menu with audio prompts, digit checking, retries and failure handling, making creating menus a breeze. A sample menu might look something like this: @@ -288,7 +479,7 @@ The `#match` method takes an `Integer`, a `String`, a `Range` or any number of t Execution of the current context resumes after `#menu` finishes. If you wish to jump to an entirely different controller, `#pass` can be used. -`#menu` will return a [CallController::Input::Result](http://rubydoc.info/github/adhearsion/adhearsion/Adhearsion/CallController/Input/Result) object detailing the success or otherwise of the menu, similarly to `#ask`. +`#menu` will return an [Adhearsion::CallController::Input::Result](http://rubydoc.info/github/adhearsion/adhearsion/Adhearsion/CallController/Input/Result) object detailing the success or otherwise of the menu, similarly to `#ask`. ## Recording diff --git a/views/docs/logging.md b/views/docs/logging.md index 1dd9bcb..9b5e8d7 100644 --- a/views/docs/logging.md +++ b/views/docs/logging.md @@ -16,24 +16,7 @@ The default available log levels are TRACE, DEBUG, INFO, WARN, ERROR, FATAL. ## Send logs elsewhere -By default, the logs are output to log/adhearsion.log and stdout. - -### Change the log file location - -You may change the location of the log file by altering the `config.platform.logging.outputters` config setting, like so: - -
-
-ADHEARSION_PLATFORM_LOGGING_OUTPUTTERS=/var/log/adhearsion.log ahn start -
-
- -### Log to syslog - -See [the logging gem](https://github.com/TwP/logging/blob/master/lib/logging/appenders/syslog.rb#L23). - -### Send logs by email - -See [the logging gem](https://github.com/TwP/logging/blob/master/lib/logging/appenders/email.rb#L25). +By default, logs are streamed to stdout in accordance with [12factor guidance](http://12factor.net/logs). If you wish to persist logs to disk or route them to some sort of aggregation system, you must do so within the platform that hosts your Adhearsion application. If you've followed the [deployment instructions](/docs/best-practices/deployment) then you already have this setup. ## Change the log format diff --git a/views/docs/upgrading.md b/views/docs/upgrading.md index 281e92e..1422179 100644 --- a/views/docs/upgrading.md +++ b/views/docs/upgrading.md @@ -1,5 +1,30 @@ [TOC] +# Upgrading from Adhearsion 2.x to 3.0 + +Adhearsion 3 builds on the Adhearsion 2 release and the lessons we learned from using it, cleaning up a number of rough edges. As such, deprecations and eventually removals happened, and there is work to be done to make an existing Adhearsion app work on 3.0. + +## Prerequisites + +* Ruby version +* No more FreeSWITCH + +## Media input + +* Migrate first to adhearsion-asr with Adhearsion 2 (including details) +* Removal of adhearsion-asr from app +* Moving configuration from adhearsion-asr to core + +## Dial confirmation + +* No more #dial_and_confirm +* #dial now confirms in parallel + +## Misc + +* No more integration with RAILS_ENV +* New operational guidelines + # Upgrading from Adhearsion 1.x to 2.0 Adhearsion 2.0 brings many changes. It marks the first time since release 0.8.0 in 2008 that we have broken backward compatibility with previous versions. This means that, while you have access to a rich set of new features, it also means existing applications will need to be ported to run on Adhearsion 2. This document aims to list the changes required to migrate an Adhearsion 1.x application up to Adhearsion 2.