narando / nest-xray

Distributed tracing for Nestjs with AWS X-Ray as the backend. Instrument incoming and outgoing HTTP requests
https://npmjs.com/package/@narando/nest-xray
MIT License
63 stars 21 forks source link

Issue importing HttpService #437

Open peisenmann opened 1 year ago

peisenmann commented 1 year ago

In the @next/axios code, they do a bunch of setup for the AXIOS_INSTANCE_TOKEN, but I don't see the same setup in the in the tracing module

Nest is throwing this error:

[Nest] 11754  - 02/02/2023, 10:15:02 PM   ERROR [ExceptionHandler] Nest can't resolve dependencies of the HttpService (?). Please make sure that the argument AXIOS_INSTANCE_TOKEN at index [0] is available in the HttpTracingModule context.

Potential solutions:
- If AXIOS_INSTANCE_TOKEN is a provider, is it part of the current HttpTracingModule?
- If AXIOS_INSTANCE_TOKEN is exported from a separate @Module, is that module imported within HttpTracingModule?
  @Module({
    imports: [ /* the Module containing AXIOS_INSTANCE_TOKEN */ ]
  })

Error: Nest can't resolve dependencies of the HttpService (?). Please make sure that the argument AXIOS_INSTANCE_TOKEN at index [0] is available in the HttpTracingModule context.

Potential solutions:
- If AXIOS_INSTANCE_TOKEN is a provider, is it part of the current HttpTracingModule?
- If AXIOS_INSTANCE_TOKEN is exported from a separate @Module, is that module imported within HttpTracingModule?
  @Module({
    imports: [ /* the Module containing AXIOS_INSTANCE_TOKEN */ ]
  })

Dependencies from package.json: "@narando/nest-xray": "^2.1.0", "@nestjs/axios": "0.1.0", "@nestjs/common": "^9.3.1", "@nestjs/config": "^2.3.0", "@nestjs/core": "^9.3.1", "@nestjs/event-emitter": "^1.4.1", "@nestjs/jwt": "^10.0.1", "@nestjs/passport": "^9.0.1", "@nestjs/platform-express": "^9.3.1", "@nestjs/platform-ws": "^9.3.1", "@nestjs/schedule": "^2.1.0", "@nestjs/websockets": "^9.3.1", "axios": "0.27.2",

peisenmann commented 1 year ago

I went ahead and did a patch-package to get me through. I would put in a PR, but I didn't test thoroughly enough yet.

index 63d8d9d..4be8c41 100644
--- a/node_modules/@narando/nest-xray/dist/clients/http/http-tracing.module.js
+++ b/node_modules/@narando/nest-xray/dist/clients/http/http-tracing.module.js
@@ -9,17 +9,30 @@ var HttpTracingModule_1;
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.HttpTracingModule = void 0;
 const axios_1 = require("@nestjs/axios");
+const axios_2 = __importDefault(require("axios"));
 const common_1 = require("@nestjs/common");
 const tracing_axios_interceptor_1 = require("./tracing.axios-interceptor");
 let HttpTracingModule = HttpTracingModule_1 = class HttpTracingModule {
+    static register(config) {
+        const httpModule = axios_1.HttpModule.register(options);
+        return Object.assign(Object.assign({}, httpModule), { module: HttpTracingModule_1 });
+    }
+
     static registerAsync(options) {
         const httpModule = axios_1.HttpModule.registerAsync(options);
         return Object.assign(Object.assign({}, httpModule), { module: HttpTracingModule_1 });
     }
 };
+
 HttpTracingModule = HttpTracingModule_1 = __decorate([
     (0, common_1.Module)({
-        providers: [axios_1.HttpService, tracing_axios_interceptor_1.TracingAxiosInterceptor],
+        providers: [
+            {
+                provide: "AXIOS_INSTANCE_TOKEN",
+                useValue: axios_2.default,
+            },
+            axios_1.HttpService, tracing_axios_interceptor_1.TracingAxiosInterceptor,
+        ],
         exports: [axios_1.HttpService],
     })
 ], HttpTracingModule);

This issue body was partially generated by patch-package.

peisenmann commented 1 year ago

Unfortunately, even after this, I wasn't able to get traces to actually show up in XRay, so I've moved to OpenTelemetry's libraries to see if I can make that work instead.

vahahavronsky commented 1 year ago

@peisenmann hey, how are things going with XRay? Please lemme know what is your solution to the whole xray in nest.js problem? Will be very grateful!

vhavronsky commented 1 year ago

I've managed to make this work by workaround:

    HttpTracingModule.registerAsync({ useFactory: () => ({}) }),
peisenmann commented 11 months ago

@peisenmann hey, how are things going with XRay? Please lemme know what is your solution to the whole xray in nest.js problem? Will be very grateful!

@vhavronsky Apologies that I missed this notification. Honestly and disappointingly, I was never able to get any form of telemetry working. I tried this package. I tried integrating OpenTelemetry. I believe I followed all the steps, and I was seeing telemetry logged to the console, but when I tried to get it to export to XRay, nothing I did seemed to help. At this point, I've rolled back all my attempts and abandoned the effort, relying on simple nginx timings in the access log and SQL timing via 3rd party DB integrated monitoring. I would love to revisit this in the future as it seems it should be a no-brainer with Nest's architecture, but I failed to get it working and had to move on.

vhavronsky commented 11 months ago

@peisenmann We've actually made XRay work just fine. You have to:

######################################################################################## ####################################### X - Ray ######################################## ########################################################################################

########################################################################################

X Ray Sampling rules

########################################################################################

TO DO

TO DO

TO DO

########################################################################################

IAM (ECS Task Role)

########################################################################################

resource "aws_iam_policy" "xray_policy" { name = "xray-policy"

policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = [ "xray:PutTraceSegments", "xray:PutTelemetryRecords", "xray:GetSamplingRules", "xray:GetSamplingTargets", "xray:GetSamplingStatisticSummaries", "xray:GetTraceGraph", "xray:GetTraceSummaries", ] Effect = "Allow" Resource = "*" }, ] }) }

resource "aws_iam_role" "ecs_xray_role" { name = "ecs-xray-role"

assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ecs-tasks.amazonaws.com" } } ] }) }

resource "aws_iam_role_policy_attachment" "xray" { policy_arn = aws_iam_policy.xray_policy.arn role = aws_iam_role.ecs_xray_role.name }

########################################################################################

IAM (ECS Task Execution Role)

########################################################################################

resource "aws_iam_policy" "xray_execution_role_policy" { name = "xray-execution-role-policy"

policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = [ "ecr:GetAuthorizationToken", "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage", "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", "logs:DescribeLogStreams", "ssm:GetParameters", "kms:GenerateDataKey", "kms:Encrypt", "kms:Decrypt", ] Effect = "Allow" Resource = "*" }, ] }) }

resource "aws_iam_role" "ecs_xray_execution_role" { name = "ecs-xray-execution-role"

assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ecs-tasks.amazonaws.com" } } ] }) }

resource "aws_iam_role_policy_attachment" "xray_execution" { policy_arn = aws_iam_policy.xray_execution_role_policy.arn role = aws_iam_role.ecs_xray_execution_role.name }

########################################################################################

ECS Task Definition

########################################################################################

resource "aws_ecs_task_definition" "xray" { task_role_arn = aws_iam_role.ecs_xray_role.arn execution_role_arn = aws_iam_role.ecs_xray_execution_role.arn family = "xray" network_mode = "host" container_definitions = jsonencode([ { name = "xray_daemon" image = "public.ecr.aws/xray/aws-xray-daemon:latest" cpu = 25 memoryReservation = 50 containerPort = 2000 protocol = "udp" portMappings = [ { "hostPort" : 2000, "containerPort" : 2000, "protocol" : "udp" } ],

  # # Uncomment to enable logging
  # logConfiguration = {
  #       logDriver =  "awslogs",
  #       options = {
  #           awslogs-group = "xray",
  #           awslogs-region = "eu-west-2",
  #           awslogs-create-group = "true"
  #       }
  #   },
},

]) }

########################################################################################

ECS Services

########################################################################################

resource "aws_ecs_service" "xray" { name = "xray" cluster = data.aws_ecs_cluster.octo.arn task_definition = aws_ecs_task_definition.xray.arn desired_count = "1" scheduling_strategy = "DAEMON" force_new_deployment = true }

resource "aws_ecs_service" "xray_admin" { name = "xray" cluster = data.aws_ecs_cluster.octo_admin.arn task_definition = aws_ecs_task_definition.xray.arn desired_count = "1" scheduling_strategy = "DAEMON" force_new_deployment = true }

peisenmann commented 10 months ago

@peisenmann We've actually made XRay work just fine. You have to:

* explicitly set the `AWS_XRAY_DAEMON_ADDRESS` to `172.17.0.1:2000`

* and set up the Daemon. We are using EC2 & ECS so we just had to add an XRay Daemon as a Cluster's Service. I believe here's a relevant Terraform code: ...

That's interesting. I'm using Elastic Beanstalk at the moment, though perhaps I could take the same Terraform approach. I don't know that I ever attempted setting the AWS_XRAY_DAEMON_ADDRESS, so perhaps with the Beanstalk built in Xray Daemon, that might simply work.

I'm heavily tasked on other products at the moment, but I'll try to get back to that one and test out this concept when I can. Thanks!

mohitphrasee commented 4 months ago
 HttpTracingModule.registerAsync({ useFactory: () => ({}) }),

Where should I add this line? I used TracingModule instead of axios client, but I'm getting errors as mentioned in the original issue above. Thanks