X-CostGraph-<key>
headers your services send and attribute each request’s bytes to their values. A Mac
reports the same attribution_<key> tags as a Linux host. Each request is attributed
to the process that sent it. The feature is off by default.
Header names become tag keys by the same rules on every host. See
How header names become keys.
Decide whether you need this
Most Macs do not need request header attribution. The agent already reports each Mac’s network flows without any setup: the destination, the bytes in each direction, and the process that opened the connection. For Linux hosts and Kubernetes, header attribution works with no proxy. Turn this feature on only when services that run on the Mac sendX-CostGraph-*
headers and you need their bytes split by those values. It has a cost:
- HTTPS requests are intercepted, so clients must trust the agent’s CA.
- Programs that pin certificates fail through the proxy.
- Go programs and other clients that verify through the keychain fail until the CA is in the keychain.
- Only requests that go through the proxy are attributed.
How it works
A Linux host reads headers with eBPF. A Mac uses the attribution proxy, a local forwarding proxy that the agent runs on a loopback port. Requests that clients send through the proxy are attributed. Requests that do not use it are not. For an HTTPS request, the proxy terminates TLS with a certificate authority (CA) that the agent creates on the Mac. It then opens its own TLS connection to the destination. The client must trust that CA, as described in Trust the CA. The proxy keeps only the values ofX-CostGraph-* request headers. It does not keep or
send any other header, path, query string, or body. The CA private key stays on the
Mac. The agent matches each request to the process that opened the connection.
Requests to Apple services and certificate authorities, such as apple.com,
icloud.com, and letsencrypt.org, pass through the proxy without interception.
Requirements
- The agent is installed on the Mac with Homebrew and registers with CostGraph. See the macOS tab in Installation.
metrics_onlyis nottrue. Attribution needs a registered agent.- Network flow tracing is on.
network_tracedefaults totruein the configuration file. - Clients send their requests through the proxy and trust its CA.
- For HTTPS, clients offer application-layer protocol negotiation (ALPN) in their TLS handshake. curl and browsers do.
Enable attribution
Add anhttp_attribution block to the agent configuration file at
$(brew --prefix)/etc/costgraph_agent/config.yaml. The following example listens on a
fixed port. The agent exports the CA files that clients read to
/usr/local/share/costgraph/ unless you set other paths.
enabled: true is combined with metrics_only: true.
It also refuses a CA path that is not absolute, and an upstream other than auto,
none, or a host:port.
boolean
default:"false"
Turns attribution on. When you set it back to
false, the agent removes its CA, the
exported CA files, and any keychain trust it added. It also restores the system proxy.number
default:"0"
Loopback port the proxy listens on at
127.0.0.1. 0 picks a free port each time the
agent starts. Set a fixed port when you configure clients to use the proxy yourself.boolean
default:"false"
Points the Mac’s web and secure web proxy settings at the attribution proxy. See
Use the system proxy.
string
default:"auto"
Where the proxy sends requests.
auto forwards through the web proxy the Mac already
has configured, or connects directly when there is none. none connects directly.
A host:port value forwards through that HTTP proxy. An upstream proxy that also
intercepts TLS breaks HTTPS through the attribution proxy.boolean
default:"false"
Adds the agent’s CA to the System keychain. See Trust the CA.
string
Absolute path where the agent writes the public CA certificate. The file is readable
by every user. Defaults to
/usr/local/share/costgraph/attribution-ca.pem.string
Absolute path where the agent writes the macOS system root certificates followed by
the agent’s CA. The file is readable by every user. Defaults to
/usr/local/share/costgraph/attribution-bundle.pem.Point clients at the proxy
A client uses the proxy when its own proxy setting names it. Many clients read theHTTPS_PROXY and HTTP_PROXY environment variables.
Use the system proxy
Withsystem_proxy: true, the agent sets the web and secure web proxy of the Mac’s
active network service to the attribution proxy after the proxy is healthy. Clients that
follow the macOS proxy settings then use it without further configuration.
The agent records the previous settings and restores them exactly when it stops, when
the proxy goes down, and after a crash. Restoring also clears a proxy host and port that
the agent set. If the proxy keeps failing, the agent restarts it with a growing delay
and then retries every five minutes. The system proxy stays restored until the proxy is
healthy again.
The agent does not apply the system proxy in these cases:
- The network service uses an automatic proxy configuration (PAC) file.
- The network service already uses a different proxy and
upstreamisnone. Withauto, the existing proxy becomes the upstream instead.
Trust the CA
The CA matters only for HTTPS. Requests over plain HTTP are not intercepted, so they are attributed with no CA at all. For HTTPS, a client that does not trust the CA fails with a certificate error. macOS does not let the agent trust its CA by itself, because an administrator trust change needs interactive approval. Give clients the CA in one of these ways:- Point clients at the exported files (
ca_cert_pathandca_bundle_path, by default under/usr/local/share/costgraph/). This works for clients that read a certificate file. - Set
trust_system_keychain: trueonly on a Mac where the trust change can be approved, such as one managed by mobile device management (MDM). If macOS refuses the change, attribution stays off. - Deliver the certificate from
ca_cert_pathto the System keychain with your MDM. Clients that verify through the keychain need this.
/etc/ssl/cert.pem are
missing or empty, the agent does not write the bundle and attribution stays off.
Set the variable each client reads.
The first three variables replace the client’s default list. The bundle includes the
system roots, so the client still verifies servers that the proxy does not intercept.
Client support
The following results were measured through the attribution proxy.
Go programs on macOS ignore
SSL_CERT_FILE and verify through the keychain. Keep Go
tools off the proxy on a Mac where the keychain does not trust the CA. Python 3.13 and later verify
certificates strictly, and the agent’s CA meets those checks.
Verify attribution
Check that the proxy is up. The agent serves its local metrics on port 9101.1 means the proxy is up. Then send a tagged request through the proxy.
200. The proxy counts the request in
costgraph_attribution_proxy_records_total{outcome="received"} on the same local
endpoint.
Read the metrics
The agent ships two request series to CostGraph. They are not served on the local/metrics endpoint.
Each sample holds the bytes counted since the previous collection. Both series carry
these labels:
attribution_<key>for eachX-CostGraph-<key>header on the requestserver_address, the host the request was sent tonameandeffective_name, the process that sent the requestsrc_ip,dst_ip, anddst_portof the outbound connection
The
reason label on dropped requests has three values:
unownedmeans no process was found for the request. It is published withoutname.cap-exceededmeans a limit was reached. See Limits.malformedmeans the request record was invalid and was dropped.
Limits
- 8 tag keys per request and 256 bytes per value, as on Linux.
- 64 server addresses per process. Requests to further hosts are published without
server_address. - 256 distinct tag sets per process in each collection. Requests with further tag sets are published without tags.
- Interception covers only clients that offer ALPN. Other HTTPS clients pass through unattributed.
- Clients that do not send requests through the proxy are not attributed.
- Tart virtual machine guests on the Mac are not covered.
Troubleshoot attribution
When attribution cannot start, the agent keeps running without it and logs a line that starts withhttp attribution is off, followed by the reason. Read it in
$(brew --prefix)/var/log/costgraph_agent.log or
$(brew --prefix)/var/log/costgraph_agent.error.log.
With
network_trace: false, the agent instead logs that HTTP attribution needs network
trace and stays off. Set network_trace to true.
The following problems appear in the client rather than in the agent log.