Open baywet opened 1 year ago
here is an example on how to do it in dotnet, exporting to zipkin, in a console application
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
.AddSource(serviceName)
.AddSource("Microsoft.Kiota.Http.HttpClientLibrary") // really important behavior is different than go/java
.AddSource("Microsoft.Kiota.Authentication.Azure") // really important behavior is different than go/java
.AddSource("Microsoft.Kiota.Abstractions") // really important behavior is different than go/java
.SetResourceBuilder(
ResourceBuilder.CreateDefault()
.AddService(serviceName: serviceName))
.AddConsoleExporter()
.AddZipkinExporter(o =>
{
o.Endpoint = new Uri("http://localhost:9411/api/v2/spans");
})
.Build();
using var myActivitySource = new ActivitySource("my-app");
using var activity = myActivitySource.StartActivity("main");
var tokenCredential = new DeviceCodeCredential(
clientId: "clientId",
tenantId: "tenantId",
deviceCodeCallback: (deviceCodeInfo, _) =>
{
Console.WriteLine(deviceCodeInfo.Message);
return Task.FromResult(0);
});
var authenticationProvider = new AzureIdentityAuthenticationProvider(tokenCredential, new string[] {"graph.microsoft.com"}, scopes: new string[] { "Mail.Read"});
var requestAdapter = new HttpClientRequestAdapter(authenticationProvider);
var apiClient = new ApiClient(requestAdapter);
// GET /users/jane@constoso.com/messages
var messagesResponse = await apiClient.Users["jane@constoso.com"].Messages.PostAsync(new Message {
Subject = "Hello world"
});
CC @philip-young @svrooij @tonipohl in the case of a graph client initialization you don't need all the ceremony for the authenticationProvider, the request adapter, etc... You can just new up the Graph client from the SDK where I new up the API client.
Here is the equivalent for Java
private static OpenTelemetry initializeOpenTelemetry(String ip, int port) {
String endpoint = String.format("http://%s:%s/api/v2/spans", ip, port);
ZipkinSpanExporter zipkinExporter = ZipkinSpanExporter.builder().setEndpoint(endpoint).build();
Resource serviceNameResource =
Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, "my-app"));
// Set to process the spans by the Zipkin Exporter
SdkTracerProvider tracerProvider =
SdkTracerProvider.builder()
.addSpanProcessor(SimpleSpanProcessor.create(zipkinExporter))
.setResource(Resource.getDefault().merge(serviceNameResource))
.build();
OpenTelemetrySdk openTelemetry =
OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).buildAndRegisterGlobal();
// add a shutdown hook to shut down the SDK
Runtime.getRuntime().addShutdownHook(new Thread(tracerProvider::close));
// return the configured instance so it can be used for instrumentation.
return openTelemetry;
}
public static void main(String[] args) throws Exception {
OpenTelemetry openTelemetry = initializeOpenTelemetry("127.0.0.1", 9411);
final TokenCredential tokenCredential = new DeviceCodeCredentialBuilder()
.clientId("clientid")
.tenantId("tenantId")
.challengeConsumer(deviceCodeInfo -> {
System.out.println(deviceCodeInfo.getMessage());
}).build();
final AzureIdentityAuthenticationProvider authProvider = new AzureIdentityAuthenticationProvider(tokenCredential, new String[] {"graph.microsoft.com"}, new String[] {"Mail.Read", "Mail.Send"});
final ApiClient client = new ApiClient(new OkHttpRequestAdapter(authProvider));
final Message result = client.users("jane@contoso.com").messages().post(new Message(){{
setSubject("Hello world");
}}).get();
System.out.println(result.getSubject());
}
Here is the equivalent for Go
var logger = log.New(os.Stderr, "zipkin-example", log.Ldate|log.Ltime|log.Llongfile)
func initTracer(url string) (func(context.Context) error, error) {
// Create Zipkin Exporter and install it as a global tracer.
//
// For demoing purposes, always sample. In a production application, you should
// configure the sampler to a trace.ParentBased(trace.TraceIDRatioBased) set at the desired
// ratio.
exporter, err := zipkin.New(
url,
zipkin.WithLogger(logger),
)
if err != nil {
return nil, err
}
batcher := sdktrace.NewBatchSpanProcessor(exporter)
tp := sdktrace.NewTracerProvider(
sdktrace.WithSpanProcessor(batcher),
sdktrace.WithResource(
resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String("zipkin-test"),
)),
)
otel.SetTracerProvider(tp)
return tp.Shutdown, nil
}
func main() {
url := flag.String("zipkin", "http://localhost:9411/api/v2/spans", "zipkin url")
flag.Parse()
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
shutdown, err := initTracer(*url)
if err != nil {
log.Fatal(err)
}
defer func() {
if err := shutdown(ctx); err != nil {
log.Fatal("failed to shutdown TracerProvider: %w", err)
}
tr := otel.GetTracerProvider().Tracer("kiota-http-go")
ctx, span := tr.Start(ctx, "main", trace.WithSpanKind(trace.SpanKindServer))
cred, err := azidentity.NewDeviceCodeCredential(&azidentity.DeviceCodeCredentialOptions{
TenantID: "tenantId",
ClientID: "clientId",
return
log.Fatal(err)
}
client := u.NewApiClient(adapter)
response, err := client.UsersById("jane@contoso.com").Messages().Get()
for _, message := range response.GetValue() {
fmt.Printf("Message: %v\n", *(message.GetSubject()))
}
span.End()
Here is the equivalent for TypeScript
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);
const resource =
Resource.default().merge(
new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: "service-name-here",
[SemanticResourceAttributes.SERVICE_VERSION]: "0.1.0",
})
);
const provider = new NodeTracerProvider({
resource: resource,
});
const exporter = new ZipkinExporter({
});
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
provider.register();
await trace.getTracer(
'service-name-here'
).startActiveSpan('my-span', async (span) => {
const cred = new DeviceCodeCredential({
tenantId: "tenantId",
clientId: "clientId",
userPromptCallback: (deviceCodeInfo) => {
// eslint-disable-next-line no-console
console.log(deviceCodeInfo.message);
},
});
const authProvider = new AzureIdentityAuthenticationProvider(cred, ["Mail.Read"]);
const requestAdapter = new FetchRequestAdapter(authProvider);
const client = new ApiClient(requestAdapter);
const result = await client.usersById("jane@contoso.com").messages.get();
for (const message of result?.value!) {
Logger.logTask(`${message.subject}`);
}
span.end();
});
exporter.shutdown();
@baywet I assume these will land as snippets in the docs directly, right? Just using this one as a reminder?
@sebastienlevert yeah I've been salvaging my stashes here for now in case something happens to them. @ndiritu has had a customer issue for Java asking about that information and he volunteered to write the documentation page. I'm hoping those will help fast track things.
The use of Open Telemetry for Kiota clients is currently undocumented. We regularly get questions about observability and showing for each language how you can export traces to the console or to a service would be helpful. Originally created by @baywet at https://github.com/microsoftdocs/openapi-docs-pr/issues/21