blob: 03c404643debc91c73fd90214ee9860b171c44a3 [file] [log] [blame]
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file 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 CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!doctype html><html lang="en"><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><meta name="description" content="An open source API to convert natural language into actions."><meta name="author" content="NLPCraft."><title>Apache NLPCraft - Natural Language Interface</title><link href="//netdna.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet"><link href="//use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" rel="stylesheet" crossorigin="anonymous"><link href="/ext/syntaxhighlighter/styles/shCoreNLPCraft.css" rel="stylesheet" type="text/css"><link href="/ext/syntaxhighlighter/styles/shThemeNLPCraft.css" rel="stylesheet" type="text/css"><link href="//fonts.googleapis.com/css?family=Amatic+SC|Roboto+Mono" rel="stylesheet"> <script src="/ext/syntaxhighlighter/scripts/XRegExp.js" type="text/javascript"></script> <script src="/ext/syntaxhighlighter/scripts/shCore.js" type="text/javascript"></script> <script src="/ext/syntaxhighlighter/scripts/shBrushXml.js" type="text/javascript"></script> <script src="/ext/syntaxhighlighter/scripts/shBrushPlain.js" type="text/javascript"></script> <script src="/ext/syntaxhighlighter/scripts/shBrushJava.js" type="text/javascript"></script> <script src="/ext/syntaxhighlighter/scripts/shBrushScala.js" type="text/javascript"></script> <script src="/ext/syntaxhighlighter/scripts/shBrushPython.js" type="text/javascript"></script> <script src="/ext/syntaxhighlighter/scripts/shBrushJScript.js" type="text/javascript"></script> <script async defer src="https://buttons.github.io/buttons.js"></script><link rel="stylesheet" type="text/css" href="/assets/css/style.css"/> <script type="text/javascript" src="//use.typekit.net/pso2adz.js"></script> <script type="text/javascript"> try { Typekit.load(); } catch(e) { // Ignore. } </script><nav class="navbar navbar-expand-lg navbar-light bg-light" id="top-header"> <a class="navbar-brand mr-4" href="/index.html"> <img src="/images/nlpcraft_logo_white.gif" height="24px"> </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button><div class="collapse navbar-collapse" id="navbarSupportedContent"><ul class="navbar-nav mr-auto"><li class="nav-item"> <a class="nav-link" href="/index.html#features">Features</a><li class="nav-item"> <a class="nav-link" href="/docs.html">Docs</a><li class="nav-item"> <a class="nav-link" href="/download.html">Downloads <i class="fas fa-download"></i></a><li class="nav-item"> <a class="nav-link" href="/community.html">Community</a><li class="nav-item"> <a class="nav-link" href="/use-cases.html">Use Cases</a></ul><ul class="navbar-nav ml-auto"><li class="nav-item mr-2"> <a class="nav-link" href="/download.html">v.0.5.0</a><li class="nav-item"> <a class="nav-link fork-link" target="github" href="https://github.com/apache/incubator-nlpcraft">GitHub <img height="20px" src="/images/github_logo_white.png"></a></ul></div></nav><div class="container-fluid"><div class="navbar-aligned"><ol class="breadcrumb"><li class="mr-1"><a href="/index.html">Home</a><li class="mr-1 active">Server <span class="amp">&amp;</span> Probe</ol><h1 class="page-title"> <span><i class="fas fa-fw fa-book"></i> Server <span class="amp">&amp;</span> Probe</span></h1><div class="three-cols-container"><div class="col-md-2 first-column"><ul class="side-nav"><li class="side-nav-title">Introduction<li> <a href="/docs.html">Overview</a><li> <a href="/installation.html">Installation</a><li> <a href="/getting-started.html">Getting Started</a><li class="side-nav-title">Developer Guide<li> <a href="/basic-concepts.html">Basic Concepts</a><li> <a href="/first-example.html">First Example</a><li> <a href="/data-model.html">Data Model</a><li> <a href="/intent-matching.html">Intent Matching</a><li> <a href="/using-rest.html">REST API</a><li> <a class="active" href="/server-and-probe.html">Server <span class="amp">&amp;</span> Probe</a><li> <a href="/metrics-and-tracing.html">Metrics <span class="amp">&amp;</span> Tracing</a><li> <a href="/integrations.html">Integrations</a><li class="side-nav-title">Examples<li> <a href="/examples/alarm_clock.html">Alarm Clock</a><li> <a href="/examples/light_switch.html">Light Switch</a></ul></div><div id="server-and-probes" class="col-md-8 second-column"><section><h2 class="section-title">Overview</h2><p> As mentioned in <a href="/docs.html">overview</a> section the REST server and data probe are the two runtime components that you need to run when using NLPCraft. Data probes are used to deploy and host data model, while REST server (or a cluster of servers) is used to accept client REST call and route them to the data models via data probes.</p><div class="bq info"> <b>REST Server vs. Data Probe</b><p> It's important to remember why REST server is a separate component from a data probe. While a typical deployment would have only one REST server (or a cluster of REST servers behind a single load balancer), there are maybe multiple data probes hosting different data models deployed in different physical locations, managed through different life cycles and requiring different security and network configurations.</p><p> Moreover, REST server is a heavy and resource consuming component that is built around Apache Ignite distributing in-memory computing capabilities - while the data probe is a lightweight data model container. During the development and testing of data models, the developers need to frequently redeploy data models by restarting the data probe. If the REST server and the data probe would be one component - this process would be very inefficient.</p></div><p> Fro the rest of this section we assume that NLPCraft was <a href="/download.html">downloaded</a> and <a href="/installation.html">installed</a> via ZIP archive. However, all instructions below are fully applicable to any type of installation.</p><p> Once NLPCraft is downloaded as a ZIP archive and unzipped, the current directory will look like this:</p><pre class="console">
├── LICENSE
├── bin
├── sql
├── build
│   └── apache-nlpcraft-0.5.0
│   ├── <b>nlpcraft.conf</b>
│   ├── ignite.xml
│   ├── log4j2.xml
│   └── <b>apache-nlpcraft-0.5.0-all-deps.jar</b>
├── javadoc
├── openapi
└── src
</pre><p> Regardless of how NLPCraft was installed it comes with a single executable JAR file that includes all necessary dependencies: <code>build/apache-nlpcraft-0.5.0/<b>apache-nlpcraft-0.5.0-all-deps.jar</b></code>. This JAR file includes binaries for data probe, data model APIs and the REST server.</p></section><section id="server"><h2 class="section-title">REST Server</h2><p> As mentioned above REST server (or a cluster of servers) is used to accept client REST calls and route them to the data model via data probes. Note that both data probe and the REST server start the same way.</p><p> REST server can be stared in a <em>standard way</em> from either the command line or IDE such as Eclipse or IntelliJ IDEA:</p><nav><div class="nav nav-tabs" role="tablist"> <a class="nav-item nav-link active" data-toggle="tab" href="#nav-srv-jar" role="tab" aria-controls="nav-home" aria-selected="true">Executable JAR</a> <a class="nav-item nav-link" data-toggle="tab" href="#nav-srv-cmd" role="tab" aria-controls="nav-home" aria-selected="true">Command Line</a> <a class="nav-item nav-link" data-toggle="tab" href="#nav-srv-ide" role="tab" aria-controls="nav-home" aria-selected="true">IDE</a></div></nav><div class="tab-content"><div class="tab-pane fade show active" id="nav-srv-jar" role="tabpanel"><pre class="brush: plain">
$ cd build
$ java -Xms1024m -jar apache-nlpcraft-0.5.0-all-deps.jar -server
</pre></div><div class="tab-pane fade show" id="nav-srv-cmd" role="tabpanel"><pre class="brush: plain">
$ cd build
$ java -Xms1024m -cp apache-nlpcraft-0.5.0-all-deps.jar org.apache.nlpcraft.NCStart -server
</pre></div><div class="tab-pane fade show" id="nav-srv-ide" role="tabpanel"><p style="padding-top: 10px"> Configure run configuration with the main class <code>org.apache.nlpcraft.NCStart</code>. Note that <code>org.apache.nlpcraft.NCStart</code> class starts both the REST server and the data probe and is the class that is configured as <code>Main-Class</code> in <code>apache-nlpcraft-0.5.0-all-deps.jar</code> JAR file manifest.</p></div></div>Parameters:<dl><dt> <code>-server</code><dd> <em>Mandatory</em> parameter to indicate that you are starting the REST server.<dt><code>-config=path</code><dd> <em>Optional</em> parameter to provide configuration file path. Server will automatically look for <code>nlpcraft.conf</code> configuration file in the same directory as <code>apache-nlpcraft-0.5.0-all-deps.jar</code> file. If the configuration file has different name or in different location use <code>-config=path</code> parameter where <code>path</code> is an absolute path to the configuration file. Note that the server and the data probe can use the same file for their configuration (just like the default <code>nlpcraft.conf</code> contains configuration for both the server and the data probe).<dt><code>-igniteConfig=path</code><dd> <em>Optional</em> parameter to provide <a target=_ href="https://ignite.apache.org/">Apache Ignite</a> configuration file path. Note that Apache Ignite is used as a cluster computing plane and a default distributed storage. Server will automatically look for <code>ignite.xml</code> configuration file in the same directory as <code>apache-nlpcraft-0.5.0-all-deps.jar</code> file. If the configuration file has different name or in different location use <code>-igniteConfig=path</code> parameter where <code>path</code> is an absolute path to the Ignite configuration file.</dl><div class="bq warn"> <b>Java Memory</b><p> Make sure to allocate enough memory for server JVM using <code>-Xms</code> JVM option, i.e. <code>-Xms1024m</code>. Many 3rd party NLP engines like Stanford CoreNLP are very memory intensive and may require several GBs of JVM heap allocated depending on the models used. Note that when server JVM has insufficient heap memory the Apache Ignite may throw the following warning logs:</p><pre class="brush: text, highlight: 2">
Jul-22 13:27:56 [INFO ] ...
Jul-22 13:28:08 [WARN ] Possible too long JVM pause: 11364 milliseconds.
Jul-22 13:28:11 [INFO ] ...
</pre><p> The abnormally long GC pauses (over 5s) can be caused by the excessive memory swapping performed by OS due to insufficient JVM heap memory.</p></div><h3 class="section-title"><i class="fab fa-docker"></i> Docker</h3><p> You can also run REST server inside of Docker container:</p><pre class="brush: plain">
$ docker run -m 8G -p 8081:8081 -p 8201:8201 -p 8202:8202 nlpcraftserver/server:0.5.0
</pre><p> By default, the Docker image runs with a default configuration. See <a href="#config">configuration</a> section on how to provide custom configuration via environment variables for the REST server running inside of Docker container.</p><p> When the REST server successfully started you should see the log output similar to this:</p><pre class="brush: plain, highlight: 19">
_ ____ ______ ______
/ | / / /___ / ____/________ _/ __/ /_
/ |/ / / __ \/ / / ___/ __ `/ /_/ __/
/ /| / / /_/ / /___/ / / /_/ / __/ /_
/_/ |_/_/ .___/\____/_/ \__,_/_/ \__/
/_/
Server
Version: 0.5.0
Copyright (C) 2020 Apache Software Foundation.
...
+-------------------------+
| Server started [19.35s] |
+-------------------------+
Mar-11 23:21:04 [INFO ] REST server is listening on 'localhost:8081'.
</pre></section><section id="probe"><h2 class="section-title">Data Probe</h2><p> Just like the REST server the data probe can be started in a <em>standard way</em> from either the command line or IDE such as Eclipse or IntelliJ IDEA:</p><nav><div class="nav nav-tabs" role="tablist"> <a class="nav-item nav-link active" data-toggle="tab" href="#nav-probe-cmd" role="tab" aria-controls="nav-home" aria-selected="true">Command Line</a> <a class="nav-item nav-link" data-toggle="tab" href="#nav-probe-jar" role="tab" aria-controls="nav-home" aria-selected="true">Executable JAR</a> <a class="nav-item nav-link" data-toggle="tab" href="#nav-probe-ide" role="tab" aria-controls="nav-home" aria-selected="true">IDE</a></div></nav><div class="tab-content"><div class="tab-pane fade show" id="nav-probe-jar" role="tabpanel"><pre class="brush: plain">
$ cd build
$ java -Xms1024m -jar apache-nlpcraft-0.5.0-all-deps.jar -probe
</pre><div class="bq warn"><p> <b>NOTE:</b> when using executable JAR to start the data probe you cannot add your own model classes to the classpath. You should either package your classes into JAR file and configure probe accordingly - or use <code>-cp</code> option in command line.</p></div></div><div class="tab-pane fade show active" id="nav-probe-cmd" role="tabpanel"><pre class="brush: plain">
$ cd build
$ java -Xms1024m -cp apache-nlpcraft-0.5.0-all-deps.jar:/my/project/classes org.apache.nlpcraft.NCStart -probe -config=/my/project/probe.conf
</pre><p> Directory <code>/my/project/classes</code> should contain all compiled classes for your models. Make sure to replace <code>/my/project/classes</code> and <code>/my/project/probe.conf</code> with the actual paths.</p></div><div class="tab-pane fade show" id="nav-probe-ide" role="tabpanel"><p style="padding-top: 10px"> Configure run configuration with the main class <code>org.apache.nlpcraft.NCStart</code>.</p><div class="bq info"> <b>Class <code>org.apache.nlpcraft.NCStart</code></b><p> Note that <code>org.apache.nlpcraft.NCStart</code> class starts both the REST server and the data probe and is the class that is configured as <code>Main-Class</code> in <code>apache-nlpcraft-0.5.0-all-deps.jar</code> JAR file manifest.</p></div></div></div>Parameters:<dl><dt> <code>-probe</code><dd> <em>Mandatory</em> parameter to indicate that you are starting a data probe.<dt><code>-config=path</code><dd><p> <em>Optional</em> parameter to provide probe configuration file path. Data probe will automatically look for <code>nlpcraft.conf</code> configuration file in the same directory as <code>apache-nlpcraft-0.5.0-all-deps.jar</code> file. If the configuration file has different name or in different location use <code>-config=path</code> parameter where <code>path</code> is an absolute path to the data probe configuration file. Note that the server and the data probe can use the same file for their configuration (just like the default <code>nlpcraft.conf</code> contains configuration for both the server and the data probe).</p></dl><div class="bq info"> <b>Adding Your Classes</b><p> Note that when you are using a <em>command line</em> to start the probe you can also add your own classes that implement your models. To do that you need to use <code>-cp</code> option instead of <code>-jar</code> and construct your JVM classpath to include both the <code>apache-nlpcraft-0.5.0-all-deps.jar</code> as well as directory where your compiled Java code is located:</p><pre class="brush: plain, highlight: 2">
$ cd build
$ java -cp apache-nlpcraft-0.5.0-all-deps.jar:/my/project/classes org.apache.nlpcraft.NCStart -probe -config /my/project/probe.conf
</pre>Make sure to replace <code>/my/project/classes</code> with your own directory where your compiled model classes are located. Note that you need to specify class <code>org.apache.nlpcraft.NCStart</code> explicitly in this case.</div><p> When the data probe started you should see the log output similar to this:</p><pre class="brush: plain">
_ ____ ______ ______
/ | / / /___ / ____/________ _/ __/ /_
/ |/ / / __ \/ / / ___/ __ `/ /_/ __/
/ /| / / /_/ / /___/ / / /_/ / __/ /_
/_/ |_/_/ .___/\____/_/ \__,_/_/ \__/
/_/
Data Probe
Version: 0.5.0
Copyright (C) 2020 Apache Software Foundation.
Mar-11 23:25:52 [INFO ] Probe Configuration:
+--------------------------------------------------------------------+
| Probe ID | all.examples |
| Probe Token | 3141592653589793 |
| API Version | 0.5.0, 2019-03-01 |
| Down-Link | localhost:8202 |
| Up-Link | localhost:8201 |
+-----------------+--------------------------------------------------+
| Models | org.apache.nlpcraft.examples.alarm.AlarmModel |
| | org.apache.nlpcraft.examples.echo.EchoModel |
| | org.apache.nlpcraft.examples.helloworld.HelloWorldModel |
| | org.apache.nlpcraft.examples.time.TimeModel |
| | org.apache.nlpcraft.examples.weather.WeatherModel |
+-----------------+--------------------------------------------------+
| Lifecycle | |
| JARs Folder | |
+--------------------------------------------------------------------+
...
Mar-11 23:25:56 [INFO ] Models deployed: 5
+================================================================================+
| Model ID | Name | Ver. | Elements | Synonyms |
+================================================================================+
| nlpcraft.alarm.ex | Alarm Example Model | 1.0 | 1 | 419 |
| nlpcraft.weather.ex | Weather Example Model | 1.0 | 3 | 9045 |
| nlpcraft.helloworld.ex | HelloWorld Example Model | 1.0 | 0 | 0 |
| nlpcraft.time.ex | Time Example Model | 1.0 | 1 | 432 |
| nlpcraft.echo.ex | Echo Example Model | 1.0 | 0 | 0 |
+--------------------------------------------------------------------------------+
...
+--------------------------+
| Probe started [5.12 sec] |
+--------------------------+
...
Mar-11 23:25:58 [INFO ] Server connection established.
</pre></section><section id="config"><h2 class="section-title">Configuration</h2><p> Both REST server and the data probe use <a target=_ href="https://github.com/lightbend/config/">Typesafe Config</a> for their configuration:</p><ul><li>Both the server and the data probe come with default configuration available in <code>build/<b>nlpcraft.conf</b></code> file.<li>Custom configuration or default overrides can be placed into a file or provided via environment variables.<li>Configuration files use <a target=_ href="https://github.com/lightbend/config/blob/master/HOCON.md">HOCON</a> file format.<li>Server and probe configuration can be placed in the same file or kept in separate files.</ul><p> By default, when REST server or data probe start they look for <code>nlpcraft.conf</code> configuration file in the same directory as <code>apache-nlpcraft-0.5.0-all-deps.jar</code> file and the on their classpath. You can change this behavior with <code>-config=path</code> parameter.</p><p> Default configuration is available in <code>build/<b>nlpcraft.conf</b></code> file and it is extensively documented. It has subsections for the server and probe configuration. When server and the probe use different files these whole sections should be placed into an individual file:</p><p> Server configuration file:</p><pre class="brush: js">
nlpcraft {
server {
...
}
}
</pre><p> Probe configuration file:</p><pre class="brush: js">
nlpcraft {
probe {
...
}
}
</pre><div class="bq info"> <b>Overriding Configuration</b><p> There are two ways to provide your own configuration for the server or the probe:</p><ul><li> Put your configuration into separate file and use <code>-config=...</code> parameter to specify the path of your configuration file.<li> Use environment variable to override specific single property.</ul><p> During development and testing, or when running in a container environment like Docker, it is more convenient to use environment variables to override just few specific configuration properties:</p><ol><li> Set probe or server JVM system property <code>-Dconfig.override_with_env_vars=true</code> which will instruct configuration framework to look for external overrides.<li>For each configuration property <code>x.y.z</code> set the overriding environment variable <code>CONFIG_FORCE_x_y_z=some_value</code></ol><p> Consider the following snippet of server configuration:</p><pre class="brush: js">
nlpcraft {
server {
...
lifecycle = [
"org.apache.nlpcraft.server.lifecycle.opencensus.NCJaegerExporter"
]
rest {
host = "0.0.0.0"
port = 8081
apiImpl = "org.apache.nlpcraft.server.rest.NCBasicRestApi"
}
...
}
}
</pre><p> You can override these properties with the following environment variables:</p><p> <code>CONFIG_FORCE_nlpcraft_server_rest_host=1.2.3.4</code><br> <code>CONFIG_FORCE_nlpcraft_server_lifecycle.0=org.apache.nlpcraft.server.lifecycle.opencensus.NCStackdriverTraceExporter</code><br> <code>CONFIG_FORCE_nlpcraft_server_lifecycle.1=org.apache.nlpcraft.server.lifecycle.opencensus.NCStackdriverStatsExporter</code></p></div></section></div><div class="col-md-2 third-column"><ul class="side-nav"><li class="side-nav-title">On This Page<li><a href="#server">REST Server</a><li><a href="#probe">Data Probe</a><li><a href="#config">Configuration</a><li class="side-nav-title">Quick Links<li> <i class="fab fa-fw fa-github mr-2"></i><a target="github" href="https://github.com/apache/incubator-nlpcraft/tree/master/src/main/scala/org/apache/nlpcraft/examples">Examples</a><li> <i class="fab fa-fw fa-java mr-2"></i><a target="_" href="/apis/latest/index.html">Javadoc</a><li> <i class="fas fa-fw fa-code mr-2"></i><a href="https://github.com/apache/incubator-nlpcraft/blob/master/openapi/nlpcraft_swagger.yml" target="github">REST API</a><li> <i class="fas fa-fw fa-download mr-2"></i><a href="/download.html">Download</a><li class="side-nav-title">Support<li> <nobr> <i class="fab fa-fw fa-jira mr-2"></i><a target="jira" href="https://issues.apache.org/jira/projects/NLPCRAFT/issues">JIRA</a> </nobr><li> <nobr> <i class="far fa-fw fa-envelope mr-2"></i><a href="http://mail-archives.apache.org/mod_mbox/nlpcraft-dev/">Dev List</a> </nobr><li> <nobr> <i class="fab fa-fw fa-stack-overflow mr-2"></i><a target="so" href="https://stackoverflow.com/questions/ask">Stack Overflow</a> </nobr><li> <nobr> <i class="fab fa-fw fa-github mr-2"></i><a target="github" href="https://github.com/apache/incubator-nlpcraft">GitHub</a> </nobr></ul></div></div></div></div><div id="footer"><div class="container"><div class="text-muted text-center"> <span>Copyright &copy; 2020 Apache Software Foundation</span> <span> <a target=_new href="https://apache.org"><img alt="asf" src="/images/asf_logo.png" height="24px"></a> </span> <a target="asf" href="http://apache.org/foundation/policies/privacy.html" class="btn btn-link ml-4">Privacy</a> <span class="sep"></span> <a href="/index.html#news" class="btn btn-link">News</a> <span class="sep"></span> <a href="/docs.html" class="btn btn-link">Docs</a> <span class="ml-4">release: <a href="/download.html"><code>0.5.0</code></a></span> <span class="ml-2"> <a target="jenkins" href="https://builds.apache.org/view/Incubator%20Projects/job/incubator-nlpcraft/"><img src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fbuilds.apache.org%2Fview%2FIncubator%2520Projects%2Fjob%2Fincubator-nlpcraft%2F"></a> <a target=_ href="https://gitter.im/apache-nlpcraft/community"><img alt="Gitter" src="https://badges.gitter.im/apache-nlpcraft/community.svg"></a> </span></div></div></div><script src="//code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js" integrity="sha384-cs/chFZiN24E4KMATLdqdvsezGxaGsi4hLGOzlXwp5UZB1LY//20VyM2taTB4QvJ" crossorigin="anonymous"></script> <script src="//stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js" type="text/javascript" ></script> <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.min.js" type="text/javascript" ></script> <script src="//cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.5/moment-timezone-with-data.min.js" type="text/javascript" ></script> <script type="text/javascript"> SyntaxHighlighter.defaults["auto-links"] = false; SyntaxHighlighter.defaults["tab-size"] = 2; SyntaxHighlighter.all(); </script>