Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to extract query's metadata for tracing? #404

Open
bangbaew opened this issue Oct 10, 2023 · 0 comments
Open

Is it possible to extract query's metadata for tracing? #404

bangbaew opened this issue Oct 10, 2023 · 0 comments

Comments

@bangbaew
Copy link

bangbaew commented Oct 10, 2023

in Prisma Client Go, i'm able to do this

func ExecuteWithTracing[T any](ctx context.Context, query builder.Query) (*T, error) {

	ctx, span := tracer.Start(ctx, "Execute Query", trace.WithSpanKind(trace.SpanKindClient))
	defer span.End()

	span.SetAttributes(attribute.Key("query.method").String(query.Method))
	span.SetAttributes(attribute.Key("query.model").String(query.Model))
	span.SetAttributes(attribute.Key("query.name").String(query.Name))
	span.SetAttributes(attribute.Key("query.operation").String(query.Operation))
	span.SetAttributes(attribute.Key("query.build").String(query.Build()))
	span.SetAttributes(attribute.Key("query.build.inner").String(query.BuildInner()))
	span.SetAttributes(attribute.Key("query.engine.name").String(query.Engine.Name()))
	span.SetAttributes(attribute.Key("peer.service").String(dbHost))

	var result *T

	err := query.Exec(ctx, &result)
	if err != nil {
		span.SetStatus(codes.Error, err.Error())
		return nil, err
	}

	span.SetStatus(codes.Ok, "")

	b, _ := json.Marshal(&result)
	if b != nil {
		span.SetAttributes(attribute.Key("query.result").String(string(b)))
	}

	return result, nil
}

and call something like

func (dc *DishCuisineQueryParams) delete(ctx context.Context) (*db.DishCuisineModel, error) {
	q := prisma.Client.DishCuisine.FindUnique(
		db.DishCuisine.DishIDCuisineID(
			db.DishCuisine.DishID.Equals(dc.DishID),
			db.DishCuisine.CuisineID.Equals(dc.CuisineID),
		),
	).Delete()

	result, err := prisma.ExecuteWithTracing[db.DishCuisineModel](ctx, q.ExtractQuery())
	if err != nil {
		return nil, err
	}
	return result, nil
}

to achieve this tracing result:
image

I would like to do the same in Prisma Client Rust, I'm currently passing a generic Future that returns prisma result like this, so I could not get anything but .await

pub async fn execute_with_tracing<T, F>(prisma_exec_fn: F) -> Result<T, ErrorResponse>
where
    T: serde::Serialize,
    F: std::future::Future<Output = prisma_client_rust::Result<T>>,
{
    let span = PRISMA_TRACER
        .span_builder("Execute Query")
        .with_kind(SpanKind::Client)
        .with_attributes(vec![
            Key::from_static_str("peer.service").string(DATABASE_HOST.to_owned())
        ])
        .start(&*PRISMA_TRACER);

    let cx = Context::current_with_span(span);
    let result = prisma_exec_fn.with_context(cx.to_owned()).await;

    match result.as_ref() {
        Ok(v) => {
            cx.span().set_status(Status::Ok);

            match prisma_client_rust::serde_json::ser::to_string(&v) {
                Ok(str) => cx.span().add_event(
                    "Success Execution".to_string(),
                    vec![Key::new("query.result").string(str)],
                ),
                Err(e) => cx.span().add_event(
                    "Failed Serialization".to_string(),
                    vec![Key::new("error.message").string(e.to_string())],
                ),
            }
        }
        Err(e) => {
            cx.span().set_status(Status::Error {
                description: e.to_string().into(),
            });

            return Err(handle_prisma_error(e));
        }
    };

    Ok(result.unwrap())
}

and call

async fn delete_chant(
    client: Data<PrismaClient>,
    id: Path<String>,
) -> Result<impl Responder, ErrorResponse> {
    let exec = client
        .chant()
        .delete(chant::id::equals(id.to_owned()))
        .exec();

    let deleted = execute_with_tracing(exec).await?;
    Ok(Json(deleted))
}

I would like to know if I can get query string, query method, operation, model name, crate version, as well as database name and database username or other tracing information from Prisma Client Rust, it would be great if someone could suggest me a better way to implement this function, like actix-web-opentelemetry crate which adds .trace_request() function to actix web client, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant