| 132 | } |
| 133 | |
| 134 | func classifyError(err error) string { |
| 135 | var upstreamErr *upstream.Error |
| 136 | if errors.As(err, &upstreamErr) { |
| 137 | switch upstreamErr.Kind { |
| 138 | case upstream.KindTimeout: |
| 139 | return fallback.TriggerTimeout |
| 140 | case upstream.KindBackendUnhealthy: |
| 141 | return fallback.TriggerBackendUnhealthy |
| 142 | case upstream.KindUpstream4xx: |
| 143 | return fallback.TriggerUpstream4xx |
| 144 | case upstream.KindUpstream5xx: |
| 145 | return fallback.TriggerUpstream5xx |
| 146 | default: |
| 147 | return fallback.TriggerBackendError |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | if errors.Is(err, context.DeadlineExceeded) { |
| 152 | return fallback.TriggerTimeout |
| 153 | } |
| 154 | msg := strings.ToLower(err.Error()) |
| 155 | if strings.Contains(msg, "unhealthy") { |
| 156 | return fallback.TriggerBackendUnhealthy |
| 157 | } |
| 158 | return fallback.TriggerBackendError |
| 159 | } |
| 160 | |
| 161 | func cloneAINonStream(req types.AIRequest) types.AIRequest { |
| 162 | out := req |