Git Product home page Git Product logo

clog's Introduction

Introduction

Windows Linux

Within the tracing and telemetry space there are many API or library choices and it's very difficult (if not impossible) to choose correctly. There is a general need for the ability to emit structured, cross platform events in high performance code paths.

Exclusively using existing encoders and tooling (e.g. ETW on Windows, LTTng on Linux) CLOG provides:

  • Durable Identifiers for use in telemetry pipelines.
  • Manifested events and argugments with type safety.
  • Generates clear, human readable text for the final log format.
  • The ability to use existing tooling, such as like WPA.

Claims

CLOG makes these claims:

  1. Code and tool assets need to be decoupled from bit encoders to preserve the code/tools assets as bit encoders are modified (as would happen as code moves between OS's or projects) API abstractions not a sufficient solution to our problems, due to performance. Worse, API's tend to create permanent couplings between code and tools due to those couplings. Clog argues a tool (and not a library) best solves the range of problems we face.

  2. Event description (manifests), for purposes of tooling needs to be decoupled from description for human presentation (text files). For example the Windows Performance Analyzer (WPA) have different needs as compared to a human reading a log.

CLOG holds these claims by:

  • Using a printf-like syntax for event description:

    TraceLogWarning(
        DroppedPacket,
        "[conn][%p] DROP packet[%llu] Dst=%!ADDR! Src=%!ADDR! Reason=%s.",
        Connection,
        Packet->PacketNumber,
        CLOG_BYTEARRAY(sizeof(Datagram->LocalAddress), &Datagram->LocalAddress),
        CLOG_BYTEARRAY(sizeof(Datagram->RemoteAddress), &Datagram->RemoteAddress),
        Reason);
  • Selecting a bit encoder based on build time tool parameters, not API configuration. In this way we're not adding yet another API surface within any OS:

    {
      "MacroName": "TraceLogWarning",
      "EncodedPrefix": null,
      "EncodedArgNumber": 1,
      "CustomSettings": {
        "WPPArgNumber": "0",
        "ETWManifestFile": "Component.man",
        "ETW_Provider": "440d0192-e016-49e9-8f9a-639f5b275ab0"
      },
      "CLogExportModules": [
        "MANIFESTED_ETW",
        "TRACELOGGING",
        "DTRACE"
      ]
    }
  • Deferring the choice of event descriptions (manifest), for tooling. This maximizes utility of existing tooling (like WPA). The author chooses, at build time, how their events are manifested based on their needs โ€“ the decision can be reevaluated in the future without making changes to code or tools.

  • Requiring a "side car" (external manifest) for event presentation to a human readable format (e.g. [conn][%p] DROP packet[%I] Dst=%!IPADDR! Src=%!IPADDR! Reason=%s. )

Tools and Modules

Note the .exe extension is provided for clarity, clog.exe is cross platform and on Linux the .exe will not be present.

Work flow

  1. At build time, your source file will be read and processed using a config file. clog.exe produces .c and .h files that contains OS specific code.
  2. Using your favorite OS collection mechanism, collect traces using the appropriate tools.
  3. For debugging, convert your recorded traces into something human readable using one of the tools (e.g. clog2text_windows or clog2text_lttng).

Modules

  • clog.exe

    Build time tool to generate source code based on regex parsing of C/C++ code. This is the main tool for clog.

  • clog2text_lttng.exe

    LINUX ONLY : Combines CLOG events that are stored with LTTng into human readable text.

  • clog2text_windows.exe

    WINDOWS ONLY : Combines CLOG events that are stored with ETW into human readable text.

  • clogutils.dll

    Utility library used between clog.exe and other clog tools.

Supported Runtimes

The build .NET clog tools can be ran on .NET 6. In order to build, .NET 6 is required.

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

clog's People

Contributors

6293 avatar chgray avatar microsoft-github-operations[bot] avatar microsoftopensource avatar nibanks avatar thadhouse avatar thhous-msft avatar thomsontan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clog's Issues

Hexadecimal format is printed as decimal

It seems to me that despite specifying %x format, the resulting logs contain decimal value. This is especially confusing as the string contains 0x prefix:

[3][840b.8435][01:17:56.211381][strm][0x7ee0ec008c50] Setting flags 0x16 (existing flags: 0x0)

https://github.com/microsoft/msquic/blob/e855aa04835dd31d113bb444c5cb2eb9593c286c/src/core/send.c#L410-L415

https://github.com/microsoft/msquic/blob/e855aa04835dd31d113bb444c5cb2eb9593c286c/src/generated/linux/send.c.clog.h.lttng.h#L4C12-L27

Potentially related: #69

Process id and Thread id missing from decoded LTTng logs

The decoded logs currently look like the following:

[0][][04:09:46.599785][time][0x5623db075208] Updating Connection 0x7fd550000b20.
[0][][04:09:46.599786][time][0x5623db075208] Next Expiration = {1412964260, 0x7fd550000b20}.
[0][][04:09:46.599787][conn][0x7fd550000b20] Flush complete flags=0x0
[0][][04:09:46.599788][conn][0x7fd550000b20] Scheduling: 0

Notice the extra [] after the [0]. This should be removed.

SKIPPED:BUG:MISSINGARG in MsQuic Logs

I was just looking at a log generated from the MsQuic CI and I found this line (for an assert):

[0][][04:09:46.617630][ lib] ASSERT, 421:"/home/vsts/work/1/s/src/platform/platform_linux.c"<SKIPPED:BUG:MISSINGARG:arg4:ANSI_String>.

This maps to the following code:

void
QuicPlatformLogAssert(
    _In_z_ const char* File,
    _In_ int Line,
    _In_z_ const char* Expr
    )
{
    QuicTraceEvent(
        LibraryAssert,
        "[ lib] ASSERT, %u:%s - %s.",
        (uint32_t)Line,
        File,
        Expr);
}

That is triggered by this macro:

#define QUIC_FRE_ASSERT(exp) ((exp) ? (void)0 : (QuicPlatformLogAssert(__FILE__, __LINE__, #exp), quic_bugcheck()));

I don't know why clog would claim the arg is missing. I suspect a CLOG bug. The artifacts can be found here (for now): https://dev.azure.com/ms/msquic/_build/results?buildId=99107&view=artifacts&type=publishedArtifacts

Clog crashes if config file cannot be found

C:\Users\thhous\Documents\GitHub\msquic\src\bin\winkernel\resource.h
Unhandled exception. System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\thhous\Documents\GitHub\msquic\src\src\manifest\msquic.clog_config'.
   at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
   at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at System.IO.StreamReader.ValidateArgsAndOpenPath(String path, Encoding encoding, Int32 bufferSize)
   at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks)
   at System.IO.File.InternalReadAllText(String path, Encoding encoding)
   at System.IO.File.ReadAllText(String path)
   at clogutils.ConfigFile.CLogConfigurationFile.FromFile(String fileName) in /home/vsts/work/1/s/src/clogutils/ConfigFile/CLogConfigurationFile.cs:line 410
   at clog.clog.<>c.<Main>b__1_0(CommandLineArguments options) in /home/vsts/work/1/s/src/clog/clog.cs:line 103
   at CommandLine.ParserResultExtensions.MapResult[TSource,TResult](ParserResult`1 result, Func`2 parsedFunc, Func`2 notParsedFunc)
   at clog.clog.Main(String[] args) in /home/vsts/work/1/s/src/clog/clog.cs:line 85

Event Names Shouldn't have CLOG_ in Them

When looking through the code to collect msquic events created by clog, I noticed this:

lttng enable-event --userspace CLOG_*

I don't want CLOG in my event name. I should be able to choose a prefix (QUIC_ or MSQUIC_ for instance) and not be cluttered by CLOG.

Support PII Protection

It's quite common for data included in logs to be considered PII when deployed in production (e.g. Client IP addresses). It would be great if we could use CLOG to tackle this problem. To support this, I think we'd need the following changes to CLOG:

  • A way to annotate individual parameters as possible PII.
  • A way to configure a custom runtime PII "switch" that CLOG would use to trigger the PII or cleartext version of an event.
  • For events with PII parameters, CLOG generates a different event macro that checks the PII switch. If true the macro hashes (or something equivalent) the PII data before passing it down to the relevant trace module.

P.S. Is there such thing as a PII event independent of the parameters? I can't think of a case.

Remove VariableInfo from Sidecar

Warning: Contentious Issue Ahead

For every argument for an event, clog tracks the following:

 {
  "VariableInfo": {
  "UserSpecifiedUnModified": "\r\n            CLOG_BYTEARRAY(sizeof(Connection->PeerTransportParams.PreferredAddress), &Connection->PeerTransportParams.PreferredAddress)",
  "UserSuppliedTrimmed": "CLOG_BYTEARRAY(sizeof(Connection->PeerTransportParams.PreferredAddress), &Connection->PeerTransportParams.PreferredAddress)",
  "SuggestedTelemetryName": "arg3"
  },
  "DefinationEncoding": "!SOCKADDR!",
  "MacroVariableName": "arg3"
}

It does this (as I understand) to prevent any kind of change. I prefer that (and argue for) clog completely ignore the format of the parameters passed into the event. Allow the code to change this at will. This will help development burden and significantly reduce the overhead of the side car. For the event the above example was taken from, removing this would result in a 27% line count reduction.

Going even further, if you remove this as suggested, I believe it might be worth removing the splitArgs all together, as they don't seem to add anything that can't be easily calculated from the TraceString already.

FYI, the full event payload:

"PeerPreferredAddress": {
  "ModuleProperites": {},
  "TraceString": "[conn][%p] Peer configured preferred address %!SOCKADDR!",
  "UniqueId": "PeerPreferredAddress",
  "splitArgs": [
	{
	  "VariableInfo": {
		"UserSpecifiedUnModified": "\r\n            Connection",
		"UserSuppliedTrimmed": "Connection",
		"SuggestedTelemetryName": "arg1"
	  },
	  "DefinationEncoding": "p",
	  "MacroVariableName": "arg1"
	},
	{
	  "VariableInfo": {
		"UserSpecifiedUnModified": "\r\n            CLOG_BYTEARRAY(sizeof(Connection->PeerTransportParams.PreferredAddress), &Connection->PeerTransportParams.PreferredAddress)",
		"UserSuppliedTrimmed": "CLOG_BYTEARRAY(sizeof(Connection->PeerTransportParams.PreferredAddress), &Connection->PeerTransportParams.PreferredAddress)",
		"SuggestedTelemetryName": "arg3"
	  },
	  "DefinationEncoding": "!SOCKADDR!",
	  "MacroVariableName": "arg3"
	}
  ],
  "macro": {
	"MacroName": "QuicTraceLogConnInfo",
	"EncodedPrefix": "[conn][%p] ",
	"EncodedArgNumber": 2,
	"MacroConfiguration": {
	  "linux": "lttng_plus",
	  "stubs": "stubs",
	  "windows_kernel": "empty",
	  "windows": "empty"
	},
	"CustomSettings": null
  }
}

Remove Superfluous Quotes

From the latest (v0.1.6.0) logs, it looks like clog is going quote-happy:

  35 [1][][02:36:05.929076][test] START "QuicTestClientDisconnect"
  70 [1][][02:36:05.929215][test]---> "NewPingConnection"
  76 [1][][02:36:05.929309][test]<--- "NewPingConnection"
  79 [1][][02:36:05.929336][test]---> "SendPingBurst"
 100 [1][][02:36:05.929428][test]<--- "SendPingBurst"
 172 [1][][02:36:05.937024][test]---> "ConnectionAcceptAndIgnoreStream"
 173 [1][][02:36:05.937026][test]<--- "ConnectionAcceptAndIgnoreStream"
2822 [1][][02:36:05.963086][ lib] ERROR, 0, "EVP_DecryptFinal_ex failed".
2833 [1][][02:36:05.963136][test]---> "PingStreamShutdown"
2835 [1][][02:36:05.963140][test]<--- "PingStreamShutdown"
2840 [1][][02:36:05.963199][ lib] ASSERT, 421:"/home/vsts/work/1/s/src/platform/platform_linux.c"<SKIPPED:BUG:MISSINGARG:arg4:ANSI_String>.

Let's remove all those.

"macro" Should Not be Per-Event in the SideCar

Every single event in the sidecar duplicates the exact same macro payload. This is unnecessary and results in a significant bloat in the file. Practically, it looks like the simplest solution is to just embed the full config (including dependents) into the sidecar.

For example, in msquic, we have 12 different macro definitions right now; and those are duplicated 506 times in the sidecar. That's a 42x increase!

Azure Pipelines CI should Build Example Cross-Platform

Right now, there's a single stage to build clog and then the example, and it all runs on Ubuntu. Let's make building clog a separate stage (Ubuntu is still fine), it publish build artifacts for everything, and then we run the cmake builds in separate stages for each supported platform, ideally Ubuntu, Linux and macOS.

Embed defaults as resources in clog.dll

Rather then requiring defaults.clog_config, defaults.clog.cs and clog.h to be available in a users repo, instead these should be embedded resources in the dll.

For the config files, if nothing is specified from the command line, the embedded copies should be used. If an external file is passed in from the command like, a special path /EMBEDDEDRESOURCE/... would be used we want to load the specified file from an embedded resource.

For clog.h, I can think of 2 choices. One would be have a separate command line flag that would extract it into a specified directory. Running clog specifically to extract that file isn't a big issue, and could easily be done. The other option would be to always extract it to the same directory we generate the headers into, and do that every time. Theres some versioning advantages to that. A 3rd option is just just insert the contents of clog.h into each header. This would make it so you couldn't include 2 logging headers in the same TU, but I'm not sure if thats a problem.

Decoded Logs Should Include Provider Name

Right now, here's an example of the decoded logs:

[0][][04:09:46.599830][strm][0x5623db187ea0] SF:16 FC:83705 QS:456734 MAX:36394 UNA:18169 NXT:36394 RECOV:0-0
[0][][04:09:46.599831][strm][0x5623db187ea0]   unACKed: [18169, 36394]
[1][][04:09:46.599832][ udp][0x5623db0aede0] Recv 1252 bytes (segment=1252) Src=IPV4:16777343:48559 Dst=IPV4:16777343:32437
[0][][04:09:46.599833][67][84X][31] SH DestCid:"d9cf9e0323943186" KP:0 SB:0 (Payload 1227 bytes)
[1][][04:09:46.599833][conn][0x7fd550000b20] Queuing 1 UDP datagrams
[0][][04:09:46.599834][67][84X][31]   STREAM ID:2 Offset:35179 Len:1215
[1][][04:09:46.599834][conn][0x7fd550000b20] Scheduling: 1
[0][][04:09:46.599848][wrkr][0x5623db0751f8] IsActive = 1, Arg = 1

Currently, only MsQuic logs are being collected, but eventually we might collect multiple providers/filters of logs in parallel. In order to better differentiate providers, we should include the name in the event, such as:

[1][][04:09:46.599833][msquic][conn][0x7fd550000b20] Queuing 1 UDP datagrams

Standardize Versioning

I just updated a version of a dependency in #107 and I was looking at how to update the CLOG version, but I couldn't figure it out. How do we make a new version so that we can say all versions before that shouldn't be used?

Stub clog causes unused variable errors if the variables are only used in logs

inline
void
QuicTraceEventStubVarArgs(
    _In_ const void* Fmt,
    ...
    )
{
    UNREFERENCED_PARAMETER(Fmt);
}
#define QuicTraceEvent(Name, ...) QuicTraceEventStubVarArgs("", __VA_ARGS__)

In msquic, we use the following trick to make sure the compiler sees all logs as referenced, rather then just defining away the macro.

Dictionary KeyNotFound if macro configuration for platform does not exist

  Unhandled exception. System.Collections.Generic.KeyNotFoundException: The given key 'windows' was not present in the dictionary.
     at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
     at clogutils.CLogFileProcessor.ConvertFile(CLogConfigurationFile configFile, ICLogFullyDecodedLineCallbackInterface callbacks, String contents, String contentsFileName, Boolean conversionMode) in /home/vsts/work/1/s/clogutils/CLogFileProcessor.cs:line 310
     at clog.clog.<>c.<Main>b__1_0(CommandLineArguments options) in /home/vsts/work/1/s/clog/clog.cs:line 94
     at CommandLine.ParserResultExtensions.MapResult[TSource,TResult](ParserResult`1 result, Func`2 parsedFunc, Func`2 notParsedFunc)
     at clog.clog.Main(String[] args) in /home/vsts/work/1/s/clog/clog.cs:line 85

Caused by passing windows config profile with a source macro not having a windows key.

Add support for TRACEPOINT_PROBE_DYNAMIC_LINKAGE to lttng generated files.

By dynamically loading a tracepoint provider, we can solve the multiple linker errors we've been having to work around in msquic. To do this, in the generated headers, after declaring the tracepoint provider, add the following

#undef TRACEPOINT_PROBE_DYNAMIC_LINKAGE
#define TRACEPOINT_PROBE_DYNAMIC_LINKAGE

#ifdef BUILDING_TRACEPOINT_PROVIDER
#define TRACEPOINT_CREATE_PROBES
#else
#define TRACEPOINT_DEFINE
#endif

We would want this to be configurable for each target, as our executable targets we would be fine with a statically linked provider.

Missing NULL check in ETWOutputModule

Hi,
I point out the lack of some explicit NULL checks in the initialization method Init() of the ETWOutputModule.
I have the simple change ready but I don't have the possibility to publish a branch to proceed with the PR.

Not all output files are declared in cmake file

On linux, clog outputs 3 files.

file.clog.h
buildname.clog_file.clog.h.c
file.clog.h.lttng.h

The last file is not actually declared as an output in cmake. This causes the build to be ran incorrectly, as the dependencies are not tracked correctly.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.