Automating Quota Usage Reports in SharePoint 2007
Posted on Tuesday, 14 September 2010 19:38Setting up a Site Collection quota in SharePoint 2007 is a straight forward task, but how do you represent the remaining space back to the users?
For our specific example, we've set a site collection quota of 4gig and need a way to reflect this back to the site collection administrator. There is nowhere in the Site Collection admin for viewing the remaining space, and often you won't know until you get a warning from SharePoint.
What I'll show you is how to automatically collate the remaining space for the site collection by creating a small command line application to sit on a SharePoint front end.
There is an STSADM command called enumsites. You can get all the size data by running this command and getting an XML document back. Try it like this:
STSADM.EXE -o enumsites -url http://mySharePointSite
Alternatively, you can dump the results to file like this:
STSADM.EXE -o enumsites -url http://mySharePointSite > siteinfo.xml
This will give you an idea of the data being returned, namely:
- Url - Site Collection URL
- Owner - Site Collection Owner
- SecondaryOwner - Secondary Site Collection Owner
- ContentDatabase - The Content Database used by the Site Collection
- StorageUsedMB - The amount of physical space used in Megabytes
- StorageWarningMB - The point at which warnings about the quota are generated
- StorageMaxMB - The Site Collections size limit
SecondaryOwner is an only returned if set, so allow for this in your code.
The really handy thing is that the data is returned in xml format. From here you have three main approaches you can chose, although I'll only cover one:
- Dump the results to an xml file and read that in through a webpart.
- Run the report "on demand" through a custom webpart.
- Run the report as a scheduled task and save the results to a SharePoint list.
- Run the report as a scheduled task and save the results to an SQL database.
Because it's that much easier to manage and setup, we'll save our usage report to the database, keeping only the most recent set of data.
Set up the database table
To set up the table execute the following SQL script:
CREATE TABLE [dbo].[stats_site_usage]([url] [varchar](500) COLLATE Latin1_General_CI_AS NOT NULL,[owner] [varchar](50) COLLATE Latin1_General_CI_AS NOT NULL,[contentdb] [varchar](100) COLLATE Latin1_General_CI_AS NOT NULL,[storageused] [varchar](50) COLLATE Latin1_General_CI_AS NOT NULL,[storagewarning] [varchar](50) COLLATE Latin1_General_CI_AS NOT NULL,[storagemax] [varchar](50) COLLATE Latin1_General_CI_AS NOT NULL,[lastupdate] [datetime] NOT NULL CONSTRAINT [DF_stats_site_usage_lastupdate] DEFAULT (getdate())) ON [PRIMARY]
I've decided to excluded secondary owner because I'm not at all interested in having that information, but if you want it then modify the structure accordingly.
Writing The Command Line Application
First, we'll gather the raw XML data.
XmlDocument siteDataFeed = new XmlDocument();string functionCall = " -o enumsites -url http://mySharePointSite";string s = string.Empty;try{Process p = new Process();p.StartInfo.FileName = @"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\stsadm.exe";p.StartInfo.Arguments = functionCall;p.StartInfo.UseShellExecute = false;p.StartInfo.CreateNoWindow = true;p.StartInfo.RedirectStandardError = true;p.StartInfo.RedirectStandardOutput = true;p.Start();StreamReader pOutput = p.StandardOutput;s = pOutput.ReadToEnd();if (!p.HasExited){p.Kill();}pOutput.Close();p.Close();}catch (Exception ex){Console.WriteLine(ex.Message);}
Here, we execute STSADM command within our console application, an save the output to a string. The next job is to parse the results from the xml data and store them data in the database.
if (!string.IsNullOrEmpty(s)){//Truncate Tableusing (SqlConnection conn = new SqlConnection(@"server=SQL1\SQL1;Initial Catalog=my_DB;Persist Security Info=True;User ID=username;Password=password")){SqlCommand cmd = new SqlCommand("TRUNCATE TABLE stats_site_usage", conn);conn.Open();cmd.ExecuteReader();cmd.Dispose();}XmlDocument xmlDoc = new XmlDocument();xmlDoc.LoadXml(s);siteDataFeed = xmlDoc;foreach (XmlNode status in siteDataFeed.DocumentElement){string url = string.Empty;string owner = string.Empty;string contentDatabase = string.Empty;string storageUsed = string.Empty;string storageWarning = string.Empty;string storageMax = string.Empty;url = status.Attributes["Url"].InnerText;owner = status.Attributes["Owner"].InnerText;contentDatabase = status.Attributes["ContentDatabase"].InnerText;storageUsed = status.Attributes["StorageUsedMB"].InnerText;storageWarning = status.Attributes["StorageWarningMB"].InnerText;storageMax = status.Attributes["StorageMaxMB"].InnerText;using (SqlConnection conn = new SqlConnection(@"server=SQL1\SQL1;Initial Catalog=my_DB;Persist Security Info=True;User ID=username;Password=password")){SqlCommand cmd = new SqlCommand("INSERT INTO stats_site_usage (url, owner, contentdb, storageused, storagewarning, storagemax) VALUES (" +"'" + url.Replace("'", "''") + "', " +"'" + owner.Replace("'", "''") + "', " +"'" + contentDatabase + "', " +"'" + storageUsed + "', " +"'" + storageWarning + "', " +"'" + storageMax + "')", conn);conn.Open();cmd.ExecuteReader();cmd.Dispose();}}}
Before parsing the XML we truncate the table to clear out the previous results. Run this now, and see what happens. Once the application has completed, check your database table and it should be full of rows of usage data.
Next Steps
Now you've done this once, you can set up a scheduled task to run it daily, or even hourly as we have. The question now is what do you do with the data. We haven't implemented the data on our portal yet but what I will probably do is take the value of SPContext.Current.Site.RootWeb and match that against the database to get the contextual Site Collection usage. You can then compare the storageMax value to the storageUsed value, and express the result in a number of ways. There are various .net or CSS / Javascript based reporting solutions, you could even use my canvas example, though if you look around the web, technology has moved on since then and you can do something really snazzy with modern techniques.