# Copyright (c) 2012 Flowerfire, Inc. All Rights Reserved. akamai_streaming = { plugin_version = "1.2" # 2012-05-08 - 1.0 - GMF - Initial creation # 2012-06-11 - 1.1 - GAS - Added media_reports snapon # 2013-06-25 - 1.2 - GMF - Fixed parsing of #Fields line to include final field info.1.manufacturer = "Akamai" info.1.device = "HTTP Streaming (W3C)" info.1.version.1 = "1.0" # #Version line shows 1.0 # The name of the log format log.format.format_label = "Akamai HTTP Streaming (W3C) Log Format" log.miscellaneous.log_data_type = "generic_w3c" log.miscellaneous.log_format_type = "media_server" # The log is in this format if any of the first ten lines match this regular expression ##Version: 1.0 ##Fields: date time cs-ip cs-method cs-uri sc-status sc-bytes time-taken cs(Referer) cs(User-Agent) cs(Cookie) #2012-04-27 12:05:17 12.34.56.78 GET /dir/file.xml 200 368 0 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0)" "-" log.format.autodetect_regular_expression = `^#Fields: date time cs-ip cs-method cs-uri sc-status sc-bytes time-taken cs[(]Referer[)] cs[(]User-Agent[)] cs[(]Cookie[)]` # This handles #Fields lines, and creates log and database fields from them log.filter_preprocessor = ` if (matches_regular_expression(current_log_line(), '^#Fields: +([^ ].*)$')) then ( string fields = $1; string fieldname; v.logfieldindex = 1; string numerical_fields = "profiles." . internal.profile_name . ".database.numerical_fields"; # This subroutine creates a database field subroutine(create_database_field(string fieldname, int top, int bottom), ( #echo("create_database_field: " . fieldname); # debug debug_message("create_database_field(" . fieldname . ")\n"); string databasefieldpath = "profiles." . internal.profile_name . ".database.fields." . fieldname; (databasefieldpath . "") = ""; node databasefield = databasefieldpath; if (top ne 0) then set_subnode_value(databasefield, "suppress_top", top); if (bottom ne 0) then set_subnode_value(databasefield, "suppress_bottom", bottom); databasefield; )); subroutine(create_log_field(string fieldname, string type, bool withindex), ( debug_message("create_log_field(" . fieldname . "; type=" . type . ")\n"); string logfieldpath = "profiles." . internal.profile_name . ".log.fields." . fieldname; (logfieldpath . "") = ""; node logfield = logfieldpath; if (withindex) then ( set_subnode_value(logfield, "index", v.logfieldindex); v.logfieldindex++; ); set_subnode_value(logfield, "subindex", 0); if (type ne '') then set_subnode_value(logfield, "type", type); logfield; )); # Extract the fields on at a time while (matches_regular_expression(fields, '^([^ ]+) (.*)$') or matches_regular_expression(fields, '^([^ ]+)$')) ( string unconverted_fieldname = $1; fields = $2; # Clean up the field name fieldname = ''; for (int i = 0; i < length(unconverted_fieldname); i++) ( string c = lowercase(substr(unconverted_fieldname, i, 1)); if (!matches_regular_expression(c, '^[a-z0-9]$')) then c = '_'; fieldname .= c; ); while (matches_regular_expression(fieldname, '^(.*)_$')) fieldname = $1; #echo("fieldname: " . fieldname); # Get the log field type string log_field_type = ''; if (fieldname eq 'cs_uri') then ( log_field_type = 'page'; ); else if (fieldname eq 'cs_user_agent') then ( log_field_type = 'agent'; ); else if (fieldname eq 'cs_ip') then ( log_field_type = 'host'; ); # Create the log field create_log_field(fieldname, log_field_type, true); # If we're creating a profile, create the database fields too. if (node_exists("volatile.creating_profile")) then ( # Start the if/else chain. if (false) then ( ); # Handle date by creating date_time and derived database fields else if (fieldname eq "date") then ( create_database_field('date_time', 0, 0); create_database_field('day_of_week', 0, 0); create_database_field('hour_of_day', 0, 0); ); # if date else if (fieldname eq "time") then ( create_database_field('date_time', 0, 0); create_database_field('day_of_week', 0, 0); create_database_field('hour_of_day', 0, 0); ); # if time # Create derived fields for agent else if (fieldname eq "cs_user_agent") then ( create_database_field('operating_system', 0, 0); create_database_field('web_browser', 0, 0); create_database_field('spider', 0, 0); ); # Create database field cs_ip and derived field for client IP else if (fieldname eq "cs_ip") then ( create_database_field('cs_ip', 0, 0); create_database_field('location', 0, 0); ); # Create derived fields from cs_uri else if (fieldname eq "cs_uri") then ( create_database_field('cs_uri', 0, 9); create_database_field('file_type', 0, 0); ); # Don't add a database field for numerical fields else if (subnode_exists(numerical_fields, fieldname)) then ( debug_message("Not adding numerical field: " . fieldname . "\n"); ); # Create a normal database field else create_database_field(fieldname, 0, 0); ); # if creating profile ); # while another field # Don't parse the #Fields line as a data line 'reject'; ); # if #Fields # Don't parse any other # lines as data lines else if (starts_with(current_log_line(), '#')) then ( 'reject'; ); ` # Get web browser, operating system, web browser, and spider information from the user-agent field. log.parsing_filters.derive_from_user_agent = { value = `get_user_agent_info(replace_all(cs_user_agent, '+', ' ')); web_browser = volatile.web_browser; operating_system = volatile.operating_system; spider = volatile.spider; ` requires_fields = { cs_user_agent = true } } # Log Filters log.filters = { mark_entry = { label = '$lang_admin.log_filters.mark_entry_label' comment = '$lang_admin.log_filters.mark_entry_comment' value = 'events = 1;' } # mark_entry } # log.filters database.numerical_fields = { events = { default = true requires_log_field = false entries_field = true } # events unique_client_ips = { label = "$lang_stats.field_labels.unique_client_ips" default = true requires_log_field = true log_field = "cs_ip" type = "unique" } # unique_client_ips sc_bytes = { default = true integer_bits = 64 display_format_type = "bandwidth" } time_taken = { label = "$lang_stats.field_labels.play_duration" integer_bits = 64 display_format_type = duration_milliseconds default = true } # time_taken average_time_taken = { label = "$lang_stats.field_labels.play_duration $lang_stats.field_labels.average_tag" integer_bits = 64 display_format_type = duration_milliseconds default = false log_field = "time_taken" requires_log_field = true type = "int" aggregation_method = "average" average_denominator_field = "events" } # average_time_taken } # database.numerical_fields create_profile_wizard_options = { # How the reports should be grouped in the report menu report_groups = { date_time_group = "" } # report_groups snapons = { # Attach a media_reports snapon media_reports = { snapon = "media_reports" name = "media_reports" label = "$lang_admin.snapons.media_reports.label" parameters = { user_field.parameter_value = "cs_ip" # have_category_field.parameter_value = false # category_field.parameter_value = "category" # domain_field.parameter_value = "top_level_domain" duration_field.parameter_value = "time_taken" stream_name_field.parameter_value = "cs_uri" client_ip_field.parameter_value = "cs_ip" # There is no stream ID in this log format have_stream_id_field.parameter_value = false # stream_id_field.parameter_value = "cs_uri" # Do the default concurrent connections analysis; it's based on a single duration field, which we have. attach_concurrent_events.parameter_value = true } # parameters requires_database_fields = { cs_ip = true time_taken = true cs_uri = true } # requires_database_fields } # media_reports } # snapons } # create_profile_wizard_options } # akamai_streaming