Skip to main content

AppScope sees a copy of all the application data coming in and out of the wire, in clear text. AppScope has basic protocol support to understand if a flow is HTTP data, and it understands enough of the protocol (in HTTP 1.1 only, today) to emit events about HTTP activity. AppScope understands HTTP status codes and endpoints, and it allows for custom header extractions.

AppScope can do this because it runs in userland, inside the application. It interposes itself not just between the application and system calls, but also between the application and TLS libraries. In Java, we insert some byte code instrumentation to interpose TLS inside the JVM. We interpose between most TLS implementations, like OpenSSL and GnuTLS.

Let's see it in action. We have nginx running locally, you might remember. Let's scope the popular http utilty curl.

important

Scoping curls

  1. In Terminal 1, run:
    scope curl -so /dev/null http://localhost/
    scope events

From the results, we can see curl doing a lot of things, including opening openssl configs, /etc/hosts, and more. We can see a network connection to localhost on port 80, and most importantly we can see an HTTP request and response event. Let's see the HTTP response in more detail.

important

HTTP Event Details

  1. In Terminal 1, run:
    scope events $(scope events -s http.resp -j | jq -r .Id | head -1)

AppScope exposes a ton of information here. HTTP Version, Host, Method, Content Length, Endpoint, User Agent, Source & Destination IPs & Ports, and Duration. With this basic information, we can understand a lot about an application's performance. Response time by endpoint. Error rates by host. In agent deployments, environment variables can help expand the dimensionality of this data, helping expose application information by service, tag, or other metadata.

Many approaches can do this with HTTP in clear text. What if it's encrypted on the wire? We can do that too.

important

HTTP Event Details

  1. In Terminal 1, run:
    scope curl -kso /dev/null https://localhost/
    scope events $(scope events -s http.resp -j | jq -r .Id | head -1)

Now we see the same event details, but this time notably http.scheme is https. Next, let's prove that this works on some Internet site we don't own and works with a different command. Let's use a different common HTTP utility, wget, instead and request a page over the Internet. Donn, our lead engineer, likes to demo with wttr.in, which returns your local weather. We're based in San Francisco, so let's get our local weather:

important

HTTP Event Details

  1. In Terminal 1, run:
    scope run -p -- wget -q -O /dev/null https://wttr.in/94105
    scope events $(scope events -s http.resp -j | jq -r .Id | head -1)

Now we see that our http.user_agent and proc have changed, and we're still https scheme with a new http.target. Since we ran scope with payloads on, let's see what came through the wire.

important

HTTP Event Payloads

  1. In Terminal 1, to see the request, run:
    scope flows $(scope flows | tail -n 1 | awk '{ print $1 }') --out
  2. To see the response, still in Terminal 1, run:
    scope flows $(scope flows | tail -n 1 | awk '{ print $1 }') --in

Pretty cool! We can easily grab payload data from any unmodified binary. This also works with statically linked languages, including Go. We've included a simple Go HTTPS Client in this sandbox.

important

Static Binaries

  1. In Terminal 1, to see the source code for our HTTP client:
    bat https.go
  2. To run the compiled binary and see the payload:
    scope run -p -- ./goHttps >/dev/null
    scope flows $(scope flows | tail -n 1 | awk '{ print $1 }') --in

Lastly, AppScope is designed to work with everything. We've included HTTPS clients in Java, Python, Perl, Go, and also curl and wget. scope will see HTTP events from all of them.

important

Works with Everything

  1. In Terminal 1, to see what HTTP clients we're running, execute:
    bat https.sh
  2. Still in Terminal 1, run all the HTTPS clients:
    scope ./https.sh
    scope events -t http

Next Steps

With HTTP-level visibility, we can see into our applications and understand what they're doing in terms of accepting and making HTTP requests. No need for proxies or new SDKs or modifying your runtime configurations. Simply prepend scope and you'll immediately see HTTP-level data.

Next, we'll walk through some capabilities of visualizing data in the scope CLI.