10.3. Server Management API Uses
Now that we have covered the Server Management API basics, we can discuss some possible uses for the Admin Service and the ActionScript API that grants access to it. The obvious example is to create a Flash movie that monitors a FlashCom Server. The Communication Application Inspector is an example of such a Flash movie. Also available on the book's web site is a sample application that extends the features of the App Inspector, some features of which are discussed shortly.
The vital statistics that you need to know about any FlashCom Server are the memory, processor, and bandwidth consumption. These statistics are the key pieces of information that indicate how well an application is performing and if it is under significant load and possibly near a critical state. To access this information, use the getServerStats( ) method. Example 10-11 illustrates how to poll the server and display these statistics in a TextArea component.
import com.oreilly.pfcs.admin.FCSAdminConnector; import com.oreilly.pfcs.admin.FCSAdminAdaptor; import com.oreilly.pfcs.admin.PendingAdminCall; adminConn = new FCSAdminConnector( ); adminConn.host = "www.yourhost.com"; adminConn.username = "admin"; adminConn.password = "flash"; adminConn.addEventListener("connect", this); adminConn.connect( ); adminAPI = new FCSAdminAdaptor(adminConn); function connect (e:Object) { monitorServer( ); monitorInterval = setInterval(this, "monitorServer", 1000); } var lastBandwidthIn = 0; var lastBandwidthOut = 0; function monitorServer ( ) { var pcall:PendingAdminCall = adminAPI.getServerStats( ); pcall.responder.result = function (result) { var data = result.data; var io = data.io; var out = ""; out += "Current Users : " + io.connected + newline; out += "CPU : " + data.cpu_Usage + newline; out += "RAM : " + data.memory_Usage + newline; if (lastBandwidthIn > 0) { out += "Bandwidth Out : " + calcBW(io.bytes_out, lastBandwidthOut) + newline; out += "Bandwidth In : " + calcBW(io.bytes_in, lastBandwidthIn) + newline; } _root.output.text = out; lastBandwidthOut = io.bytes_out; lastBandwidthIn = io.bytes_in; }; } function calcBW (currentBW, lastBW) { return (Math.round(((currentBW - lastBW) * (8 / 1024))*100)/100) + " Kbps"; }
This example first establishes a connection to the server with the FCSAdminConnector class and then creates an interval that polls the server every second for server statistics. Once per second, the data is returned and displayed to the user . Only a few elements of the data are actually displayed in this example and the rest of the properties are ignored, but you can experiment with it and add other useful properties to display.
|
Multiply the number of bytes by 8 to determine the number of bits. To convert bits to kilobits, divide by 1000. To convert bits into megabits divide by 1,000,000. This will be the actual number to use to determine how close you are to the license limits.
Monitoring these statistics can be taken further as well. The data returned from the Server Management API doesn't have to be destroyed every second. You could collect that data in various storage formats. For example, you could use a local shared object, remote shared object, or data stream to collect a sample of the data to later run an analysis. You could also ship the data off to a database for more robust and flexible storage. This data can be invaluable in determining peak usage times and general capacity for making hardware and software purchasing decisions.
A sample application that exposes most of the features of the Server Management API can be downloaded from the book's web site. This application provides an example of how to view the detailed data that can be gathered from the Admin Service and can be used as the basis to build more sophisticated monitoring applications that can further collect data for analysis.
If you are creating a multiroom application, such as a chat room system, or other similar scenarios, you could also use the Server Management API to gather statistics about each instance of the application to display to the users. For example, if you had multiple chat rooms, you could use the Server Management API to list the total number of users in each room. You could obviously implement this in other ways, including using proxy shared objects, but each of those methods requires additional interinstance connections, which consume part of your server license. Connections to the Admin Service do not count against the FlashCom license, so this can be a useful way to conserve license slots and add the global room data necessary to make a rich multiroom application.
Imagine that we have an application named ChatRooms . This application has multiple rooms, and we want to display the current number of participants in each room. The previous examples in this chapter used client-side ActionScript 2.0. Server-Side ActionScript is still based on ActionScript 1.0, but the basic ideas of using the NetConnection object and its methods still apply to any server-side examples; only the syntax will look slightly different. The Server-Side ActionScript in Example 10-12 periodically polls the Server Management API for all of the instances of the application and gathers how many users are connected to each instance.
application.onAppStart = function ( ) { this.adminConn = new NetConnection( ); this.applicationName = this.name.split("/")[0]; this.adminConn.onStatus = function (info) { if (info.code == "NetConnection.Connect.Success") { this.loopInterval = setInterval(application, "loopRoomStats", 10000); application.loopRoomStats( ); } }; this.adminConn.connect("rtmp://localhost:1111", "username", "password"); this.roomTotals = SharedObject.get("roomTotals", false); }; application.loopRoomStats = function ( ) { var instanceResponder = new Object( ); instanceResponder.onResult = function (result) { var data = result.data; for (var i in data) { var name = data[i]; if (name.indexOf(application.applicationName) == 0) { application.getRoomStats(name); } } }; this.adminConn.call("getActiveInstances", instanceResponder); }; application.getRoomStats = function (roomName) { var resp = new Object( ); resp.roomName = roomName; resp.onResult = function (result) { var data = result.data; application.roomTotals.setProperty(this.roomName, data.connected); }; this.adminConn.call("getInstanceStats", resp, roomName); }; application.onAppStop = function ( ) { this.adminConn.close( ); this.roomTotals.close( ); clearInterval(this.loopInterval); };
In the application.onAppStart( ) method, we first create the NetConnection object and connect it to the Admin Service. At the same time, we create a shared object that is used to cache the room statistics gathered from the API and deliver the data to the connected clients . When the onStatus( ) callback method executes, we initialize an interval to run every 10 seconds and gather the room statistics. The application.loopRoomStats( ) method calls getActiveInstances( ) to list the available rooms and call application.getRoomStats( ) on each room. Once the room statistics have been gathered, the connected property is mapped as the value for the room name in the shared object.
To display this data on the client side, all we would have to do is subscribe to the roomTotals remote shared object and map the room count properties to a visual display. Each room instance will have a corresponding entry in the roomTotals shared object that holds the total number of users connected to each instance. This approach is a proven strategy to gather data from a multiple-instance application and will work for many situations.
|
Along with the ActionScript API discussed throughout this chapter, several log streams are available from the Admin Service. Fundamentally, the log streams are the same as any other FlashCom stream, except these streams contain only data and are available only if you are logged in to the Admin Service. The two types of log streams available are access logs and application logs. Like other FlashCom streams, these streams can also be recorded and used for later playback. Turning on the recording feature of the streams is handled in the configuration files. The access log stream is handled at the virtual host level, and that configuration setting is found in the Vhost.xml file for each adaptor. Set the following flag to TRue to record (store) the access log:
<RecordAccessLog>true</RecordAccessLog>
The configuration for the application logs is found in each Application.xml file. Set the following flag to true to record (store) the application log:
<RecordAppLog>true</RecordAppLog>
|
Either of the logs can be played as live streams or recorded streams. Playing the stream as a live stream will listen in real time for new events to be posted to the stream. If you play the log stream as a recorded stream, all of the historical data will be either played back in real time or immediately flushed to the client, depending on the parameters passed to the NetStream.play( ) method.
The access log is simply a record of all of the connection attempts to the server. This stream will contain a lot of connect and disconnect messages including basic information about what clients connected to and where they connected from.
The application logs are a bit more complicated and display all of the compile and runtime errors generated by an application. The application logs are also the stream to which server-side trace( ) methods are sent. Regardless of the stream type or the source of the message, the method triggered on the listening NetStream object is always onLog( ) . The onLog( ) method should accept a single argument, an information object. This object is formatted similarly to other FlashCom response arguments and is a collection of properties including, but not limited to, description , code , and level .
Example 10-13 demonstrates how to play an access log stream.
accessLog = new NetStream(adminConn); accessLog.onLog = function (msg) { for (var i in msg) trace(i + " : " + msg[i]); }; // Play it as a live stream. accessLog.play("logs/access", -1); // Or play it as a recorded stream. accssLog.play("logs/access", 0, -1, 3);
This code should look really familiar, as it is akin to playing any other FlashCom stream. The two versions of the accessLog.play( ) call illustrate listening to the stream as a live stream or a recorded stream. In the latter example, the value 3 is used as the fourth parameter to indicate that we want all of the data events to be flushed immediately and we want to reset any playlists that might be stored on the server.
Application log streams work exactly the same as access log streamsthe only difference is the stream name. The stream name for an application log stream consists of the same "logs/" prefix but with an additional "application" prefix followed by the full application instance name. The full format is as follows :
logs/application/ applicationName / instanceName
Example 10-14 demonstrates how to play an application log stream.
myAppLog = new NetStream(adminConn); myAppLog.onLog = function (msg) { for (var i in msg) trace(i + " : " + msg[i]); }; myAppLog.play("logs/application/pfcschat/adminchapter", -1);
There are a couple of additional special log streams that do not seem to have corresponding configuration file entries and are not listed in any available documentation. A special stream named logs/application/? is used as a catchall log. If a log is not attached to a particular application, the warning and trace messages are sent to this special log. For example, an application that has a compile error and was not recently running would send its compile error messages to the catchall log. Another special stream, named logs/system , appears to be rarely used.