OK i think im still missing some values, and some of these new stats
values dont seem to work, from the log4j layout i sent yesterday, ive
made a method to build the information into a hashmap. Here is the class
my app extends to get the log info, as you can see down below, i think
im missing a few things but something isnt right with the time values
for the new statistics methods as i cant calculate the duration correct,
im assuming though x-duration is the duration of the clip, and then
c-starttime and c-endtime is the start and finish times the client was
streaming. Im unsure where to put the sent bytes either in the c-bytes
or sc-bytes field. Im pretty sure windows media use the c-bytes field,
maybe its been sc-bytes all along which is server-client.
public class VODStatistics extends ApplicationAdapter
{
private static final Logger logStats =
Logger.getLogger(VODStatistics.class.getName());
private Map<String, Object> m = new HashMap<String,Object>();
private String[] fields =
{"c-playerversion","c-swffile","c-referer","c-totalbuffertime","x-duration"
,"x-app","x-appinst","avgbandwidth","maxbandwidth","c-proto","s-uri","date","time","s-session-id"
,"c-ip","c-port","s-ip","c-starttime","c-endtime","c-bytes","sc-bytes","c-os","c-playermanufacturer"
,"c-playertype","c-playerlanguage","c-screenres"};
@Override
public boolean appStart(IScope app) {
return true;
}
public void streamPublishStart(IBroadcastStream stream) {
}
public void streamPlaylistItemPlay(IPlaylistSubscriberStream stream,
IPlayItem item, boolean isLive) {
}
public void streamPlaylistItemStop(IPlaylistSubscriberStream stream,
IPlayItem item) {
}
public void streamPlaylistVODItemPause(IPlaylistSubscriberStream
stream, IPlayItem item, int position) {
}
public void streamPlaylistVODItemResume(IPlaylistSubscriberStream
stream, IPlayItem item, int position) {
}
public void streamPlaylistVODItemSeek(IPlaylistSubscriberStream
stream, IPlayItem item, int position) {
}
//#Fields: c-dns cs-uri-stem c-starttime x-duration c-rate c-status
c-playerid c-playerversion c-playerlanguage cs(User-Agent) cs(Referer)
c-hostexe c-hostexever c-os c-osversion c-cpu filelength filesize
avgbandwidth protocol transport audiocodec videocodec channelURL
sc-bytes c-bytes s-pkts-sent c-pkts-received c-pkts-lost-client
c-pkts-lost-net c-pkts-lost-cont-net c-resendreqs c-pkts-recovered-ECC
c-pkts-recovered-resent c-buffercount c-totalbuffertime c-quality s-ip
s-dns s-totalclients s-cpu-util cs-user-name s-session-id s-content-path
cs-url cs-media-name c-max-bandwidth cs-media-role s-proxied
@Override
public void streamSubscriberClose(ISubscriberStream stream) {
IConnection conn = Red5.getConnectionLocal();
IPlaylistSubscriberStream streamStats =
(IPlaylistSubscriberStream) stream;
logStream(streamStats, conn);
}
public void streamSubscriberStart(ISubscriberStream stream) {
}
private void logStream(IPlaylistSubscriberStream stream, IConnection
conn)
{
//c-playerversion
m.put(fields[0], conn.getConnectParams().get("flashVer"));
//c-swffile
m.put(fields[1], conn.getConnectParams().get("swfUrl"));
//c-referer
m.put(fields[2], conn.getConnectParams().get("pageUrl"));
//c-totlebuffertime
m.put(fields[3], stream.getStatistics().getEstimatedBufferFill());
//x-duration
m.put(fields[4], stream.getStatistics().getCurrentTimestamp() -
stream.getStatistics().getCreationTime());
//x-app
m.put(fields[5], conn.getPath());
//x-appinst
m.put(fields[6], conn.getScope().getName());
//avgbandwidth
m.put(fields[7], "n/a");
//maxbandwidth
m.put(fields[8], "n/a");
//c-proto
m.put(fields[9], conn.getType());
//s-uri
m.put(fields[10], conn.getConnectParams().get("tcUrl"));
//date
m.put(fields[11], new SimpleDateFormat("yyyy-MM-dd").format(new
Date()));
//time
m.put(fields[12], new SimpleDateFormat("HH:MM:SS").format(new
Date()));
//s-session-id
m.put(fields[13], conn.getSessionId());
//c-ip
m.put(fields[14], conn.getRemoteAddress());
//c-port
m.put(fields[15], conn.getRemotePort());
//s-ip
m.put(fields[16], conn.getHost());
//c-starttime
m.put(fields[17], stream.getStatistics().getCreationTime());
//c-endtime
m.put(fields[18], stream.getStatistics().getCurrentTimestamp());
//c-bytes
m.put(fields[19], conn.getWrittenBytes());
//sc-bytes
m.put(fields[20], stream.getStatistics().getBytesSent());
//c-os
m.put(fields[21], conn.getAttribute("os"));
//c-manufacturer
m.put(fields[22], conn.getAttribute("manufacturer"));
//c-playertype
m.put(fields[23], conn.getAttribute("type"));
//c-playerlanguage
m.put(fields[24], conn.getAttribute("lang"));
//c-screenres
m.put(fields[25], conn.getAttribute("res"));
logStats.info(m);
}
}
Red5 Flash Streaming Server v0.6
c-playerversion c-swffile c-referer c-totalbuffertime
x-duration x-app x-appinst avgbandwidth maxbandwidth
c-proto s-uri date time s-session-id c-ip c-port
s-ip c-starttime c-endtime c-bytes sc-bytes c-os
c-playermanufacturer c-playertype c-playerlanguage c-screenres
MAC 9,0,28,0 Player.swf null 0.0 -1178712302729 theapp/
theapp n/a n/a persistent rtmp://192.168.1.1/theapp/
2007-05-09 22:05:841 null 192.168.1.1 52776
192.168.1.1 1178712302729 0 768741 0 null null
null null null
MAC 9,0,28,0 Player.swf null 0.0 -1178712311004 theapp/
theapp n/a n/a persistent rtmp://192.168.1.1/theapp/
2007-05-09 22:05:898 null 192.168.1.1 52776
192.168.1.1 1178712311004 0 9186717 0 null null
null null null
MAC 9,0,28,0 Player.swf null 0.0 -1178712323005 theapp/
theapp n/a n/a persistent rtmp://192.168.1.1/theapp/
2007-05-09 22:05:609 null 192.168.1.1 52776
192.168.1.1 1178712323005 0 17621087 0 null null
null null null
MAC 9,0,28,0 Player.swf null 0.0 -1178712386464 theapp/
theapp n/a n/a persistent rtmp://192.168.1.1/theapp/
2007-05-09 22:05:493 null 192.168.1.1 52776
192.168.1.1 1178712386464 0 26049356 0 null null
null null null
Modification to the layout class was
Default fields list
protected String[] fieldsList =
{"c-playerversion","c-swffile","c-referer","c-totalbuffertime","x-duration"
,"x-app","x-appinst","avgbandwidth","maxbandwidth","c-proto","s-uri","date","time","s-session-id"
,"c-ip","c-port","s-ip","c-starttime","c-endtime","c-bytes","sc-bytes","c-os","c-playermanufacturer"
,"c-playertype","c-playerlanguage","c-screenres"};
Fields setter creates new fields array from the log4j settting
public void setFields(String patternFields) {
// pattern = conversionPattern;
fields = patternFields;
fieldsList = fields.split(",");
//head = createPatternParser(patternFields).parse();
}
getHeader builds the column header from this
@Override
public String getHeader() {
StringBuffer result = new StringBuffer();
result.append(fieldsList[0]);
for (int i=1; i<fieldsList.length; i++) {
result.append(delimiter);
result.append(fieldsList[i]);
}
return "\n\nRed5 Flash Streaming Server v0.6 \n\n" + result + "\n";
}
Format method returns the built string
public String format(LoggingEvent event) {
// Reset working stringbuffer
if(sbuf.capacity() > MAX_CAPACITY) {
sbuf = new StringBuffer(BUF_SIZE);
} else {
sbuf.setLength(0);
}
map = (Map<String, Object>) event.getMessage();
for (int i = 0; i < fieldsList.length; i++)
{
sbuf.append(map.get(fieldsList[i]) + delimiter);
}
sbuf.append("\n");
return sbuf.toString();
}
Dan Rossi wrote:
> Ok apologies you can call the aware handler like
>
> public void streamSubscriberClose(IPlaylistSubscriberStream stream) {
>
> Seems you also have to calculate the duration, im hoping its the right
> one, but ill just create a helper class to include all stats into the
> one package so they are all methods and properties in the one place like
> FMS.
>
> Dan Rossi wrote:
>
>> I can see the methods in PlaylistSubscriber however when i bring it up
>> here the methods arent there
>>
>> public void streamSubscriberClose(ISubscriberStream stream) {
>>
>>
>> Joachim Bauch wrote:
>>
>>
>>> Hi,
>>>
>>> Steven Gong schrieb:
>>>
>>>
>>>
>>>> Yes, it's been removed after the logic of tracking the client buffer is
>>>> enhanced. We assumed that the StreamFlow only aims to control the client
>>>> buffer and didn't notice that it's been exposed as an API. It seems that
>>>> we need to add this functionality back. Thanks for the reminder.
>>>>
>>>>
>>>>
>>> Steven's right about the removal of IStreamFlow. After all it was an
>>> internal interface (i.e. not in or below org.red5.server.api) so I thought
>>> it was safe to delete it ;) It only was used to calculate the client
>>> buffer - and that it didn't do correctly...
>>>
>>> To provide a better way for querying of statistics, I commited some
>>> interfaces in r1979 where I started working on an API to get live
>>> informations.
>>>
>>> Feel free to check them out in "org.red5.server.api.statistics" and give
>>> some feedback about them and other things you need to get from the stats.
>>>
>>> Joachim
>>>
>>> _______________________________________________
>>> Red5 mailing list
>>> [email protected]
>>> http://osflash.org/mailman/listinfo/red5_osflash.org
>>>
>>>
>>>
>>>
>> _______________________________________________
>> Red5 mailing list
>> [email protected]
>> http://osflash.org/mailman/listinfo/red5_osflash.org
>>
>>
>>
>
>
> _______________________________________________
> Red5 mailing list
> [email protected]
> http://osflash.org/mailman/listinfo/red5_osflash.org
>
>
_______________________________________________
Red5 mailing list
[email protected]
http://osflash.org/mailman/listinfo/red5_osflash.org