Skip to content

Instantly share code, notes, and snippets.

@winlinvip
Last active September 5, 2022 14:52
Show Gist options
  • Save winlinvip/298bcfbb59865c471a475b0550e49bb3 to your computer and use it in GitHub Desktop.
Save winlinvip/298bcfbb59865c471a475b0550e49bb3 to your computer and use it in GitHub Desktop.
Wireshark dissector for parsing Protobuf for APM over HTTP1
-- To apply this wireshark plugin:
-- mkdir -p ~/.local/lib/wireshark/plugins
-- ln -sf $(pwd)/otel.lua ~/.local/lib/wireshark/plugins/otel.lua
-- Download proto files for otel:
-- git clone https://github.com/open-telemetry/opentelemetry-proto.git
-- Setup Wireshark `Protobuf search paths` to load the proto files at `Preferences > Protocols > Protobuf`:
-- ~/git/opentelemetry-proto
-- ~/git/srs/trunk/research/proto
-- Start capture or parsing file.
do
function string_starts_with(str, start)
return str ~= nil and str:sub(1, #start) == start
end
-- See https://gitlab.com/wireshark/wireshark/-/wikis/Protobuf#write-your-own-protobuf-udp-or-tcp-dissectors
local protobuf_dissector = Dissector.get("protobuf")
-- Only parsing Protobuf over HTTP, with http uri.
local f_http_uri = Field.new("http.request.uri")
local otel_proto = Proto("otel_proto", "Extra analysis of the HTTP protocol");
function otel_proto.dissector(tvb, pinfo, tree)
local http_uri = f_http_uri()
if http_uri == nil then return end
-- See https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/collector/trace/v1/trace_service.proto
if string_starts_with(http_uri.value, "/v1/traces") then
pinfo.private["pb_msg_type"] = "message," .. "opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest"
pcall(Dissector.call, protobuf_dissector, tvb, pinfo, tree)
end
-- See https://cloud.tencent.com/document/api/614/16873
if string_starts_with(http_uri.value, "/structuredlog") then
pinfo.private["pb_msg_type"] = "message," .. "cls.LogGroupList"
pcall(Dissector.call, protobuf_dissector, tvb, pinfo, tree)
end
end
local tbl = DissectorTable.get("media_type")
tbl:add("application/x-protobuf", otel_proto)
print("Add application/x-protobuf dissector", otel_proto)
end
@winlinvip
Copy link
Author

winlinvip commented Sep 5, 2022

APM over HTTP1, please see otlptracehttp

To upload to APM:

ctx := context.Background()
endpoint := "ap-guangzhou.apm.tencentcs.com:55681" // Might be "4318" for new exporter.
token := "xxx" // From your service provider.

opts := []otlptracehttp.Option{
	otlptracehttp.WithEndpoint(endpoint),
	otlptracehttp.WithInsecure(),
}
exporter, err := otlptracehttp.New(ctx, opts...)
if err != nil {
	panic(err)
}

r, err := resource.New(ctx, []resource.Option{
resource.WithAttributes(attribute.KeyValue{
	Key: "token", Value: attribute.StringValue(token),
}),
resource.WithAttributes(attribute.KeyValue{
	Key: "service.name", Value: attribute.StringValue("srs-server"),
}),
}...)
if err != nil {
	panic(err)
}

tp := sdktrace.NewTracerProvider(
	sdktrace.WithSampler(sdktrace.AlwaysSample()),
	sdktrace.WithBatcher(traceExporter),
	sdktrace.WithResource(r),
)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
defer tp.Shutdown(ctx)

tracer := otel.Tracer("app")
ctx, span := tracer.Start(context.Background(), "main", trace.WithSpanKind(trace.SpanKindServer))
time.Sleep(100 * time.Millisecond)
defer span.End()

_, span2 := tracer.Start(ctx, "sub")
time.Sleep(70 * time.Millisecond)
span2.End()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment