The standard reporting suite on the Knowledge Management Console covers the most important metrics -- Unique Users, Total Sessions, etc. However, you'll often want (or be asked) to provide additional reports based on the special needs of the customer and/or the particular tasks of the agent. This article won't cover all the details of configuring usage reports, but will hopefully demonstrate how to log a simple data point and have it show up on the console as a graph or table.
 
Before configuring usage, we should look briefly at how logging works. The agent's log is an object variable called SYS.Log -- anything written there is a candidate to show up in usage reports. This is completely separate from the User Profile: the agent may store the user's birthplace in a variable called G_USER.birthplace, but it won't show up in usage unless we also write it to, for example, SYS.Log.birthplace. It is also completely separate from the server component logs on the console.
 
So let's actually use birthplace as our example, and look at what we need to record and display that statistic.
 
Say we have a procedure called CollectBirthplaceFromUser() that takes care of collecting the user's birthplace and resolving it into a valid place name we can record.
 
procedure CollectBirthplaceFromUser()
  BIRTHPLACE = ""
  [...]
  call WriteBirthplaceToProfile(BIRTHPLACE)
  call LogBirthplace(BIRTHPLACE)
 
WriteBirthplaceToProfile assigns the value of BIRTHPLACE to G_USER.birthplace. LogBirthplace writes the same value to the SYS.Log.birthplace variable.
 
procedure LogBirthplace(BIRTHPLACE)
  SYS.Log.birthplace = BIRTHPLACE
 
Now that we're confident birthplaces are being collected and logged, let's move on to configuring Usage. We do this by editing a file at the root directory of the project, called usage_config.xml.
 
usage_config.xml controls the presentation of log data in the Usage Reports section of the console.  It's completely separate from the actual logging of data -- we can log something in the BuddyScript, for example, but not add the necessary sections in usage_config.xml for another month, at which point the data the agent has been logging for the last month will be displayed. However, the opposite is not true -- adding a section in usage_config.xml doesn't cause data to be collected.
 
There are two main parts: a "sections" element containing all the configuration options for the usage reports, and a "usagestats" element containing the variables and datapoints to be used in the sections element.
 
The sections element itself contains two subsections labeled "all_ids" and "individual_id", which correspond to views of usage statistics broken out by individual buddyid or all buddyid's combined, exposed as a drop-down list in the console. First we'll look at the all_ids section, which is somewhat simpler than the individual_id section.
 
The first section here is called Volume Summary, and contains a number of elements for reporting usage data. You can get a good idea of the syntax we'll be using later by examining this section.
 
 <section name="Volume Summary" id="volume_summary" shared-graph-type="barline" shared-graph-title="Usage">
  <element name="Total Queries" key="message_count" calc-type="normal" default-graph-state="on" graph-type="shared"/>
  <element name="Total Sessions" key="session_count" calc-type="normal" default-graph-state="on" graph-type="shared"/>
  <element name="Unique Users" key="unique_users" calc-type="normal" default-graph-state="off" graph-type="none"/>
  <element name="New Users" key="new_users" calc-type="normal" default-graph-state="off" graph-type="shared"/>
  <element name="Average Queries Per Session" key="message_count" calc-type="per" subkey="session_count" graph-type="shared"/>
  <element name="Average Sessions Per Unique User" key="session_count" calc-type="per" subkey="unique_users" graph-type="none"/>
  <element name="Average Session Length (in seconds)" key="total_session_length" calc-type="per" subkey="session_count" graph-type="shared"/>
 </section>
 
The "name" identifier is the text displayed on the console, the "key" is the datapoint, "calc-type" can be normal or something else depending on whether we want to perform some math on the number before displaying it, "subkey" is the other datapoint to use when calc-type is not normal, "default-graph-state" toggles whether a particular element shows up on the graph, "graph-type" controls what kind of graph, if any, to display the data on. In this case, multiple elements are sharing a "barline" graph -- a combination bar graph and line graph where the user selects which data goes on the bar, and which goes on the line.
 
We could add our own section for birthplace, but it turns out there is already a section for demographics, so we'll just add an element within that section:
 
  <element name="Birthplace Distribution" key='[birthplace][%]' keyName="Birthplace" valueName="Sessions" calc-type="distribution" graph-type="pie" display-type="percentage"/>     
 
This will pull all the values of SYS.Log.birthplace and display them in a pie graph, distributed by the number of sessions they occur in, along with a key. ("name", "keyName", and "valueName" are all labels and have no effect on the display of the data.) [%] represents a wildcard, meaning "all values of birthplace" -- we could choose instead to report on only [birthplace]['New York'], for example. 
 
Since there are potentially a large number of birthplaces (depending on how smart CollectBirthplaceFromUser is), it probably makes sense to dispense with the graph, and just display a table:
 
  <element name="Birthplace Distribution" key='[birthplace][%]' keyName="Birthplace" valueName="Sessions" calc-type="distribution" display-type="percentage"/>     
 
That's all we need to do for the all_ids section. For the individual_ids section, because we'll be filtering by buddyid, we need to go to the bottom of the file and add a datapoint:
 
        <var name="userBirthplace" default="">value('[birthplace]')</var>
  <datapoint buckets="+hour" key="sessions where userBirthplace=${userBirthplace};buddyid=${buddyid}">
    <filter>userBirthplace != ''</filter>
  </datapoint>
 
First we create a variable called userBirthplace, which is assigned the value of SYS.Log.birthplace. Then we create an hourly bucket for that data with a key for pulling the number of sessions within a particular buddyid where a particular birthplace was recorded. In the demographics section of the individual_id section, we'll add this:
 
  <element name="Birthplace Distribution" key='sessions where userBirthplace=%;buddyid=%var:buddyid%' keyName="Birthplace" valueName="Sessions" calc-type="distribution" display-type="percentage"/>     
 
This is similar to the element we created for the all_ids section, but birthplace (userBirthplace=%) and buddyid (buddyid=%var:buddyid%) are interpolated into their actual values, and we see only the number of sessions for a birthplace recorded for the buddyid currently selected. Now we can use the buddy dropdown on the console as a filter.
 
In practice, displaying a list of arbitrary names of places is not going to be very useful because there are many thousands of place names the user can enter. We'd probably want to constrain the list to countries, states, or other large areas, depending on the mission of the agent. Still, this example will hopefully get you started experimenting with Usage, which is the best way to learn. Chances are, usage_config.xml probably already contains most of the necessary pieces for whatever report you need to create.