Skip to content

Commit 3ed9796

Browse files
authored
Revamp documentation (#188)
* Refactor plugin creation to separate framework models * Add building-a-table docs * Link to docs overview from README * Fix header in Creating-a-table * Remove unused file * Fix typo * Update simple next steps * Consistent periods in list * Compatability typos fix * Update known-driver-compat overview * Address comments * Exposes typo
1 parent 94f415a commit 3ed9796

17 files changed

+857
-745
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ tabular data from arbitrary data sources such as Common Trace Format (`.ctf`) fi
1717
feature-rich data-processing pipeline
1818

1919
These two functionalities are not mutually exclusive, and plugins may access data in another plugin's (or, commonly, its own)
20-
data processing pipeline when creating tables for a given data source.
20+
data-processing pipeline when creating tables for a given data source.
2121

22-
For help with getting started and developing SDK plugins, refer to the [documentation folder](./documentation).
22+
For help with getting started and developing SDK plugins, refer to our [documentation](./documentation/Overview.md).
2323

2424
## In this Repository
2525
* `devel-template`: a work-in-progress .NET template for creating SDK plugins

documentation/Architecture/Overview.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
This document outlines the architecture of the Microsoft Performance Toolkit SDK.
44

5-
For more detailed information on how to create your own project using the SDK, please view [Creating an SDK Plugin C# Project](../Using-the-SDK/Creating-your-project.md).
5+
For more detailed information on how to create your own project using the SDK, please view [Creating an SDK Plugin](../Using-the-SDK/Creating-your-plugin.md).
66

77

88
## High-Level Interfaces
@@ -76,9 +76,9 @@ that work together to
7676
A plugin is an **abstract collection of these objects** which can be bundled together for distribution and loaded as a single
7777
unit by the SDK driver. *A plugin can be, and often is, made up of multiple assemblies*.
7878

79-
:warning: Note that while a single assembly *can* define more than one `ProcessingSource`, __it is highly recommended that an assembly only contains
80-
a single `ProcessingSource`.__ Tables, data cookers, and custom data processors are almost always associated with a single `ProcessingSource`.
81-
It is best therefore to package __only one__ `ProcessingSource` and all of its associated classes in a single binary.
79+
> :warning: Note that while a single assembly *can* define more than one `ProcessingSource`, __it is highly recommended that an assembly only contains
80+
> a single `ProcessingSource`.__ Tables, data cookers, and custom data processors are almost always associated with a single `ProcessingSource`.
81+
> It is best therefore to package __only one__ `ProcessingSource` and all of its associated classes in a single binary.
8282
8383
The diagram below demonstrates how these objects work together to acheive this high-level interface:
8484

@@ -98,9 +98,9 @@ The diagram below demonstrates how these objects work together to acheive this h
9898
For implementation details on how to create a simple plugin containing one `ProcessingSource`, its associated `CustomDataProcessor` and a
9999
`Table`, please view [Using the SDK/Creating A Simple SDK Plugin](../Using-the-SDK/Creating-a-simple-sdk-plugin.md).
100100

101-
For implementation details on how to create a plugin containing `DataCooker`s, please view [Using the SDK/Creating a Data Processing Pipeline](../Using-the-SDK/Creating-a-pipeline.md)
101+
For implementation details on how to create a plugin containing `DataCooker`s, please view [Using the SDK/Creating a Data-Processing Pipeline](../Using-the-SDK/Creating-a-pipeline.md)
102102

103103
# Next Steps
104104

105105
Now that we understand the high-level overview of the SDK architecture, the next step is to better understand how the data processing
106-
pipeline works. Continue reading at [Architecture/The Data Processing Pipeline](./The-Data-Processing-Pipeline.md).
106+
pipeline works. Continue reading at [Architecture/The Data-Processing Pipeline](./The-Data-Processing-Pipeline.md).

documentation/Architecture/The-Data-Processing-Pipeline.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# The Data Processing Pipeline
1+
# The Data-Processing Pipeline
22

33
Within a plugin, a `ProcessingSource` delegates the task of processing data sources to a `CustomDataProcessor`.
44
In order to minimize the overhead of accessing persistent data storage, a well-designed plugin aims to have its
@@ -10,11 +10,11 @@ if the SDK provided a way to
1010
4) Allow external binaries, such as other plugins, access to the output of these transformations (as in *extend* the plugin defining the transformation)
1111

1212
The SDK allows a plugin to achieve these goals, while minimizing the number of times data sources need to be directly accessed,
13-
by facilitating and allowing the creation of a __data processing pipeline__.
13+
by facilitating and allowing the creation of a __data-processing pipeline__.
1414

1515
# Pipeline Components
1616

17-
At the highest level, when a plugin wishes to create a data processing pipeline, it will define two types of
17+
At the highest level, when a plugin wishes to create a data-processing pipeline, it will define two types of
1818
components: __source parsers__ and __data cookers__.
1919

2020
## Source Parsers
@@ -106,7 +106,7 @@ the `CompositeDataCooker` can query the `DataOutput`s it needs to perform *its*
106106
# Putting Everything Together
107107

108108
By combining `SourceParser`s, `SourceDataCooker`s, and `CompositeDataCooker`s, a plugin can create arbitrarily
109-
complex and extensible data processing pipelines. For example, here is a pipeline a plugin may create to
109+
complex and extensible data-processing pipelines. For example, here is a pipeline a plugin may create to
110110
modularize and promote the extensibility of three tables:
111111

112112
<img src=".attachments/complex_pipeline.svg" width="100%">
@@ -128,5 +128,5 @@ and do whatever it wishes with it.
128128

129129
# Next Steps
130130

131-
Now that we understand at a high level how a data processing pipeline works, we can now begin creating our own
132-
SDK plugins. To get started, view [Using the SDK/Creating an SDK Plugin C# Project](../Using-the-SDK/Creating-your-project.md).
131+
Now that we understand at a high level how a data-processing pipeline works, we can now begin creating our own
132+
SDK plugins. To get started, view [Using the SDK/Creating an SDK Plugin](../Using-the-SDK/Creating-your-plugin.md).

documentation/Components.md

Lines changed: 0 additions & 128 deletions
This file was deleted.

documentation/Known-SDK-Driver-Compatibility/Overview.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Abstract
22
This folder contains, for known SDK drivers such as Windows Performance Analyzer, a mapping between SDK versions and all versions of the driver that can load plugins compiled against that SDK version.
33

4+
When creating an SDK plugin, refer to the compatibility lists for the programs that will load it. For example, when creating a plugin that will only be used with Windows Performance Analyzer, reference [its compatibility list](./WPA.md).
5+
46
# Known Drivers
57

68
The current compatibility lists being maintained are:

documentation/Overview.md

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,12 @@ The SDK is published as a NuGet package under the name [Microsoft.Performance.SD
2121
Since it is hosted on [NuGet.org](https://www.nuget.org/), it can be added to a `csproj` with no additional configuration by using
2222
the Visual Studio NuGet Package Manager, `dotnet.exe`, or `nuget.exe`.
2323

24-
# Creating Your First Plugin
24+
# Creating A Plugin
2525
Refer to [Creating your first plugin](Using-the-SDK/Creating-your-plugin.md)
2626

2727
# Recommended Reading Order
2828
To best understand how the SDK works and how to develop SDK plugins, it is recommended to read documentation in the following order:
2929
1) [Architecture/Overview](./Architecture/Overview.md) to understand at a high level the various systems the SDK provides
30-
2) [Architecture/The Data Processing Pipeline](./Architecture/The-Data-Processing-Pipeline.md) to understand how to systematically process data that
30+
2) [Architecture/The Data-Processing Pipeline](./Architecture/The-Data-Processing-Pipeline.md) to understand how to systematically process data that
3131
can be used by tables
32-
3) [Using the SDK/Creating an SDK Plugin C# Project](Using-the-SDK/Creating-your-project.md) to get your developer environment ready to create an SDK plugin
33-
4) [Using the SDK/Creating a Simple SDK Plugin](Using-the-SDK/Creating-a-simple-sdk-plugin.md) to see how to create a basic plugin that can
34-
take in a specific data source and output structured tables
35-
5) [Using the SDK/Creating a Data Processing Pipeline](Using-the-SDK/Creating-a-pipeline.md) to see how to create a data processing pipeline that
36-
exposes data that can be consumed by your tables and other plugins
37-
6) [Using the SDK/Creating an Extended Table](Using-the-SDK/Creating-an-extended-table.md) to see how to use data cookers to obtain the data to display
38-
inside of a table
32+
3) [Creating your first plugin](Using-the-SDK/Creating-your-plugin.md) to learn how to create an SDK plugin

documentation/Troubleshooting.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Troubleshooting
2+
3+
This document outlines steps for troubleshooting common issues that arise when developing SDK plugins.
4+
5+
* [WPA-Related Issues](#wpa-related-issues)
6+
* [WPA does not load my plugin](#wpa-does-not-load-my-plugin)
7+
8+
## WPA-Related Issues
9+
10+
### WPA does not load my plugin
11+
12+
There are many reasons this could happen. Here are some things to check:
13+
14+
* Check WPA's diagnostic console to see if there were any errors when loading your plugin. From within WPA, select `Window` -> `Diagnostic Console`
15+
* Ensure Visual Studio is correctly setup to load your plugin when debugging. Follow [these steps](./Using-the-SDK/Creating-your-plugin.md#setup-for-debugging-using-wpa)
16+
* Ensure your plugin builds successfully. In Visual Studio, select `Build` -> `Rebuild Solution`. Or, from a command prompt in your plugin's folder, run `dotnet build`
17+
* Ensure the `-addsearchdir` path in your debug profile created during [these steps](./Using-the-SDK/Creating-your-plugin.md#setup-for-debugging-using-wpa) is correct. Manually navigate to the folder used for `-addsearchdir` and verify your DLLs are there
18+
* If your `-addsearchdir` path contains spaces, ensure the path is surrounded by quotes (`"`)
19+
* Ensure the SDK version your plugin uses is [compatible with your version of WPA](./Known-SDK-Driver-Compatibility/WPA.md). To find your WPA version, select `Help` -> `About Windows Performance Analyzer`
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Custom Table Discovery
2+
3+
** Coming soon **
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Building a Table
2+
3+
Table construction happens by interacting with an instance of an `ITableBuilder`. Broadly, `Tables` consist of 3 parts: columns, which are composed of `ColumnConfigurations` and `Projections`, and `TableConfigurations`. An `ITableBuilder` has methods that accept all three of these objects.
4+
5+
* [Column](#column)
6+
* [ColumnConfiguration](#columnconfiguration)
7+
* [Projection](#projection)
8+
* [Combining ColumnConfiguration and Projections](#combining-columnconfiguration-and-projections)
9+
* [TableConfiguration](#tableconfiguration)
10+
* [ColumnRole](#columnrole)
11+
12+
## Column
13+
14+
A column is a conceptual (`ColumnConfiguration`, `Projection`) pair that defines data inside a [Table](#table).
15+
16+
### ColumnConfiguration
17+
18+
A `ColumnConfiguration` contains metadata information about a column. For example, it contains the column's name and description, along with `UIHints` that help GUI viewers know how to render the column.
19+
20+
Typically, `ColumnConfigurations` are stored as `static` fields on the `Table` class for the `Table` being built. For example,
21+
22+
```cs
23+
[Table]
24+
public sealed class WordTable
25+
{
26+
...
27+
28+
private static readonly ColumnConfiguration lineNumberColumn = new ColumnConfiguration(
29+
new ColumnMetadata(new Guid("75b5adfe-6eee-4b95-b530-94cc68789565"), "Line Number"),
30+
new UIHints
31+
{
32+
IsVisible = true,
33+
Width = 100,
34+
});
35+
36+
private static readonly ColumnConfiguration wordCountColumn = new ColumnConfiguration(
37+
new ColumnMetadata(new Guid("d1c800e5-2d19-4474-8dad-0ebc7caff3ab"), "Number of Words"),
38+
new UIHints
39+
{
40+
IsVisible = true,
41+
Width = 100,
42+
});
43+
}
44+
```
45+
46+
### Projection
47+
48+
A column's `Projection` is a function that maps a row index for a column to a piece of data. Projections are normally constructed at runtime by a `Build` method, since they depend on the data inside the final table. The SDK offers many helper methods for constructing `Projections`, such as
49+
* `Projection.Index(IReadOnlyList<T> data)`, which projects a column index `i` to `data[i]`
50+
* `Projection.Compose(this IProjection<T1, T2>, Func<T2, TResult>)` which composes one `IProjection` with another method
51+
52+
For example, suppose we have a collection of `LineItem` objects that each have two properties: `LineNumber` and `Words`. We can use the above helper methods to create the following projections:
53+
54+
```cs
55+
var baseProjection = Projection.Index(myLineItemCollection);
56+
57+
var lineNumberProjection = baseProjection.Compose(lineItem => lineItem.LineNumber);
58+
var wordCountProjection = baseProjection.Compose(lineItem => lineItem.Words.Count());
59+
```
60+
61+
## Combining ColumnConfiguration and Projections
62+
63+
If we have the `ColumnConfigurations` and `Projections` above, we can add them to the table we're building by calling `ITableBuilder.AddColumn`:
64+
65+
```cs
66+
tableBuilder.AddColumn(this.lineNumberColumn, lineNumberProjection);
67+
tableBuilder.AddColumn(this.wordCountColumn, wordCountProjection);
68+
```
69+
70+
Note that _every_ column a table provides must be added through a call to `ITableBuilder.AddColumn`, even if they're not used in a `TableConfiguration` (see below).
71+
72+
## TableConfiguration
73+
74+
Some tables may have _many_ columns available. In these situations, it is not useful for a user to be shown every single column at once. A `TableConfiguration` describes groupings of columns that should be used together, along with metadata information such as `ColumnRoles`. Every `Table` must provide at least one `TableConfiguration`.
75+
76+
For example, here is a `TableConfiguration` that contains both of columns above:
77+
78+
```cs
79+
var tableConfig = new TableConfiguration("All Data")
80+
{
81+
Columns = new[]
82+
{
83+
this.lineNumberColumn,
84+
this.wordCountColumn,
85+
},
86+
};
87+
```
88+
89+
You also specify [Special Columns](../Glossary.md##special-columns) in a `TableConfiguration`.
90+
91+
Once a `TableConfiguration` is created, it is added to the table we're building by calling `ITableBuilder.AddTableConfiguration`:
92+
93+
```cs
94+
tableBuilder.AddTableConfiguration(tableConfig);
95+
```
96+
97+
It is also recommended to set a default `TableConfiguration`:
98+
```cs
99+
tableBuilder.SetDefaultTableConfiguration(tableConfig);
100+
```
101+
102+
103+
### ColumnRole
104+
105+
A `ColumnRole` is metadata information about a column that defines the column's role in data presentation. For example, a column that contains a `Timestamp` whose value indicates when an event occured relative to the start of a `DataSource`](#datasource)` may be marked as a "start time" Column:
106+
107+
```cs
108+
tableConfig.AddColumnRole(ColumnRole.StartTime, relativeTimestampColumnConfiguration);
109+
```
110+
111+
# More Information
112+
There are many other things you can do with your `Tables`, such as adding `TableCommands` or configuring its default layout style. For more information, refer to the [Advanced Topics](./Advanced/Overview.md).

0 commit comments

Comments
 (0)