Giter Club home page Giter Club logo

ampm's Introduction


application
management
+
performance
monitoring

ampm is Stimulant's tool for monitoring public-facing software that needs to run 24/7. It does a bunch of things:

  • Launches an application and restarts it when it crashes, leaks, or whenever you want it to.
  • Provides application configuration, and applies different settings for different environments.
  • Makes it easy to log troubleshooting information to a file, and email out any errors or crashes.
  • Makes it easy to integrate Google Analytics with an application.
  • Provides hooks for custom server-side logic and ways for multiple instances of an app to communicate.
  • Provides a mobile-friendly web panel which displays app status and controls.
  • Supports any application type that can speak websockets or OSC. There are samples for web apps, WPF, Cinder, Unity, and Processing.

Installation

ampm relies on the nodemon utility, which must be installed first. Just run npm install -g nodemon from an administrator command prompt to install it.

Then to install ampm from npm, just do npm install -g ampm.

To install from source, clone the repo, and do npm link from the root of the repo. This is the best way to do development on ampm itself.

Execution

After installing, the ampm command should be available on your system. The command only has two arguments, one for a configuration file, and one for the mode to run in. With no arguments, ampm will use the ampm.json configuration file and the default configuration within it.

To use a different configuration file or mode (explained further below), you can use:

ampm ampm.json dev

You can also specify multiple configuration files. The first one will be the one used, but you can then switch between them using the web console.

ampm app1.json,app2.json,app3.json live

If you pass arguments other than the config file and the mode, those will be passed as arguments to nodemon.

Note that machine restart functionality requires executing ampm with administrative privileges.

sudo ampm ampm.json

Configuration

ampm requires a configuration file in order to monitor your application. Start with a file called ampm.json, placed somewhere near your application binary.

You can include multiple configuration schemes in the same json file. For example.

{
    "default": {
        // lots of configuration
    },
    "dev": {
        // only the configuration which overrides the default
    },
    "dev.foo" {
        // only the configuration which overrides default and dev
    },
    "machinename" {
        // configuration to apply on a specific machine
    },
    "machinename.dev" {
        // configuration to apply only to a specific machine in dev
    }
}

You can specify which configurations to use as an argument to node:

  • use the default: ampm ampm.json, or just ampm
  • use the dev configuration: ampm ampm.json dev
  • use the dev.foo configuration: ampm ampm.json dev.foo

You don't have to explicitly specify the usage of machine-specific configurations, that will happen automatically if the current machine name matches a configuration.

The configuration is broken into a number of modules. You only need to specify the defaults you want to override.

Persistence

The persistence manager is in chage of starting a process, monitoring it, restarting it if it dies, and triggering updates on a schedule. At a minimum you'll need to set the launchCommand here in order to monitor anything.

"persistence": {
    // The command to run to launch the client, relative to the config file.
    "launchCommand": "",

    // The command to run to launch a parallel process, relative to
    // the config file. {config} will be replaced with the contents of the config
    // file. This process will be stopped and started at the same time as the
    // main process.
    "sideCommand": "",

    // A command to run after the first heartbeat to do any additional
    // system configuration.
    "postLaunchCommand": "",

    // Restart the app if it doesn't start up in this much time. Set to
    // zero (default) to allow the app to take forever to start up.
    "startupTimeout": 0,

    // Restart the app this many seconds of no heartbeat messages. Set to
    // zero (default) to never restart due to lack of heartbeats.
    "heartbeatTimeout": 0,

    // Restart the machine after this many app restarts.
    "restartMachineAfter": Infinity,

    // Shut down the app on this schedule -- see cronmaker.com for the format.
    "shutdownSchedule": null,

    // Shut down the PC on this schedule -- see cronmaker.com for the format.
    "shutdownPcSchedule": null,

    // Start up the app on this schedule -- see cronmaker.com for the format.
    "startupSchedule": null,

    // Restart the app on this schedule -- see cronmaker.com for the format. 
    "restartSchedule": null,
    
    // Restart the PC on this schedule -- see cronmaker.com for the format.
    "restartPcSchedule": null,        

    // Restart the app if it uses more than this much memory.
    "maxMemory": Infinity
}

Permissions

If permissions are specified, the console is locked down with a username and password. Multiple users can be defined, each with different sets of permissions. By default, there is no access control.

"permissions": {
    // A username.
    "test4": {
        // The password for that user.
        "password": "test4",
        
        // If true, the user can shutdown, start, and restart the app.
        "app": true,
        
        // If true, the user can restart the computer.
        "computer": true
    }
}

Logging

The logging module sends logs from ampm and the application being monitored to a number of places. In a dev environment you probably want to turn most of the logging off.

// Settings for the logging module.
"logging": {
    // Settings for the file logger.
    "file": {
        "enabled": true, // false to turn off
        "filename": "logs/server", // Path to the log file, relative to the config file.
        "maxsize": 1048576, // The max size of the log file before rolling over (1MB default)
        "json": false, // Whether to log in JSON format.
        "level": "info" // The logging level to write: info, warn, error.
    },

    // Settings for the console logger.
    "console": {
        "enabled": true, // false to turn off
        "colorize": true, // Colors are fun.
        "timestamp": true, // Include timestamps.
        "level": "info", // The logging level to write: info, warn, error.
        "preserve": false // If false, the ampm client should send console output to the server if possible.
    },

    // Settings for Google Analytics.
    "google": {
        "enabled": true, // false to turn off
        "accountId": "", // The property ID -- this should be unique per project.
    },

    // Settings for the event log file.
    "eventFile": {
        "enabled": true, // false to turn off
        "filename": "logs/event-{date}.tsv" // Path to the log file, relative to the config file. {date} will be replaced by the current date.
    },

    // Settings for screenshots taken after crashes.
    "screenshots": {
        "enabled": true, // false to turn off
        "filename": "logs/capture-{date}.jpg" // Path to save screen shots, relative to the config file. {date} will be replaced by the current date.
    },

    // Settings for loggly.com.
    "loggly": {
        "enabled": false, // false to turn off
        "subdomain": "", // The account name. https://stimulant.loggly.com/dashboards
        "inputToken": "", // The API token.
        "json": true, // Whether to log as JSON -- this should be true.
        "token": "", // The um, other token.
        "tags": "ampm" // A tag to differentiate app logs from one another in loggly.
    },

    // Settings for the email logger.
    "mail": {
        "enabled": true, // false to turn off
        "ssl": false, // Whether to use SSL.
        "subject": "ERROR: {hostname}", // The subject of the emails. "{hostname}" is replaced by the output of os.hostname(). Paths to anything in the config object can be used as well.
        "level": "error", // The logging level to write: info, warn, error.
        "host": "", // The SMTP server to use.
        "username": "", // The account to log in with.
        "from": "", // Where the emails should appear to be from.
        "password": "", // The password to log in with.
        "to": "" // Where the emails should go.
    },

    "cacheAmount": 20 // How many lines of logs and events to show in the web console.
}

Networking

The networking module coordinates connections between ampm, the application its monitoring, the web console, and other ampm instances.

"network": {
    // The port used to communicate between node and the browser. This is also the URL you'd use
    // to access the console, such as http://localhost:8888.
    "socketToConsolePort": 8888,

    // The port used to communicate between node and the client app over a TCP socket. This is
    // used for the app to send log messages and event tracking.
    "socketToAppPort": 3001,

    // The port used to communicate from the client app to the server over UDP/OSC. 
    "oscFromAppPort": 3002,

    // The port used to communicate from the server to the client app over UDP/OSC.
    "oscToAppPort": 3003
}

Custom Plugins

You can have ampm run custom code by including the path to a module in the plugin attribute:

    "plugin": "plugin.js"

This should be a class called Plugin. It will be instantiated and it's boot() method called at startup.

This is a handy place to implement a web server for your app, or to listen to custom web socket messages from your app, or to implement a sync layer between multiple applications.

Integration with Applications

ampm implementes a web socket server with socket.io on port 3001 by default, and an OSC server on port 3002/3003. Heartbeats should be sent via one of those means for application monitoring, but other messages can be sent that way too, and handled in a plugin, as described above. For specific implementation details and examples, see the samples.

Application Configuration

In addition to the ampm configuration described above, you can include arbitrary JSON in the configuration file that pertains to your specific application. This is especially handy if you have the same application running on multiple machines, and each machine needs different settings for some reason.

ampm will serve up that part of the configuration with a request to /config, by default at http://localhost:8888/config.

Another way to get the configuration is to emit configRequest over the web socket. ampm will respond with a configRequest event containing the config data. For specific implementation details and examples, see the samples.

Heartbeat Monitoring

The persistence layer works by listening for a heartbeat message from the app on an interval. If it doesn't get one, it will restart the app (or the machine, if you want). To send a heartbeat message, send an OSC message over UDP to localhost on the port specified in network.oscFromAppPort (default is 3002) that's simply the string heart. You should probably do this when every frame is rendered.

For web applications, use a TCP message to network.socketToAppPort (default is 3001) via a web socket that is also just heart.

Logging

You can log any message to ampm and it will go through its logging mechanism, including emailing errors out, etc. To send a log message, send a TCP message over a web socket on network.socketToAppPort (default is 3002). The event name should be log and the payload should be an object like this:

{
    "level": "info",
    "message": "my log message"
}

The level can be error, warn, or info. error is the most severe, and is emailed out by default. This can be configured with logging.mail.level.

Event Tracking

ampm can track events indicating normal usage, such as button clicks or accesses to various content. These are sent to Google Analytics and configured via logging.google. To track an event, send a TCP message over a web socket on network.socketToAppPort (default is 3002). The event name should be event and the payload should be an object like this:

{
    "Category": "a name that you supply as a way to group objects that you want to track",
    "Action": "name the type of event or interaction you want to track",
    "Label": "provide additional information for events that you want to track, such as title of content",
    "Value": "some relevant numeric value"
}

More information about the types of data to include in the event tracking message can be found on the Google Analytics site.

Application Restart

Sending a restart message ovr the websocket or OSC connection will cause ampm to restart the application on demand.

ampm's People

Contributors

apavani avatar endquote avatar igierard avatar joelpryde avatar kitschpatrol avatar lritesh avatar peterobbin avatar potioninstallation avatar sorob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ampm's Issues

Debug mode

A config setting to output more debugging information to the console.

  • incoming/outgoing OSC messages
  • incoming/outgoing websocket messages
  • analytics data
  • ....etc

ampm portfolio

Include links in the readme to projects which use ampm in production environments.

file name and line number for error logging

We're using some code similar to the AMPMClient.cpp to send error messages to AMPM, however it seems like the file name and line number don't show up in the logs. Is this by design, or could it be made optional?

For now I'm just prepending the location info the the message string that send across, but wondering if I'm not meant to do that.

Screenshot support for Raspberry Pi?

Hi! I was pleasantly surprised to find that ampm seems to install & run fine on rPi running the latest Raspian (2016-11-25-raspbian I guess?).

One thing I realized is that screen shots wouldn't work and dug in a little bit. There's a utility called scrot which is included - not sure if it's part of Raspian normally or only when you install the "full" version with their new PIXEL windowing environment - and works fine, creating a PNG image.

I looked into the platform detection for a second and see that node's process.platform will return linux on rPi, but I'm not sure how to detect an rPi vs a full x86 desktop machine, and/or whether the scrot app would be included with something like a standard Debian, Ubuntu etc. install.

I'm half thinking out loud/half throwing this out there to see if this is something you've thought about at all, whether you care if trying to take a screenshot fails on linux, etc. It seems it'd be easy enough to change the platform detection logic to make it work, but then you open a new can of worms about "incomplete linux support."

Can I restart the application from within a plug-in?

I've got a python script that I want to run before our application starts up in the morning that downloads and caches new content from our CMS. I'm thinking that the easiest way to reload after this happens is to restart the application. Is there a way to send a command to AMPM to do this? I realize I could call App::quit() from within C++ and rely on the heartbeat checker to cause a restart, but this feels a bit hacky.

Side question: how would you recommend running the python script? It doesn't look like a can run a "preLaunchCommand", although I think I can get by with a "postLaunchCommand", letting the app run in the meantime, then restarting afterwards.

Thanks for any help.. and really enjoying using this tool that you've created.

Possible to update "heartbeatTimeout" from app via OSC?

I've got a tricky situation in our app where we know that the main update loop is going to snag for a long period of time while loading data, perhaps a couple minutes or so. Would it be possible to set the "heartbeatTimeout" longer for this duration, and then decrease it something much more responsive after the load is complete?

My understanding is that this is different to "startupTimeout", because I have actually already started up and it is now in a 'loading data from remote server' phase, but isn't yet interactive.

Support for custom branding

Structure the CSS in the web panel to make it easy to override, and add a config setting to specify an alternate CSS file. Remove hard-coded Stimulant branding.

Space in user path error?

After installation, launching ampm from the Cinder sample folder causes this error:
'C:\Users\Eric' is not recognized as an internal or external command,
operable program or batch file.

The full path is C:\Users\Eric Renaud-Houde\Code\ampm\samples\Cinder.

Am I missing something obvious?

Mac Cinder sample, error running server: "env: node\r: No such file or directory"

This is probably something simple, reading around it might be because one of the script files has a windows-style carriage return? I'm extremely unfamiliar with node, so opening this here.

When I follow the directions for the Cinder sample and run ampm from the samples/Cinder directory on Mac OS X, this is what I get:

[r@Richs-MacBook-Pro Cinder (master *)]$ ampm ampm.mac.json
env: node\r: No such file or directory

sending events / logs with unicode chars

An issue came up where we were trying to send an event for analytics that contained a utf-16 char, for example "Writing Chicago\u2019s Story". We can correctly draw this string in the application, however when we sent that to AMPM (using something like this function), it would crash the server with the following printed to console:

2016-06-27T21:39:30.789Z - warn: OSC messages should be JSON
C:\Users\potion-nw-wall\projects\northwestern\nw\tools\monitoring\ampm\model\logging.js:233            
this._google.event(data.Category, data.Action, data.Label, data.Value);

TypeError: Cannot read property 'Category' of null    at exports.Logging.BaseModel.extend._logEvent (C:\Users\potion-nw-wall\projects\northwestern\nw\tools\monitoring\ampm\model\logging.js:233:36)
at wrapper (C:\Users\potion-nw-wall\projects\northwestern\nw\tools\monitoring\ampm\node_modules\lodash\index.js:3095:19)
at emitOne (events.js:77:13)
at emit (events.js:169:7)
at exports.Network.BaseModel.extend._handleOsc (C:\Users\potion-nw-wall\projects\northwestern\nw\tools\monitoring\ampm\model\network.js:175:19)
at null.<anonymous> (C:\Users\potion-nw-wall\projects\northwestern\nw\tools\monitoring\ampm\model\network.js:152:22)
at wrapper (C:\Users\potion-nw-wall\projects\northwestern\nw\tools\monitoring\ampm\node_modules\lodash\index.js:3095:19)
at emitTwo (events.js:87:13)
at emit (events.js:172:7)
at Socket.<anonymous> (C:\Users\potion-nw-wall\projects\northwestern\nw\tools\monitoring\ampm\node_modules\node-osc\lib\Server.js:27:20)

[nodemon] app crashed
[nodemon] exiting
[nodemon] 1.9.2
[nodemon] to restart at any time, enter `rs`
[nodemon] ignoring: .git .nyc_output .sass-cache bower_components coverage node_modules logs C:\Users\potion-nw-wall\projects\northwestern\nw\tools\monitoring\ampm-state.json
[nodemon] watching: C:\Users\potion-nw-wall\projects\northwestern\nw\tools\monitoring\ampm.json C:\Users\potion-nw-wall\projects\northwestern\nw\tools\monitoring\ampm-restart.json
[nodemon] watching extensions: js,json
[nodemon] starting `node C:\Users\potion-nw-wall\AppData\Roaming\npm\node_modules\ampm\server.js ..\tools\monitoring\ampm.json default`
[nodemon] child pid: 11200
[nodemon] watching 2 files

Merging config: default
Merging config: default
Merging config: DESKTOP-RNH48JB
Merging config: DESKTOP-RNH48JB.default
Server starting up.
2016-06-27T21:39:32.219Z - info: App starting up.

So, the json appears in node.js as malformatted. We've been investigating whether this is a problem with cinder's OSC implementation, however I don't believe it is - ci::osc just serializes the std::string as raw bytes. However, @LRitesh has pointed out that the OSC spec specifies that OSC-string should be only ASCII. Cinder's implementation doesn't seem to care, but perhaps the json parse in javascript does? This is the extent of my knowledge on the situation.

If it turns out to be that we just aren't allowed to send unicode chars as OSC-string to AMPM, one solution we've thought about is whether we could send the events / logs as OSC-blob instead, so they can be parsed with unicode chars and all on the other end.

Also, am I correct in thinking that analytics.js supports utf8 / 16?

Java Application Monitoring

Hey so I'm trying to configure this to work with a java-based server and am running into issues. I am passing a number of arguments to java and launching the .jar file via batch file on windows. If I use ampm to launch the batch file, it starts up but ampm doesn't acknowledge the .jar executable as I believe it only takes into account the batch file itself (.bat). What happens is ampm keeps trying to launch the .bat file over and over again rather than track and monitor the .jar. How can I reliably launch and monitor a .jar file while ensuring I can also pass arguments to it? Also I realize the project is rather old at this point so no worries if no one is still maintaining these forums. Thanks for making this!

Defining "macosx" config within main ampm.json

I was wondering if its possible to define a config mode for different platforms within the main ampm.json file, it seems like I should be able to from your readme but I haven't yet figured out how.

Basically, I'd like the "default" section to define how the app would run on our production PC, and then the "macosx" mode would just override the minimal amount to run the appropriate app on that platform (I'm overriding all of "persistence", would hopefully only have to override persistence.launchCommand). This is some example config:

{
    "default": {
        "persistence": {
            "launchCommand": "../../applications/MyApp/vc2013/build/x64/RelWithDebInfo/MyApp.exe",
            "maxMemory": 0,
            "startupTimeout": 10,
            "heartbeatTimeout": 5
        },
        "permissions": {
            "user": {
                "password": "pw",
                "app": true,
                "computer": true
            }
        },
        "logging": {
            "file": {
                "filename": "logs/server"
            }
        }
    },
    "macosx": {
        "persistence": {
            "launchCommand": "../../applications/MyApp/xcode/build/Debug/MyApp.app/Contents/MacOS/MyApp",
            "maxMemory": 0,
            "startupTimeout": 10,
            "heartbeatTimeout": 5
        }
    }
}

When I try to run ampm macosx, it looks like nothing in the "persistence" sectio is set, so no launchCommand. Am I misunderstanding how this is supposed to work?

Kill explorer on startup

Let's look at killing explorer.exe when ampm starts up, and restoring it when it closes. This would disable the taskbar, windows charms, etc.

Make printing config to console an option?

Right now running ampm will print the config json to console. It's super useful while debugging but it'd be cool to make this an option so if the app goes down on a public display, the config details (which might have analytics email/password info in it) is not visible.

Limit the rate of emails

Don't let an error in a loop send infinite emails. Queue errors up and send at most one per minute or so?

Does this apply to other logging methods as well?

Monitor console output of launched app

This might be a dumb question, but is there any way to visualize the console output of a Mac app launched via launchCommand?

I have an app that's been crashing only when launched with AMPM and I need to check its exception messages.

Thanks!

Consider adding nomousy.exe as the cursor handler

Startup scripts call it to hide cursor at startup. ampm panel could have a toggle cursor link which calls it. Can't have hide/show links because there isn't really a way to query the current state.

Bad path to server.js, in start.js. ampm never starts

First, this is an amazing tool, thank you so much!

I implemented on an OSX project, all smooth. Now I've migrated the app over to Windows 10, and am running into issues with ampm. The ampm server fails to start properly, and just loops trying to. I've found I can resolve the issue by altering the ampm module's source code in the following way:

start.js, line 27
from: server = path.join(path.dirname(server), 'node_modules', 'ampm', 'server.js');
to: server = path.join(path.dirname(server), '..', 'ampm', 'server.js');

My value for server as returned by the child process on line 26 is:
C:\Users\path\to\application\node_modules\.bin\ampm.cmd,

Interestingly, my value for server as of line 20 (start.js), is valid on both OSX & Windows (so everything works if I comment out lines 26 & 27).

I've installed my modules using Yarn. Could that be using the .bin differently than normal npm installs? Not sure what the real solution to this is exactly. I can certainly fork the module for my needs but would rather have a proper fix either with the way I'm using ampm or with the official module itself. Thanks!

restart app on crash

Is there a way to have AMPM auto-restart my application when it stops, without having to integrate against AMPM's watchdog endpoint?

ampm on linux?

I was wondering if anyone has successfully used AMPM on linux, as I'm running into some issues that I haven't been able to track down. It is really easy to set up and seems to work almost entirely, but then I'm getting mysterious "App shut down by force." messages. I'm sure that I'm sending out heartbeats at this point, but I'm not sure why that message is happening and the app is being restarted regardless.

Also, I'm seeing an issue with logging in with credentials - they appear to get mixed up and it no longer accepts my specified username / password.

For background info, we're running a cinder 0.9.1 application in Ubuntu 16.04, node v6.11.1 and latest ampm from npm.

Example of how to send event to google analytics from cinder app?

Hi there, and thanks for this project, it looks very good for installations. I'm currently reviewing some options for how we can integrate google analytics into our application and I noticed that your README has a section on Event Tracking. Is there any example code that makes use of this? Particularly, I'm wondering how the payload should be sent over OSC from within a cinder app, as it looks like the expected payload is a JSON / JS object.

Thanks again!
Rich

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.